android listview下拉刷新

原来android里面写个下拉刷新时这么难的....

总体思路是要定义两个控件, 一个是ViewGroup控件, 一个是listview控件, 自定义的ViewGroup包裹着listview, 以方便对其进行控制

效果图和比较长的代码...


布局:

<com.lin.pulltorefresh.PullRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pull_refresh_layout"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <include layout="@layout/pull_refresh_head"/>

    <com.lin.pulltorefresh.PullRefreshListview
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <include layout="@layout/pull_refresh_foot"/>

</com.lin.pulltorefresh.PullRefreshLayout>

MainActivity.java:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ListView listView= (ListView) findViewById(R.id.list_view);
        listView.setAdapter(new MyAdapter(this.getApplicationContext()));
        //
        final PullRefreshLayout pullRefreshLayout= (PullRefreshLayout) findViewById(R.id.pull_refresh_layout);
        final Handler handler=new Handler();
        final Runnable failRunnale=new Runnable() {
            @Override
            public void run() {
                pullRefreshLayout.notifyFail();
            }
        };
        final Runnable successRunnale=new Runnable() {
            @Override
            public void run() {
                pullRefreshLayout.notifySuccess();
            }
        };
        pullRefreshLayout.setListener(new PullRefreshLayout.PullListener() {
            @Override
            public void refresh() {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            handler.post(failRunnale);
                        }
                        handler.post(successRunnale);
                    }
                }).start();
            }

            @Override
            public void loadMore() {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            handler.post(failRunnale);
                        }
                        handler.post(successRunnale);
                    }
                }).start();
            }
        });
    }
    class MyAdapter extends BaseAdapter{

        int size=32;
        LayoutInflater lf;
        ArrayList<String> datas=new ArrayList<>(size);
        public MyAdapter(Context context){
            for (int i=0;i<size;i++) datas.add("data id: "+i);
            lf=LayoutInflater.from(context);
        }
        @Override
        public int getCount() {
            return size;
        }
        @Override
        public Object getItem(int position) {
            return null;
        }
        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView==null){
                convertView=lf.inflate(R.layout.item_adapter,parent,false);
            }
            TextView tv= (TextView) convertView.findViewById(R.id.text);
            tv.setText(datas.get(position));
            return convertView;
        }
    }
}

PullRefreshListview.java
public class PullRefreshListview extends ListView implements PullWidget{
    public PullRefreshListview(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean canPullDown() {
        if (getCount()==0) {
            return true;
        }
        if (getFirstVisiblePosition()==0&&getChildAt(0).getTop()>=0){
            return true;
        }
        return false;
    }

    @Override
    public boolean canPullUp() {

        if (getCount()==0) {
            return true;
        }
        View lastView=getChildAt(getLastVisiblePosition()-getFirstVisiblePosition());
        if (getLastVisiblePosition()==getCount()-1&&lastView.getBottom()<=getMeasuredHeight()){
            return true;
        }
        return false;
    }
}

(最复杂的, 主要是因为有太多情况要判断了)PullRefreshLayout.java
public class PullRefreshLayout extends RelativeLayout {

    ViewGroup headView,footView;
    View pullTarget;
    ProgressBar headProgBar,footProgBar;
    TextView headText,footText;
    TextView headTimeText,footTimeText;
    ImageView headIcon,footIcon;
    PullListener mListener;
    //config
    int pullDonwDist,pullUpDist;
    int speed;
    int downY;
    int headHeight,footHeight;
    boolean first=true;
    int state;
    final static int READY_REFRESHING=0,READY_LOAGMOREING=1,
            NORMAL=2,REFRESHING=31,LOADING=32,RESET=4,SUCCESS=5,
            FAIL=6,WAITING=7;
    Handler mHandler;
    Handler timeHandler;
    int duration=300;
    private int fps=60;
    //date
    long preRefreshTime=0,preLoadTime=0;
    RotateAnimation rotateAnimation1=new RotateAnimation(0,180f,
            Animation.RELATIVE_TO_SELF, 0.5f,
            Animation.RELATIVE_TO_SELF, 0.5f);
    RotateAnimation rotateAnimation2=new RotateAnimation(180,0f,
            Animation.RELATIVE_TO_SELF, 0.5f,
            Animation.RELATIVE_TO_SELF, 0.5f);
    public PullRefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        state=NORMAL;
        rotateAnimation1.setDuration(200);
        rotateAnimation1.setFillAfter(true);
        rotateAnimation2.setDuration(200);
        rotateAnimation2.setFillAfter(true);
        preRefreshTime=preLoadTime=System.currentTimeMillis();
        mHandler=new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (state==RESET||state==SUCCESS||state==FAIL){
                    if (pullDonwDist>0){
                        pullDonwDist=pullDonwDist-speed>0?pullDonwDist-speed:0;
                    }else if (pullUpDist<0){
                        pullUpDist=pullUpDist+speed<0?pullUpDist+speed:0;
                    }
                    requestLayout();
                    if (pullDonwDist!=0||pullUpDist!=0){
                        sendEmptyMessageDelayed(0,duration/fps);
                    }else{
                        state=NORMAL;
                    }
                }
                else if (state==REFRESHING){
                    if (pullDonwDist>headHeight){
                        pullDonwDist=pullDonwDist-speed>headHeight?pullDonwDist-speed:headHeight;
                    }
                    requestLayout();
                    if (pullDonwDist!=headHeight){
                        sendEmptyMessageDelayed(0,duration/fps);
                    }
                }
                else if (state==LOADING){
                    if (pullUpDist<-footHeight){
                        pullUpDist=pullUpDist+speed<-footHeight?pullUpDist+speed:-footHeight;
                    }
                    requestLayout();
                    if (pullUpDist!=-footHeight){
                        sendEmptyMessageDelayed(0,duration/fps);
                    }
                }
            }
        };
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (first){
            first=false;
            headView= (ViewGroup) getChildAt(0);
            footView= (ViewGroup) getChildAt(2);
            //init head
            headIcon= (ImageView) headView.findViewById(R.id.icon);
            headProgBar= (ProgressBar) headView.findViewById(R.id.progress_bar);
            headText= (TextView) headView.findViewById(R.id.text);
            headTimeText= (TextView) headView.findViewById(R.id.time_text);
            headHeight=headView.getMeasuredHeight();
            //init foot
            footIcon= (ImageView) footView.findViewById(R.id.icon);
            footProgBar= (ProgressBar) footView.findViewById(R.id.progress_bar);
            footText= (TextView) footView.findViewById(R.id.text);
            footTimeText= (TextView) footView.findViewById(R.id.time_text);
            footHeight=footView.getMeasuredHeight();
            //init target
            pullTarget=getChildAt(1);
            //
            timeHandler=new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    if (state==REFRESHING){
                        preRefreshTime=System.currentTimeMillis();
                    }else if (state==LOADING){
                        preLoadTime=System.currentTimeMillis();
                    }
                    else{
                        headTimeText.setText("上次刷新时间: "+(System.currentTimeMillis()-preRefreshTime)/1000+"秒");
                        footTimeText.setText("上次刷新时间: "+(System.currentTimeMillis()-preLoadTime)/1000+"秒");
                    }
                    sendEmptyMessageDelayed(0,1000);
                }
            };
            timeHandler.sendEmptyMessage(0);
        }

        int dist=pullDonwDist+pullUpDist;
        headView.layout(
                0,
                -headView.getMeasuredHeight()+dist,
                headView.getMeasuredWidth(),
                0+dist);
        pullTarget.layout(
                0,
                0+dist,
                pullTarget.getMeasuredWidth(),
                pullTarget.getMeasuredHeight()+dist);
        footView.layout(
                0,
                pullTarget.getMeasuredHeight()+dist,
                footView.getMeasuredWidth(),
                pullTarget.getMeasuredHeight()+footView.getMeasuredHeight()+dist);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (state==LOADING||state==RESET||state==SUCCESS||state==FAIL){
            return super.dispatchTouchEvent(ev);
        }
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                downY= (int) ev.getRawY();
                pullDonwDist=pullUpDist=0;
                break;
            case MotionEvent.ACTION_MOVE:
                int moveY= (int) ev.getRawY();
                int dist=moveY-downY;
                if (((PullWidget)pullTarget).canPullDown()&&dist>=0){
                    pullDonwDist=dist/2;
                    pullUpDist=0;
                    if (pullDonwDist>=headHeight){
                        if (state!=READY_REFRESHING){
                            state=READY_REFRESHING;
                            headIcon.startAnimation(rotateAnimation1);
                            headText.setText("松开刷新..");
                        }
                    }else{
                        if (state!=NORMAL){
                            headIcon.startAnimation(rotateAnimation2);
                            headText.setText("下拉刷新");
                            state=NORMAL;
                        }
                    }
                }else if (((PullWidget)pullTarget).canPullUp()&&dist<=0){
                    pullDonwDist=0;
                    pullUpDist=dist/2;
                    if (-pullUpDist>=footHeight){
                        if (state!=READY_LOAGMOREING){
                            state=READY_LOAGMOREING;
                            footIcon.startAnimation(rotateAnimation1);
                            footText.setText("松开加载更多..");
                        }
                    }else{
                        if (state!=NORMAL){
                            footIcon.startAnimation(rotateAnimation2);
                            footText.setText("上拉刷新");
                            state=NORMAL;
                        }
                    }
                }else{
                    pullDonwDist=pullUpDist=0;
                    return super.dispatchTouchEvent(ev);
                }
                requestLayout();
                return true;
            case MotionEvent.ACTION_UP:
                if (pullDonwDist>0){
                    //头部复位到刷新的位置
                    if (state==READY_REFRESHING){
                        headIcon.clearAnimation();
                        headIcon.setVisibility(View.INVISIBLE);
                        headProgBar.setVisibility(View.VISIBLE);
                        headText.setText("正在刷新");
                        state=REFRESHING;
                        if (mListener!=null) {
                            mListener.refresh();
                        }else{
                            notifySuccess();
                        }
                    }
                    //头部复位到0
                    else{
                        state=RESET;
                    }
                    speed=pullDonwDist*1000/fps/duration;
                }else if (-pullUpDist>0){
                    //尾部复位到刷新的位置
                    if (state==READY_LOAGMOREING){
                        footText.setText("正在刷新");
                        state=LOADING;
                        footIcon.clearAnimation();
                        footIcon.setVisibility(View.INVISIBLE);
                        footProgBar.setVisibility(View.VISIBLE);
                        if (mListener!=null) {
                            mListener.loadMore();
                        }else{
                            notifySuccess();
                        }
                    }
                    //尾部复位
                    else{
                        state=RESET;
                    }
                    speed=-pullUpDist*1000/fps/duration;
                }
                if (speed==0) speed=2;
                mHandler.sendEmptyMessage(0);
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    public void setListener(PullListener pullListener){
        mListener=pullListener;
    }

    public void notifySuccess() {
        notifyState(SUCCESS);
    }

    public void notifyFail() {
        notifyState(FAIL);
    }

    private void notifyState(int _state) {
        state=_state;
        footProgBar.setVisibility(View.GONE);
        footIcon.setVisibility(View.VISIBLE);
        footIcon.startAnimation(rotateAnimation2);
        headProgBar.setVisibility(View.GONE);
        headIcon.setVisibility(View.VISIBLE);
        headIcon.startAnimation(rotateAnimation2);
        mHandler.sendEmptyMessage(0);

    }

    public interface PullListener{
        public void refresh();
        public void loadMore();
    }



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值