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/




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