公司项目,需要用到ScrollView的下拉刷新,一开始使用的时候PullToRefresh三方库的下拉刷新,我比较纠结第三档库,很强大,但是,公司项目的需求,PullToRefresh就不能做到了,改来改去的还是自己写一个下拉刷新比较靠谱,很多东西能够自己去控制。效果图就不上传了。直接解释关键代码。
ScrollView的下拉刷新比ListView的好做多了。

因为ScroTo的性质,ScrollView的下拉刷新,需要在外部添加一个父布局,通过父布局来控制触摸手势时候下传,什么时候下拉。
我自定义了一个PullScrollView 

public class PullScrollView extends RelativeLayout   


public PullScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }
    
    public PullScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }
    
    public PullScrollView(Context context) {
        super(context);
        init(context);
    }
    
    private Scroller mScroller ;
    private int mTouchSlop ;
    private void init(Context context){
        
         ViewConfiguration configuration = ViewConfiguration.get(getContext());
         mTouchSlop = configuration.getScaledTouchSlop();
        mScroller = new Scroller(context, new DecelerateInterpolator());

}  


首先是初始化mTouchSlop  是触摸手势滑动的最小像素值,也就是说滑动多少的距离才算是手势滑动,这样可以防止手势一点点的移动就引起的滑动事件。
mScroller  是用来处理平滑滚动的。之前的博客有介绍。

第二点:
@Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        if (getChildCount() > 2) {
            throw new RuntimeException("子孩子只能有两个");
        }
        bottomView = (ViewGroup) getChildAt(0);
        contentView = (ScrollView) getChildAt(1);

}  


在布局初始化结束之后,得到布局中的两个子孩子,为啥只能有两个孩子那?? BottomView是用来下拉刷新展示的View  contentView 就是我们的ScrollView了。如果子孩子多了,怎么知道哪个VIew是需要被隐藏的?所以只处理两个View的情况,当然,如果还有上拉加载更多,就需要三个子孩子了。


第三:

@Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        bottomHeight = getBottomViewHeight() ; 
        Log.i("Test", l + "ceshi" + " t="+t + " r"+r + " b=" + b + " height= "   + bottomHeight);
        bottomView.layout(l, - bottomHeight, r, t);
        contentView.layout(l, 0, r, b);

}  

onLayout,做过自定义的都应该很熟悉这个方法,放置子孩子位置的一个方法,因为我们需要有一个子孩子隐藏掉,当我们需要它显示的时候才去显示,所以  需要手动的去将BottomView放到布局-hight到0的位置,这样下拉的时候才能显示出来。

第四:
@Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        
        if (getScrollY() < 0 ) {
            return true ;
        }
        
        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            startY = (int) ev.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            int moveY = (int) ev.getY();
            int delayY = moveY - startY ;
            Log.i("Test", delayY + " =  " + mTouchSlop) ;
            if (getTopPosition() && delayY > mTouchSlop) {
                ev.setAction(MotionEvent.ACTION_DOWN);
                return true ;
            }
            break ;
        case MotionEvent.ACTION_UP:
            
            break;
        }
        return super.onInterceptTouchEvent(ev);

}  


手势的拦截动作,通过getTopPosition()方式,来判断ScrollView时候处于下拉需要显示隐藏子View的状态,delayY > mTouchSlop 是用来判断是不是下拉的动作的。 如果符合条件  我们就需要将手势拦截掉,return true。
为什么我觉得ScrollView做下来刷新比较好做那? 就是因为ScrollView的判断比较好判断。

private boolean getTopPosition(){
        if (contentView.getScrollY() <= 0 ) {
            return true ;
        }
        return false ;
    }

是不是很简单!!!!


第五:
@Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            startY = (int) event.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            int delayY = (int) (event.getY() - startY) ;
            if (getTopPosition() && getScrollY() <= 0 ) {
                pullMove((int) (-delayY * 0.8));  // 跟随手势滑动
            }
            startY = (int) event.getY();
            return true ;
        case MotionEvent.ACTION_UP:
            int scrollY = getScrollY();
            if (state == PullState.ON_REFRESH && scrollY < 0 && Math.abs(scrollY) > bottomHeight) {
                restView(-getScrollY() - bottomHeight);  // 回弹到下拉刷新的状态
                return true ;
            }else if (state == PullState.ON_REFRESH && scrollY < 0 && Math.abs(scrollY) < bottomHeight) {
                return true ;
            }
            if (scrollY < 0  &&  Math.abs(scrollY) < bottomHeight ) {
                returnView(); // 回弹到原来的位置。
            }else if (scrollY < 0 && Math.abs(scrollY) > bottomHeight  && state != PullState.ON_REFRESH) {
                if (onreListener != null) {
                    state = PullState.ON_REFRESH ;
                    onreListener.refresh();  // 回调函数
                }
                restView(-getScrollY() - bottomHeight);
            }
            break;
        }
        return true ;

}  

这个就是做移动的处理手势的方法了。

ScrollView的下拉刷新比起Listview ,要好做的多了。哈哈………………  
下面是源码附上,用做学习之用。代码还有不完善之处,等我项目完成之后,我会把项目中的封装很完善的下拉刷新代码重新打包上传。

下载地址:  http://pan.baidu.com/s/1jG67mzc 




Android自定义之ScrollView下拉刷新的更多相关文章

  1. Android仿苹果版QQ下拉刷新实现(二) ——贝塞尔曲线开发"鼻涕"下拉粘连效果

    前言 接着上一期Android仿苹果版QQ下拉刷新实现(一) ——打造简单平滑的通用下拉刷新控件 的博客开始,同样,在开始前我们先来看一下目标效果: 下面上一下本章需要实现的效果图: 大家看到这个效果 ...

  2. Android仿苹果版QQ下拉刷新实现(一) ——打造简单平滑的通用下拉刷新控件

    前言: 忙完了结婚乐APP的开发,终于可以花一定的时间放在博客上了.好了,废话不多说,今天我们要带来的效果是苹果版本的QQ下拉刷新.首先看一下目标效果以及demo效果:      因为此效果实现的步骤 ...

  3. Android—自定义控件实现ListView下拉刷新

    这篇博客为大家介绍一个android常见的功能——ListView下拉刷新(参考自他人博客,网址忘记了,阅读他的代码自己理解注释的,希望能帮助到大家): 首先下拉未松手时候手机显示这样的界面: 下面的 ...

  4. android 引用 project以及下拉刷新开源类库Android-PullToRefresh 的使用

    Android-PullToRefresh 是一个github上的开源下拉刷新类库, GitHub  .此外,该作者还有另外一个实用度和关注量极高的项目–另一种Android ActionBar的实现 ...

  5. Swift 自定义炫酷下拉刷新效果

    先来看下效果 下拉刷新 其实下拉刷新没大家想得那么难.本文已第二个为例子.给大家讲解下下拉刷新的做法(完整代码后面会放上) 首先,先搞一个single View Application .然后进Mai ...

  6. Android实现RecyclerView的下拉刷新和上拉载入很多其它

    需求 先上效果图, Material Design风格的下拉刷新和上拉载入很多其它. 源代码地址(欢迎star) https://github.com/studychen/SeeNewsV2 假设对于 ...

  7. 自定义ListView实现下拉刷新,下拉加载的功能

    package com.loaderman.myrefreshlistviewdemo; import android.content.Context; import android.util.Att ...

  8. android SwipeRefreshLayout google官方下拉刷新控件

    下拉刷新功能之前一直使用的是XlistView很方便我前面的博客有介绍 SwipeRefreshLayout是google官方推出的下拉刷新控件使用方法也比较简单 今天就来使用下SwipeRefres ...

  9. Android PullToRefresh (GridView 下拉刷新上拉加载)

    做这个需要自己去git hub上下载个pull-to-refresh 里面有个library为依赖包自己导到自己的项目中 (下载地址:https://github.com/chrisbanes/And ...

随机推荐

  1. linux系统下的日志,此日志对于系统安全来说是非常重要的一 个机制!!

    var/log/messages /etc/logrotate.conf 日志切割配置文件 (参考https://my.oschina.net/u/2000675/blog/908189) dmesg ...

  2. 12C GI + 11g DB 环境中PSU安装

    环境说明: 12.1.0.2的GI集群,11.2.0.4的RAC数据库,需要安装最新的补丁. 补丁下载: 12.1.0.2 GI的PSU:11.2.0.4 DB的PSU:OJVM For 11.2.0 ...

  3. tornado 06 数据库—ORM—SQLAlchemy——基本内容及操作

    tornado 06 数据库—ORM—SQLAlchemy——基本内容及操作 一. ORM #在服务器后台,数据是要储存在数据库的,但是如果项目在开发和部署的时候,是使用的不同的数据库,该怎么办?是不 ...

  4. tornado 09 cookie和session

    tornado 09 cookie和session 一.cookie #有什么办法能够让浏览器记住登录信息,下次再打开的时候可以自动登录?网站是如何记录登录信息的? class SetCookieHa ...

  5. rest-assured的对象映射(序列化和反序列化)

    rest-assured支持映射Java对象到Json和XML以及从Json和XML中映射到Java对象.Json映射需要在classpath 中有Jackson.Jackson 2或者是Gson,X ...

  6. indexOf获取字符位置

    先定义一个字符串: var aString = "you are beautiful,so beautiful,and i love you ver much"; 拿到第一个逗号的 ...

  7. c# 动态生成继承类并实现序列化特性

    项目来源 App传过来的字段是动态的,希望能保证扩展性,返回时,把所需要的字段与数据融合后再返回过去 数据是第3方来源的,但是序列化后的结果又希望能并列返回 如:App传过来 一个设备Id,客户Id等 ...

  8. jar 启动关闭

    1.后台启动 startTest.sh #设置工程路径project_path=/root/testcd $project_path#nohup后台启动,输出日志到test.lognohup java ...

  9. 1.rabbitmq 集群版安装及使用nginx进行四层负载均衡设置

    1.安装erlang 需要注意erlang的版本是否满足rabbitmq的需求 这里用到的版本是:Erlang 19.0.4   RabbitMQ 3.6.15 wget http://www.rab ...

  10. spring初始化bean的目的

    初始化bean就是为了将所有需要的bean全部装载到容器里面,等我们需要用到哪个bean就将哪个bean从容器里面拿出来