RefreshListView下拉刷新

布局:

<com.example.administrator.d30_myrefreshlistview.RefreshListView
    android:id="@+id/refresh_listview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
     />
<RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="20dp"
    android:layout_marginBottom="10dp"
    >
    <ImageView
        android:id="@+id/image_arrow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/indicator_arrow"
        android:layout_centerInParent="true"
        />
    <ProgressBar
        android:id="@+id/pb_rotate"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:indeterminate="false"
        android:indeterminateDuration="1000"
        android:indeterminateDrawable="@drawable/indecate_rotate"
        android:layout_centerInParent="true"
        android:visibility="invisible"
        />
</RelativeLayout>
<LinearLayout
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="20dp"
    android:layout_marginTop="10dp"
    android:layout_marginBottom="10dp"
    >
    <TextView
        android:id="@+id/tv_state"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:textColor="#aa000000"
        android:text="下拉刷新"
        android:layout_marginBottom="10dp"
        />
    <TextView
        android:id="@+id/tv_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="14sp"
        android:textColor="@android:color/darker_gray"
        android:text="最后刷新"
        android:layout_marginBottom="10dp"
        />
</LinearLayout>
<ProgressBar
    android:layout_width="30dp"
    android:layout_height="30dp"
    android:id="@+id/pb_rotate_footer"
    android:indeterminateDrawable="@drawable/indecate_rotate"
    android:indeterminateDuration="1000"
    android:layout_marginTop="10dp"
    android:layout_marginBottom="10dp"
    />
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="正在加载..."
    android:textSize="20sp"
    android:textColor="#aa000000"
    android:layout_marginLeft="10dp"
    android:layout_marginTop="10dp"
    android:layout_marginBottom="10dp"/>

代码:

/*
1:创建集合,准备数据。
2:创建适配器。
3:设置适配器。
 */
public class MainActivity extends AppCompatActivity {
    private RefreshListView listview;
    private List<String> strs;
    private MyAdapter adapter;
    private boolean flag = true;//true表示下拉刷新,false表示上拉加载。
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
           //下载数据已经完成。
            //更新界面。
           adapter.notifyDataSetChanged();
            //RefreshListView界面要还原初始状态。
            listview.completeView();
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listview = (RefreshListView) findViewById(R.id.refresh_listview);
        //添加监听
        listview.setOnRefreshListener(new RefreshListView.onRefreshListener() {
            @Override
            public void onPullRefresh() {
                //模拟请求网络数据。
                requestDataFromServer(true);
            }

            @Override
            public void onLoadMore() {
                //模拟请求下一页网络数据。
                requestDataFromServer(false);
            }
        });
        initData();
        adapter = new MyAdapter();
        listview.setAdapter(adapter);
    }

    private void requestDataFromServer(final boolean flag) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                SystemClock.sleep(3000);
                //1;添加新的数据。
                if(flag) {
                    strs.add(0, "下拉刷新的数据");
                    //2;通知ui线程更新界面。
                    handler.sendEmptyMessage(1);
                }else{
                    //上拉加载。
                    strs.add("加载更多的数据"+1);
                    strs.add("加载更多的数据"+2);
                    strs.add("加载更多的数据"+3);
                    handler.sendEmptyMessage(1);
                }
            }
        }).start();
    }

    private void initData() {
        strs = new ArrayList<String>();
        for(int i=0;i<18;i++){
            strs.add("listview 原来的数据"+i);
        }
    }
    class MyAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return strs.size();
        }

        @Override
        public Object getItem(int position) {
            return strs.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView item_view = new TextView(MainActivity.this);
            item_view.setPadding(0,10,0,10);
            //设置字体
            item_view.setTextSize(20);
            //设置内容
            item_view.setText(strs.get(position));
            return item_view;
        }
    }
}
public class RefreshListView extends ListView implements AbsListView.OnScrollListener {
    private View headerView;
    private int headerView_height;
    private int down_y;//按下的时候y的坐标
    private static final int PULL_REFRESH = 0;//表示下拉刷新--允许下拉刷新
    private static final int RELEASE_REFRESH = 1;//表示松开刷新--允许松开刷新
    private static final int REFRESHING = 2;//表示正在刷新--头部完全显示。---正在请求网络数据。
    private int current_state = PULL_REFRESH;//最初状态
    private ImageView image_arrow;//箭头控件
    private TextView tv_state, tv_time;//状态文本框,时间文本显示框。
    private ProgressBar pb_rotate;//旋转动画。
    private RotateAnimation downAnimation, upAnimation;
    private int padding_top;//表示headview的padding_top;
    private onRefreshListener listener;//使用者传过来的实现的对象。
    private View footView;//底部控件。
    private int footView_height;//底部控件的高度。
    public RefreshListView(Context context) {
        super(context);
        init();
    }

    public RefreshListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        //设置监听
        setOnScrollListener(this);
        initHeaderView();
        initRotateAnimation();//创建2个动画
        initFooterView();
    }

    private void initFooterView() {
        footView = View.inflate(getContext(),R.layout.layout_footer,null);
        footView.measure(0, 0);
        footView_height =footView.getMeasuredHeight();
        //设置隐藏
        footView.setPadding(0, -footView_height, 0, 0);
        addFooterView(footView);
    }

    private void initRotateAnimation() {
        //往下动画。
        downAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        downAnimation.setDuration(300);
        downAnimation.setFillAfter(true);
        //往上动画
        upAnimation = new RotateAnimation(-180, -360, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        upAnimation.setDuration(300);
        upAnimation.setFillAfter(true);
    }

    private void initHeaderView() {
        headerView = View.inflate(getContext(), R.layout.layout_header, null);
        image_arrow = (ImageView) headerView.findViewById(R.id.image_arrow);
        tv_state = (TextView) headerView.findViewById(R.id.tv_state);
        tv_time = (TextView) headerView.findViewById(R.id.tv_time);
        pb_rotate = (ProgressBar) headerView.findViewById(R.id.pb_rotate);
        //设置头部控件的一些属性。--下拉刷新主要是通过更改头部控件的padding值来隐藏和显示的。
        //先要计算头部控件的高度。
        headerView.measure(0, 0);//先执行onMearsure();
        headerView_height = headerView.getMeasuredHeight();
        headerView.setPadding(0, -headerView_height, 0, 0);//隐藏头部
        //添加给listview.
        addHeaderView(headerView);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                down_y = (int) ev.getY();
                //按下状态
                break;
            case MotionEvent.ACTION_MOVE:
                //滑动的状态
                //1:获得当前的y坐标
                int y = (int) ev.getY();
                //2:计算滑动了多远。
                int delta_y = y - down_y;//往下滑delta_y>0,,往上滑  delta_y<0
                padding_top = delta_y + (-headerView_height);
                //将值设置给头部控件。
                if (padding_top > -headerView_height) {//说明头部要么正好隐藏要么显示一部分或者更多。
                    headerView.setPadding(0, padding_top, 0, 0);
                    if (padding_top >= 0 && current_state == PULL_REFRESH) {
                        current_state = RELEASE_REFRESH;//松开刷新。
                        //变化
                        //1:箭头往上执行动画
                        //2:文字改变。----tv_state---松开刷新。
                        refreshView();
                    } else if (padding_top < 0 && current_state == RELEASE_REFRESH) {
                        current_state = PULL_REFRESH;
                        //变化
                        // 1:箭头往下执行动画
                        //2:文字改变---下拉刷新
                        refreshView();
                    }
                    return true;//消费这个事件。意思就是让listview不要有滚动的行为,杜绝listview滚动。

                }
                break;
            case MotionEvent.ACTION_UP:
                //松开的状态
                if(current_state==PULL_REFRESH){
                    //隐藏
                    headerView.setPadding(0,-headerView_height,0,0);
                }else if(current_state==RELEASE_REFRESH){
                   //更改状态。
                    current_state = REFRESHING;
                    //更新界面。
                    refreshView();
                    //5:要请求网络数据,
                    if(listener!=null){
                        listener.onPullRefresh();//请求新的数据。
                    }
                }
                break;
        }
        return super.onTouchEvent(ev);
    }
    private boolean flag;//true表示数据已经显示完。
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
              if(scrollState==SCROLL_STATE_IDLE && flag){
                  isLoadMore = true;
                  //请求下一页
                  //1:底部要显示。
                  footView.setPadding(0,0,0,0);
                  //2:请求下一页数据。
                  if(listener!=null){
                      listener.onLoadMore();
                  }
              }
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
             flag = firstVisibleItem+visibleItemCount==totalItemCount;
    }

    public interface  onRefreshListener{
        void onPullRefresh();
        void onLoadMore();
    }
    public void setOnRefreshListener(onRefreshListener listener){
        this.listener = listener;
    }
    private void refreshView() {
        switch (current_state) {
            case RELEASE_REFRESH:
                //动画
                //1:箭头往上执行动画
                image_arrow.startAnimation(upAnimation);
                //2:文字改变。----tv_state---松开刷新。
                tv_state.setText("松开刷新");
                break;
            case PULL_REFRESH:
                // 1:箭头往下执行动画
                image_arrow.startAnimation(downAnimation);
                //2:文字改变---下拉刷新
                tv_state.setText("下拉刷新");
                break;
            case REFRESHING:
                //1:头部要正常显示。
                headerView.setPadding(0, 0, 0, 0);
                //2:箭头隐藏
                image_arrow.setVisibility(INVISIBLE);
                //3:进度条显示。
                pb_rotate.setVisibility(VISIBLE);
                //4:文字更改。
                tv_state.setText("正在刷新");
                break;

        }
    }
    private boolean isLoadMore;//true表示上拉加载,false表示下拉刷新。
    //还原初始化状态。
    public void completeView(){
        if(!isLoadMore) {
            //1:箭头要显示。
            image_arrow.clearAnimation();//这个时候有可能箭头有可能在执行动画。将动画进行清除。
            image_arrow.setVisibility(VISIBLE);
            //2:进度动画要隐藏
            pb_rotate.setVisibility(INVISIBLE);
            //3:tv_state文字改变为下拉刷新。
            tv_state.setText("下拉刷新");
            //4;状态---更改为下拉刷新。
            current_state = PULL_REFRESH;
            //5:tv_time更改为当前的时间
            tv_time.setText(getTime());
            //隐藏
            headerView.setPadding(0, -headerView_height, 0, 0);
        }else{
            footView.setPadding(0,-footView_height,0,0);
            isLoadMore = false;
            //  定位到最后一条。
            setSelection(getCount()-1);//定位到最后一条数据。
        }
    }
    private String getTime(){
        SimpleDateFormat format = new SimpleDateFormat("yyyy MM dd HH:mm:ss");
       return  format.format(new Date());
    }
}

 

原文地址:https://www.cnblogs.com/anni-qianqian/p/5436322.html