高仿京东下拉刷新,轻松上手!

直接进入主题,先来看一下京东的实现效果:
jd.gif
以及我自己的实现效果:
myjd.gif

实现过程

1.下拉原理
layout.png

整个布局为继承自LinearLayout的Viewgroup,分为头部及下面的列表部分,通过设置HeaderView的topMargin属性为负使HeaderView向屏幕上方偏移。
初始化时设置HeaderView的topMargin为负的HeaderView的高度可以将HeaderView完全隐藏,从而屏幕中只看得到列表部分。下拉过程中根据手指划过的距离不断更新HeaderView的topMargin值来改变HeaderView的可视范围从而达到下拉的效果。

2.效果实现

观察京东客户端的下拉过程,可以看出下拉过程中快递员和包裹是不断放大的并且透明度在增加,当HeaderView完全可见时达到最大值并且快递员“取到”包裹,松开手后快递员开始“拼命送货”。

其中放大效果我是用ScaleDrawable实现,通过手指划过的位移改变Drawable的level从而改变图片的大小,不熟悉ScaleDrawable的可以参考Android Drawable之ScaleDrawable。松开手后快递员奔跑是由帧动画实现。

3.关键代码

拦截部分:

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {    
    switch (event.getAction()) {        
        case MotionEvent.ACTION_DOWN:           
             mTouchY = event.getY();
             break; 
        case MotionEvent.ACTION_MOVE:
             float dy = event.getY() - mTouchY; 
            //当RecyclerView移到顶部并且手指向下滑动时,拦截事件,由自己处理Touch事件           
             if (dy > 0 && canPull)              
                  return true;       
        case MotionEvent.ACTION_UP:  
        default:            
             break;    
    }    
    return false;
}

滑动部分:

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_MOVE:
            float dy = event.getY() - mTouchY;
            mTouchY = event.getY();
            if (Math.abs(mTouchY)<touchSlop)
                break;
            if (mCurrentStatus != STATUS_REFRESHING) {
                //除以2是增加下拉的阻力感
                headerLayoutParams.topMargin += dy / 2;
                //此时为向上滑动到头部完全隐藏的情况,继续滑动的话应该交由RecyclerView处理了,故返回false自己不消耗事件。
                if (headerLayoutParams.topMargin<=hideHeaderHeight){
                    headerLayoutParams.topMargin=hideHeaderHeight;
                    mHeaderView.requestLayout();
                    return false;
                }
                //此时为头部完全显示的情况
                if (headerLayoutParams.topMargin>=0){
                    mCurrentStatus = STATUS_RELEASE_TO_REFRESH;
                }else {
                    mCurrentStatus = STATUS_PULL_TO_REFRESH;
                    //改变图片的大小及透明度
                    onLevelChanged((hideHeaderHeight-headerLayoutParams.topMargin)*100/hideHeaderHeight);
                }
                mHeaderView.requestLayout();
            }
            break;
        case MotionEvent.ACTION_UP:
        if (mCurrentStatus == STATUS_PULL_TO_REFRESH){
            //属性动画实现平滑滚动
           headerAnimation(headerLayoutParams.topMargin,hideHeaderHeight,350,null);
        }else if (mCurrentStatus == STATUS_RELEASE_TO_REFRESH){
            mCurrentStatus = STATUS_REFRESHING;
            headerAnimation(headerLayoutParams.topMargin,0,250,null);
            if (listener!=null)
                listener.onRefresh();
        }
        break;
    }
    updateHeaderView();
    lastStatus = mCurrentStatus;
    return super.onTouchEvent(event);
}

<br />

具体代码可以参考https://github.com/tangr2015/JDPullToRefresh

<br />
<br />

参考Android下拉刷新完全解析,教你如何一分钟实现下拉刷新功能

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 176,268评论 25 709
  • 博文出处:带你实现仿美团的下拉刷新,欢迎大家关注我的博客,谢谢! 有一段时间没更新博客了,近来都在做毕业设计,今天...
    俞其荣阅读 8,506评论 1 32
  • 自定义view之自定义下拉刷新控件 经过了之前的学习,这一次撸一个能用的:在很多app中都有下拉刷新的功能,所以这...
    Ugly_K阅读 6,481评论 1 15
  • 买了几套16开的线装竖版,发现太好读了。这不就象七肢通的语言表达一样吗,不同的语言结构应该用不同的载体: 同步并发...
    掌门_艾老师阅读 1,576评论 0 0
  • 每个孩子都有自然向上、向善的能力。 以下来自一位初三男生的故事…… 第一幕: 这像一个卫生间 ————发泄.安全...
    福州生命港湾阅读 3,848评论 1 1

友情链接更多精彩内容