HorizontalRefresh 一个可以左右拖动刷新的控件

前言

博主是个android程序员,最近接了不少私活在做。想写博客也一直没时间,刚好有几个项目交工了才有时间写博客。同时这也是我写的第一篇博客,因为一直以来我都是写开发笔记的。

在做项目的时候我遇到一个需求,一个横向滚动的列表要添加拖动刷新和加载的功能。本着快速开发的原则,我就在网上找别人的控件使用。然而找到一个控件只能左拉加载,却不能同时两端拖动加载。于是就自己写了。


一、先上个效果图


二、创建可以滑动的容器

1、既然是个容器那就直接继承FrameLayout,如下

public class HorizontalRefreshView extends FrameLayout {
    public HorizontalRefreshView(Context context) {
        super(context);
        init(context);
    }

    public HorizontalRefreshView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.attrs = attrs;
        init(context);
    }
}

2、添加左右两边的的拖动展示控件

leftView = new MoreView(context);
leftView.setId(leftViewId);
leftView.setIsStats(1);
leftView.setText(text1, text2);
leftView.setBgColor(bgColor);

rightView = new MoreView(context);
rightView.setId(rightViewId);
rightView.setIsStats(2);
rightView.setText(text1, text2);
rightView.setBgColor(bgColor);

LayoutParams params = new LayoutParams((int) maxW, -1);
addView(leftView, params);
params = new LayoutParams((int) maxW, -1);
addView(rightView, params);

3、控件是添加进入了,但是还是需要计算控件的位置和控件如何摆放

    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        this.r = r;
        b = b - t;
        this.b = b;
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View childAt = getChildAt(i);
            if (childAt.getId() == leftViewId) {//左边
                childAt.layout(0, 0, 0, b);//将控件宽度设置为0
            } else if (childAt.getId() == rightViewId) {
                childAt.layout(r, 0, 0, b);
            } else {
                mChildView = childAt;//获取其中要滚动的view,可以是listview
            }
        }
    }
我将两个控件分别放在一左一右,childAt.layout(0, 0, 0, b);从这可以看出,我将控件的展示宽度设置成0px,后面拖动时就可以改变其宽度。

4、拦截触摸事件

  public boolean onInterceptTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                ox = event.getX();//按下时的位置
                break;
            case MotionEvent.ACTION_MOVE:
                float x = event.getX();
                x = ox - x;//计算移动手指的偏移
                if (x > 0 && !canScrollLeft()) {//判断是否可以向左滑
                    scrollStats = 2;
                    return true;
                } else if (x < 0 && !canScrollRight()) {//判断是否可以向右滑
                    scrollStats = 1;
                    return true;
                }
        }
        return super.onInterceptTouchEvent(event);
    }

5、监听事件并改变控件宽度

public boolean onTouchEvent(MotionEvent event) {//事件监听
        if (scrollStats != 0)
            switch (event.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    float x = event.getX();
                    if (oldX == 0) oldX = x;//第一次监听到移动
                    else {//计算移动偏移
                        scrollW = oldX - x;
                        ViewHelper.setTranslationX(mChildView, -scrollW);//平移控件
                        Log.v("--scrollW--", "" + scrollW);
                        Log.v("--scrollStats--", "" + scrollStats);
                        float scrollW = Math.abs(this.scrollW);
                        //显示左右的提示控件
                        if (scrollStats == 1) {
                            leftView.layout(0, 0, (int) (scrollW > maxW ? maxW : scrollW), b);
                            leftView.setShowStats(scrollW > maxW ? 2 : 1);
                        } else if (scrollStats == 2) {
                            rightView.layout((int) (r - (scrollW > maxW ? maxW : scrollW)), 0, r, b);
                            rightView.setShowStats(scrollW > maxW ? 2 : 1);
                        }
                    }
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    //结束滑动
                    oldX = 0;
                    //开启动画
                    startAnim();
                    Log.v("--ACTION_UP--", "ACTION_UP");
                    //触发监听事件
                    float scrollW = Math.abs(this.scrollW);
                    if (onHorizontalRefresh != null && scrollW > maxW) {
                        if (scrollStats == 1) onHorizontalRefresh.OnLeftRefresh(this);
                        else onHorizontalRefresh.OnRightRefresh(this);
                    }
                    return true;
            }
        return super.onTouchEvent(event);
    }

到此这个控件基本上就可以做完了,其中的MoreView 就是拖动出来展示的控件,这个控件可以自己随意更换展示,并不会有什么影响。其实也没什么好说的,注释里写的还是很明白的。篇幅有限,就讲到这了。附上源码地址:https://github.com/cookieci/HorizontalRefresh/




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章