热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

android粘性view_Android自定义StickinessView粘性滑动效果

design包的出现,Android界面发生了巨大变化,各种滑动配合的效果,下面我就粘性滑动中的一种进行自定义,效果图如下&

design包的出现,Android界面发生了巨大变化,各种滑动配合的效果,下面我就粘性滑动中的一种进行自定义,效果图如下:

大家看到效果了,这里我是继承了LinerLayout,方便一点,若果是ViewGroup的话,也就复杂一点点。这里分为三部分:

1.head1,顶部可移动的Layout。

2.head2,固定的头部,不会滑动除屏幕外。

3.可滑动的Layout(这里只可以是ListView,不过也可以是任何可滑动的View,只要给出Head可滑动的时机即可)

本StickinessView的难点在于,解决滑动冲突和事件的拦截处理,接下来我一一道来。

一、首先,要确定HeadLayout什么时候可以拦截事件,那么就要确定ListView到达顶部和底部的时机。

@Override

public void onScroll(AbsListView view,int firstVisibleItem,int visibleItemCount,int totalItemCount) {

View v = mListView.getChildAt(0);

//当firstItem的top为0的时候就认为已经到达ListView的顶部了

if (mListView.getChildCount() > 0 && firstVisibleItem == 0) {

//滑动到顶部

if (v.getTop() == 0) {

//滑动到顶部了

isListViewTop = true;

} else {

isListViewBottom = false;

}

}else if (mListView.getChildCount()>0&&firstVisibleItem+visibleItemCount==totalItemCount){

final View bottomChildView = mListView.getChildAt(mListView.getChildCount()-1);

//当最后一个itemView的bottom>=ListView的高度的时候,那么就认为到达底部了

if (mListView.getHeight()>=bottomChildView.getBottom()){

isListViewBottom = true;

}else {

isListViewBottom = false;

}

}else {

isListViewBottom = false;

isListViewTop = false;

}

原因很简单,因为View的getTop和getBottom方法是相对父容器的位置,熟悉Layout方法的,想必就会很明白了。

二、知道了HeadView拦截事件的时机,我们就要搞清楚在此基础之上,我们到底啥时候拦击点击事件,进行滑动。

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

switch (ev.getAction()) {

case MotionEvent.ACTION_DOWN:

touchY = ev.getRawY();

isIntercept = false;

break;

case MotionEvent.ACTION_MOVE:

float distant = ev.getRawY() - touchY;

if (isListViewTop) {

switch (mHeadPosition) {

case TOP:

if (distant > 0) isIntercept = true;

break;

case CENTER:

isIntercept = true;

break;

}

}

if (isListViewBottom){

switch (mHeadPosition) {

case CENTER:

isIntercept = true;

break;

case BOTTOM:

if (distant <0) isIntercept &#61; true;

break;

}

}

break;

case MotionEvent.ACTION_UP:

isIntercept &#61; true;

break;

}

return isIntercept;

}

跟大家讲解一下onInterceptTouchEvent(MotionEvent ev),这个方法会最先调用&#xff0c;当一个事件序列拦截一次后&#xff0c;那么这个事件的后续事件动作就不会再调用该方法&#xff0c;也就是说&#xff0c;当该ViewGroup决定拦截某个事件后&#xff0c;那么它注定要消费后续的事件动作。这里贴出HeadView的位置状态

public static final int TOP &#61; 0;//收缩状态

public static final int CENTER &#61; 1;//中间状态

public static final int BOTTOM &#61; 2;//展开状态

关于细节&#xff0c;想必大家画个图就可以知道了&#xff0c;注意一点&#xff1a;在拦截事件序列的时候&#xff0c;一般ACTION_DOWN事件不可以被拦截&#xff0c;因为拦截的话&#xff0c;没得意义了&#xff0c;后续事件就无法控制了&#xff0c;不可能继续往ChildView传递事件序列。

三、移动HeadView。

&#64;Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

//获取不到的

break;

case MotionEvent.ACTION_MOVE:

int distant &#61; (int) (touchY - event.getRawY());

if (getScrollY() &#43; distant-1 0) {

scrollTo(0,getScrollY() &#43; distant);

}

break;

case MotionEvent.ACTION_UP:

if (getScrollY() &#61;&#61; 0) mHeadPosition &#61; BOTTOM;

if (getScrollY() &#61;&#61; MAXY) mHeadPosition &#61; TOP;

if (getScrollY() > 0 && getScrollY()

if (getScrollY() > MAXY / 2) {

mScroll.startScroll(0,getScrollY(),MAXY-getScrollY(),100);

invalidate();

mHeadPosition &#61; TOP;

}

if (getScrollY()

mScroll.startScroll(0,-getScrollY(),100);

invalidate();

mHeadPosition &#61; BOTTOM;

}

break;

}

return super.onTouchEvent(event);

}

这里为了使得滑动跟家顺畅我使用了Scroller这个类&#xff0c;该类是专门处理弹性滑动的工具类&#xff0c;先初始化构造器&#xff0c;在调用startScroll()方法(其中四个参数&#xff1a;滑动的x,滑动的y,滑动x的偏移量&#xff0c;滑动y的偏移量)&#xff0c;然后刷新视图&#xff0c;最后重写computeScroll()方法&#xff0c;

&#64;Override

public void computeScroll() {

super.computeScroll();

if (mScroll.computeScrollOffset()){

scrollTo(mScroll.getCurrX(),mScroll.getCurrY());

postInvalidate();

}

}

好了&#xff0c;基本完成&#xff0c;我们还要第一时间获取HeadView的高度&#xff0c;那么在onMeasure()中获取比较好&#xff0c;并且只获取一次如下

if (MAXY &#61;&#61; -1)

MAXY &#61; mHeadSecond.getMeasuredHeight();

在onFinishInflate()方法中&#xff0c;该方法的执行标志着所有的View都已经add完毕&#xff0c;这里我们进行初始化是比较妥当的。

&#64;Override

protected void onFinishInflate() {

super.onFinishInflate();

int count &#61; getChildCount();

//本粘性布局只支持ListView

if (count &#61;&#61; 3 && getChildAt(2) instanceof ListView)

init();

}

/**

* 初始化

*/

private void init() {

//获得子元素

mHeadFiest &#61; getChildAt(0);

mHeadSecond &#61; getChildAt(1);

mListView &#61; (ListView) getChildAt(2);

mListView.setOnScrollListener(this);

mScroll &#61; new Scroller(getContext());

}

以上就是本文的全部内容&#xff0c;希望对大家的学习有所帮助&#xff0c;也希望大家多多支持编程小技巧。



推荐阅读
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 使用圣杯布局模式实现网站首页的内容布局
    本文介绍了使用圣杯布局模式实现网站首页的内容布局的方法,包括HTML部分代码和实例。同时还提供了公司新闻、最新产品、关于我们、联系我们等页面的布局示例。商品展示区包括了车里子和农家生态土鸡蛋等产品的价格信息。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 十大经典排序算法动图演示+Python实现
    本文介绍了十大经典排序算法的原理、演示和Python实现。排序算法分为内部排序和外部排序,常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。文章还解释了时间复杂度和稳定性的概念,并提供了相关的名词解释。 ... [详细]
  • 本文详细介绍了Android中的坐标系以及与View相关的方法。首先介绍了Android坐标系和视图坐标系的概念,并通过图示进行了解释。接着提到了View的大小可以超过手机屏幕,并且只有在手机屏幕内才能看到。最后,作者表示将在后续文章中继续探讨与View相关的内容。 ... [详细]
  • android 触屏处理流程,android触摸事件处理流程 ? FOOKWOOD「建议收藏」
    android触屏处理流程,android触摸事件处理流程?FOOKWOOD「建议收藏」最近在工作中,经常需要处理触摸事件,但是有时候会出现一些奇怪的bug,比如有时候会检测不到A ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
author-avatar
理想压力正比_635
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有