支持listview、GridView、普通布局、scrollview和viewpager的下拉刷新控件

来源:互联网 发布:极品飞车17截图软件 编辑:程序博客网 时间:2024/04/27 18:27

支持listview、GridView、scrollview和viewpager的下拉刷新(经测试未发现bug),但是不支持viewpager中嵌套listview、GridView等可上下滑动组件的情况,本来想作支持的,但是鉴于viewpager的嵌套的可能性太过复杂,最后还是放弃了。以下为scrollview刷新效果图


用法如下:

1.布局文件如下,只需将需要刷新效果的控件包裹在该控件中即可,注意只能有一个子控件,如果使用普通布局的情况,可使用布局进行包裹。

<com.zp.scrolltest.RefreshView        android:layout_width="match_parent"        android:layout_height="match_parent"        android:id="@+id/refresh_view">        <!--<GridView-->            <!--android:layout_width="match_parent"-->            <!--android:layout_height="match_parent"-->            <!--android:numColumns="1"-->            <!--android:visibility="gone"-->            <!--android:id="@+id/grid_view"/>-->        <!--<ListView-->            <!--android:layout_width="match_parent"-->            <!--android:layout_height="match_parent"-->            <!--android:background="#ff9900"-->            <!--android:id="@+id/list_view"-->            <!--android:visibility="gone"-->            <!--android:text="content"/>-->        <ScrollView            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:background="#00ff00">            <LinearLayout                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:orientation="vertical">                <TextView                    android:layout_width="wrap_content"                    android:layout_height="300dp"                    android:text="hhhhhhh"/>                <TextView                    android:layout_width="wrap_content"                    android:layout_height="300dp"                    android:text="hhhhhhh"/>                <TextView                    android:layout_width="wrap_content"                    android:layout_height="300dp"                    android:text="hhhhhhh"/>                <TextView                    android:layout_width="wrap_content"                    android:layout_height="300dp"                    android:text="hhhhhhh"/>            </LinearLayout>        </ScrollView>        <!--<LinearLayout-->            <!--android:layout_width="match_parent"-->            <!--android:layout_height="wrap_content"-->            <!--android:orientation="vertical">-->            <!--<TextView-->                <!--android:layout_width="wrap_content"-->                <!--android:layout_height="300dp"-->                <!--android:text="hhhhhhh"/>-->        <!--</LinearLayout>-->    </com.zp.scrolltest.RefreshView>

Java代码中使用:

refresh_view = (RefreshView)findViewById(R.id.refresh_view);        refresh_view.setOnRefshing(new RefreshView.OnRefshing() {            @Override            public void refresh() {//                Toast.makeText(MainActivity.this, "hahah you are me", Toast.LENGTH_SHORT).show();            }        });        refresh_view.setTime("2017-1-9 12:12:56");

可对刷新事件进行监听,可设置刷新时间(如果不设置则不显示该效果),可手动触发刷新(startRefresh())和停止刷新效果(stopRefresh())。


源码如下:

package com.zp.scrolltest;import android.content.Context;import android.os.Handler;import android.os.Message;import android.support.v4.view.ViewPager;import android.util.AttributeSet;import android.util.Log;import android.view.Gravity;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.widget.GridView;import android.widget.LinearLayout;import android.widget.ListView;import android.widget.ProgressBar;import android.widget.ScrollView;import android.widget.Scroller;import android.widget.TextView;import java.util.Calendar;/** * Created by ez on 2017/5/8. */public class RefreshView extends LinearLayout {    TextView status_tv, refresh_time;    ProgressBar progressBar;    Context context;    float lastY;    int SCREEN_HEIGHT;    Scroller scroller;    int mHeight = 200;    public static final int PREPARE = 0;    public static final int WILLREFRESH = 1;    public static final int REFRESHING = 2;    public static final int END = 3;    private int status;    private int delayTime = 2000;    boolean inControl;//临界点过度控制,由listview或者其他部分下拉到顶,触发滑动效果时用到    OnRefshing onRefshing;    boolean isTopHidden;    Handler handler = new Handler(new Handler.Callback() {        @Override        public boolean handleMessage(Message msg) {            return false;        }    });    public RefreshView(Context context) {        super(context);        init(context);    }    public RefreshView(Context context, AttributeSet attrs) {        super(context, attrs);        init(context);    }    public RefreshView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(context);    }    private void init(Context context){        this.context = context;        SCREEN_HEIGHT = context.getResources().getDisplayMetrics().heightPixels;        setOrientation(VERTICAL);        LinearLayout ll = new LinearLayout(context);        ll.setOrientation(HORIZONTAL);        ll.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, mHeight));        ll.setGravity(Gravity.CENTER);        progressBar = new ProgressBar(context);        progressBar.setVisibility(View.GONE);        ll.addView(progressBar);        LinearLayout linearLayout = new LinearLayout(context);        linearLayout.setOrientation(VERTICAL);        linearLayout.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));        status_tv = new TextView(context);        LayoutParams param = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);        param.setMargins(20, 0, 30, 0);        status_tv.setLayoutParams(param);        status_tv.setText("下拉刷新");        status_tv.setTextSize(16);        status_tv.setGravity(Gravity.CENTER);        linearLayout.addView(status_tv);        refresh_time = new TextView(context);        refresh_time.setLayoutParams(param);        refresh_time.setText("刷新时间:");        refresh_time.setTextSize(12);        refresh_time.setVisibility(View.GONE);        linearLayout.addView(refresh_time);        ll.addView(linearLayout);        addView(ll);        scrollTo(0, mHeight);        scroller = new Scroller(context);        status = PREPARE;    }    public void setDelayTime(int time){        this.delayTime = time;    }    public void setOnRefshing(OnRefshing onRefshing){        this.onRefshing = onRefshing;    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        ViewGroup.LayoutParams params = getChildAt(1).getLayoutParams();        params.height = getMeasuredHeight();    }    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                lastY = ev.getY();                break;            case MotionEvent.ACTION_MOVE:                View view = getChildAt(1);                float dy = ev.getY()-lastY;                Log.e("zp", "坐标:"+ev.getY());                //作用于下面的组件滑动到最顶端,重新分发事件响应刷新动作                if(dy>0){                    if(view instanceof ListView){                        ListView lv = (ListView)view;                        View c = lv.getChildAt(lv.getFirstVisiblePosition());                        if(c!=null && c.getTop()==0 && !inControl){                            inControl = true;                            ev.setAction(MotionEvent.ACTION_CANCEL);                            MotionEvent ev2 = MotionEvent.obtain(ev);                            dispatchTouchEvent(ev);                            ev2.setAction(MotionEvent.ACTION_DOWN);                            return dispatchTouchEvent(ev2);                        }                    }else if(view instanceof ScrollView){                        ScrollView sv = (ScrollView)view;                        if(sv.getScrollY()==0 && !inControl){                            inControl = true;                            ev.setAction(MotionEvent.ACTION_CANCEL);                            MotionEvent ev2 = MotionEvent.obtain(ev);                            dispatchTouchEvent(ev);                            ev2.setAction(MotionEvent.ACTION_DOWN);                            return dispatchTouchEvent(ev2);                        }                    }else if(view instanceof GridView){                        GridView gv = (GridView)view;                        View c = gv.getChildAt(gv.getFirstVisiblePosition());                        if(c!=null && c.getTop()==0 && !inControl){                            inControl = true;                            ev.setAction(MotionEvent.ACTION_CANCEL);                            MotionEvent ev2 = MotionEvent.obtain(ev);                            dispatchTouchEvent(ev);                            ev2.setAction(MotionEvent.ACTION_DOWN);                            return dispatchTouchEvent(ev2);                        }                    }                }                break;        }        return super.dispatchTouchEvent(ev);    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        switch (ev.getAction()){            case MotionEvent.ACTION_DOWN:                break;            case MotionEvent.ACTION_MOVE:                View view = getChildAt(1);                float dy = ev.getY()-lastY;                Log.e("zp", "坐标1:"+ev.getY());                //下拉且下面组件为顶端时,阻断事件向下层传递,直接触发本身的touch事件                if(dy>0){                    if(view instanceof ListView){                        ListView lv = (ListView)view;                        View c = lv.getChildAt(lv.getFirstVisiblePosition());                        if(c!=null && c.getTop()==0 && inControl){                            return true;                        }                    }else if(view instanceof ScrollView){                        ScrollView sv = (ScrollView)view;                        if(sv.getScrollY()==0  && inControl){                            return true;                        }                    }else if(view instanceof GridView){                        GridView gv = (GridView)view;                        View c = gv.getChildAt(gv.getFirstVisiblePosition());                        if(c!=null && c.getTop()==0 && inControl){                            return true;                        }                    }else if(view instanceof ViewPager){                        return true;                    }                }                break;        }        return super.onInterceptTouchEvent(ev);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()){            case MotionEvent.ACTION_DOWN:                status = PREPARE;                return true;            case MotionEvent.ACTION_MOVE:                //加入判断,防止多次刷新,同时也不影响界面的滑动                if(status!=REFRESHING){                    float disY = event.getY()-lastY;                    lastY = event.getY();                    Log.e("zp", "坐标2:"+event.getY());                    int ty = getScrollY();                    scrollBy(0, -(int)disY/2);                    if(getScrollY()<10){                        status_tv.setText("松开手刷新");                        status = WILLREFRESH;                    }else{                        status_tv.setText("下拉刷新");                        status = PREPARE;                    }                    //作用于刷新动作上滑取消,重新分发事件,响应下面组件的滑动效果                    if(disY<0 && mHeight == getScrollY()){                        event.setAction(MotionEvent.ACTION_DOWN);                        dispatchTouchEvent(event);                        inControl = false;                    }                }                break;            case MotionEvent.ACTION_UP:                if(status==PREPARE){                    scroller.startScroll(0, getScrollY(), 0, mHeight-getScrollY(), 200);                    status_tv.setText("下拉刷新");                    status = END;                }                else if(status == WILLREFRESH){                    status = REFRESHING;                    scroller.startScroll(0, getScrollY(), 0, -getScrollY(), 200);                    progressBar.setVisibility(View.VISIBLE);                    status_tv.setText("正在刷新...");                    if(onRefshing!=null){                        onRefshing.refresh();                    }                    handler.postDelayed(new Runnable() {                        @Override                        public void run() {                            stopRefresh();                        }                    }, delayTime);                }                inControl = false;                break;            case MotionEvent.ACTION_CANCEL:                if(scroller.isFinished()){                    scroller.abortAnimation();                }                break;        }        return super.onTouchEvent(event);    }    @Override    public void computeScroll() {        if (scroller.computeScrollOffset()) {            scrollTo(0, scroller.getCurrY());        }        invalidate();    }    /**     * scrollBy最终还是依靠scrollTo实现,这里的条件可以屏蔽上滑导致整个页面往上走,下面出现空白     * 便于处理事件的重新分发过程     * @param x     * @param y     */    @Override    public void scrollTo(int x, int y) {        if (y > mHeight) {            y = mHeight;        }        if (y != getScrollY()) {            super.scrollTo(x, y);        }        isTopHidden = getScrollY() == mHeight;    }    private String getTime(){        Calendar calendar=Calendar.getInstance();        return "上次刷新:"+calendar.get(Calendar.MONTH)+"-"+calendar.get(Calendar.DAY_OF_MONTH)+" "+calendar.get(Calendar.HOUR_OF_DAY)+":"+calendar.get(Calendar.MINUTE)+":"+calendar.get(Calendar.SECOND);    }    public void setTime(String time){        refresh_time.setVisibility(View.VISIBLE );        refresh_time.setText(time);    }    public void startRefresh(){        if(status!=REFRESHING){            status = REFRESHING;            scroller.startScroll(0, getScrollY(), 0, -getScrollY(), 200);            status_tv.setText("正在刷新...");            progressBar.setVisibility(View.VISIBLE);            if(onRefshing!=null){                onRefshing.refresh();            }            handler.postDelayed(new Runnable() {                @Override                public void run() {                    stopRefresh();                }            }, delayTime);        }    }    public void stopRefresh(){        if(status==REFRESHING){            progressBar.setVisibility(View.GONE);            scroller.startScroll(0, getScrollY(), 0, mHeight-getScrollY(), 200);            status_tv.setText("下拉刷新");            status = END;            handler.removeCallbacksAndMessages(null);        }    }    public interface OnRefshing{        void refresh();    }}

0 0
原创粉丝点击