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 = true;

break;

}

}

break;

case MotionEvent.ACTION_UP:

isIntercept = true;

break;

}

return isIntercept;

}

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

public static final int TOP = 0;//收缩状态

public static final int CENTER = 1;//中间状态

public static final int BOTTOM = 2;//展开状态

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

三、移动HeadView。

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

//获取不到的

break;

case MotionEvent.ACTION_MOVE:

int distant = (int) (touchY - event.getRawY());

if (getScrollY() + distant-1 < MAXY && getScrollY() + distant > 0) {

scrollTo(0,getScrollY() + distant);

}

break;

case MotionEvent.ACTION_UP:

if (getScrollY() == 0) mHeadPosition = BOTTOM;

if (getScrollY() == MAXY) mHeadPosition = TOP;

if (getScrollY() > 0 && getScrollY() < MAXY) mHeadPosition = CENTER;

if (getScrollY() > MAXY / 2) {

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

invalidate();

mHeadPosition = TOP;

}

if (getScrollY() < MAXY / 2) {

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

invalidate();

mHeadPosition = BOTTOM;

}

break;

}

return super.onTouchEvent(event);

}

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

@Override

public void computeScroll() {

super.computeScroll();

if (mScroll.computeScrollOffset()){

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

postInvalidate();

}

}

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

if (MAXY == -1)

MAXY = mHeadSecond.getMeasuredHeight();

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

@Override

protected void onFinishInflate() {

super.onFinishInflate();

int count = getChildCount();

//本粘性布局只支持ListView

if (count == 3 && getChildAt(2) instanceof ListView)

init();

}

/**

* 初始化

*/

private void init() {

//获得子元素

mHeadFiest = getChildAt(0);

mHeadSecond = getChildAt(1);

mListView = (ListView) getChildAt(2);

mListView.setOnScrollListener(this);

mScroll = new Scroller(getContext());

}

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

android 粘性view_Android自定义StickinessView粘性滑动效果相关推荐

  1. android 阅读器自动滚动,Android编程实现小说阅读器滑动效果的方法

    本文实例讲述了Android编程实现小说阅读器滑动效果的方法.分享给大家供大家参考,具体如下: 看过小说都知道小说阅读器翻页有好多种效果,比如仿真翻页,滑动翻页,等等.由于某种原因,突然想写一个简单点 ...

  2. android 齿轮动画,Android仿正点闹钟时间齿轮滑动效果

    看到正点闹钟上的设置时间的滑动效果非常好看,自己就想做一个那样的,在网上就开始搜资料了,看到网上有的齿轮效果的代码非常多,也非常难懂,我就决定自己研究一下,现在我就把我的研究成果分享给大家.我研究的这 ...

  3. Android横向滚动卡片,Android仿探探卡片式滑动效果实现

    前言 第一次进入探探软件界面,就被这种通过卡片式滑动来选择"喜欢/不喜欢"的设计所吸引了.当时就非常想通过自己来实现这种仿探探式的效果,然而却没什么思路.不过毋庸置疑的是,这种效果 ...

  4. 仿百度动态Android源码,Android 仿百度手机助手首页滑动效果

    今天看到百度手机助手首页上的滑动效果非常nice,主要功能归结为: 1.当手指上划时,顶部搜索栏随手指移动距离而缩小到隐藏,隐藏后内容还是可以继续移动 2.手指下滑时,当显示内容达到第一个时,顶部搜索 ...

  5. android view禁用,Android 禁止ViewPager的自带滑动效果

    由于最近在做墨水屏的相关工作,ViewPager自带的滑动效果在墨水屏上表现的很不好,残影太重了.所以禁止自带的滑动效果,用接口来接管相关逻辑实现自处理. import android.content ...

  6. android弹球动画,Android动画之自定义Evaluator实现弹球效果

    前言 今天给大家带来的是自定义Evaluator实现弹球效果,我们先给大家来个效果图. 下面我们介绍具体代码流程 1. 自定义Point类 public class Point { private i ...

  7. Android 自定义 HorizontalScrollView 横向滑动效果

    自从Gallery被谷歌废弃以后,Google推荐使用ViewPager和HorizontalScrollView来实现Gallery的效果.的确HorizontalScrollView可以实现Gal ...

  8. Android仿探探卡片式滑动效果实现

    第一次进入探探软件界面,就被这种通过卡片式滑动来选择"喜欢/不喜欢"的设计所吸引了.当时就非常想通过自己来实现这种仿探探式的效果,然而却没什么思路.不过毋庸置疑的是,这种效果的原理 ...

  9. Android开发之自定义Spinner样式的效果实现(源代码实现)

    android系统自带的Spinner样式是远远满足不了我们实际开发过程中对Spinner UI风格的要求,因此我们肯定需要为了切合整个应用的风格,修改我们的Spinner样式.系统给我们提供了两种常 ...

最新文章

  1. SVN更换修改用户名
  2. AJAX 一些常用方法
  3. VNX证书过期解决方案(2018-11-02)
  4. CF Round410 D. Mike and distribution
  5. ES6语法---set
  6. (73)信号发生器DDS三角波设计(一)(第15天)
  7. K - Repeating Decimals(循环小数)
  8. [从架构到设计]第一回:设计,应该多一点
  9. Java JDK动态代理Proxy类的原理是什么? - 知乎(重排版)
  10. html ztree选中状态,ztree-select.html
  11. UE4 如何导入外部插件包
  12. faster rcnn理论讲解
  13. 排序—时间复杂度为O(n2)的三种排序算法
  14. postfix搭建纯邮件转发服务器
  15. 整合xxl-job-admin动态添加xxl-job定时任务
  16. glove.840B.300d、glove.42B.300d、glove.6B网盘下载
  17. 2021-07-26记录字节“懂车帝”重庆岗一面(绝对凉)
  18. 100725B Banal Tickets
  19. 《浪潮之巅》系列疑问
  20. 前端JavaScript+HTML

热门文章

  1. 项目中获取系统的用例的基本步骤
  2. linux学习一个服务(未完)
  3. CentOS经常使用文件操作命令[百度博客搬家]
  4. 7.Reverse Integer (INT; Overflow)
  5. 交叉编译器arm-linux-gcc
  6. mysql innodb缓存策略之Buffer Pool
  7. 用O(1)的时间复杂度删除单链表中的某个节点
  8. 一个从华为离职的朋友
  9. Android bootchart(二)
  10. Python3——函数