天天看點

Android之RecyclerView輕松實作下拉重新整理和加載更多

今天研究了下RecyclerView的滑動事件,特别是下拉重新整理和加載更多事件,在現在幾乎所有的APP顯示資料清單時都用到了。自定義RecyclerView下拉重新整理和加載更多聽上去很複雜,實際上并不難,隻要是對滑動事件的監聽和處理。

一、自定義RecyclerView實作下拉重新整理和加載更多

1、如何判斷RecyclerView是在上滑還是下滑

在RecyclerView的OnScrollListener滑動事件監聽中有個好用的方法,就是onScrolled(RecyclerView recyclerView, int dx, int dy),其中根據dx的值的正負就可以判斷是在左滑還是右滑,而根據dy的值就可以判斷是在上滑還是下滑。

//上滑
if(dy>0){
//相應操作代碼
}
//下滑
else if(dy<0){
//相應操作代碼
}
           

2、如何判斷是否滑到了頂部或者底部

同樣在RecyclerView的OnScrollListener滑動事件監聽中onScrolled(RecyclerView recyclerView, int dx, int dy)方法中處理,根據canScrollVertically(int direction)來進行判斷。

//是否滑到底部
if(!recyclerView.canScrollVertically(1)){
    //相應處理操作
}
//是否滑到頂部
if(!recyclerView.canScrollVertically(-1)){
    //相應處理操作
}
           

3、自定義RecyclerView

知道了滑動事件的判斷和處理,就可以很輕松得實作下拉重新整理和加載更多了。

import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

/**
 * Package:com.liuting.library
 * author:liuting
 * Date:2017/2/14
 * Desc:自定義RecycleView,下拉重新整理以及上拉加載更多
 */

public class RefreshLoadMoreRecycleView extends RecyclerView implements RecyclerView.OnTouchListener{
    private Boolean isLoadMore;//加載更多标志
    private Boolean isLoadEnd;//加載到最後的标志
    private Boolean isLoadStart;//頂部的标志
    private Boolean isRefresh;//下拉重新整理标志
    private int lastVisibleItem;//最後一項
    private IOnScrollListener listener;//事件監聽
    private float mLastY;//監聽移動的位置

    public RefreshLoadMoreRecycleView(Context context) {
        super(context);
        init(context);
    }

    public RefreshLoadMoreRecycleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public RefreshLoadMoreRecycleView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

	 /**
     * 初始化
     * 
     * @param context
     */
    public void init(Context context) {
        isLoadEnd=false;
        isLoadStart =true;

        this.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                //SCROLL_STATE_DRAGGING  和   SCROLL_STATE_IDLE 兩種效果自己看着來
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    loadData();
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                //上滑
                if(dy>0){
                    //是否滑到底部
                    if(!recyclerView.canScrollVertically(1)){
                        isLoadEnd = true;
                    }else{
                        isLoadEnd = false;
                    }
                    Log.e("TAG","Running--->>isLoadEnd:"+isLoadEnd+dy);
                }else if(dy<0){
                    //是否滑到頂部
                    if(!recyclerView.canScrollVertically(-1)){
                        isLoadStart=true;
                    }else{
                        isLoadStart=false;
                    }

                }
            }
        });
        this.setOnTouchListener(this);
    }

	 /**
     * 
     * 加載資料
     * 
     */
    private void loadData() {
        if (isLoadEnd) {
            // 判斷是否已加載所有資料
            if (isLoadMore) {//未加載完所有資料,加載資料,并且還原isLoadEnd值為false,重新定位清單底部
                if (getListener() != null) {
                    getListener().onLoadMore();
                }
            } else {//加載完了所有的資料
                if(getListener()!=null){
                    getListener().onLoaded();
                }
            }
            isLoadEnd = false;
        } else if (isLoadStart) {
            if(isRefresh){
                if (getListener() != null) {
                    getListener().onRefresh();
                }
                isLoadStart=false;
            }
        }
    }

    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if (mLastY == -1) {
            mLastY = motionEvent.getRawY();
        }
        switch (motionEvent.getAction()){
            case MotionEvent.ACTION_MOVE:
                final float deltaY = motionEvent.getRawY() - mLastY;
                mLastY = motionEvent.getRawY();
				//向上移動
                if(deltaY<0){
                    //是否滑到底部
                    if(!this.canScrollVertically(1)){
                        isLoadEnd = true;
                    }else{
                        isLoadEnd = false;
                    }
                }
				//向下移動
				else if(deltaY>0) {
                    //是否滑到頂部
                    if (!this.canScrollVertically(-1)) {
                        isLoadStart = true;
                    } else {
                        isLoadStart = false;
                    }
                }
                break;
            case MotionEvent.ACTION_DOWN:
                mLastY = motionEvent.getRawY();
                break;
            default://重置
                mLastY = -1;
                break;
        }

        return false;
    }

	//事件監聽
    public interface IOnScrollListener {
        void onRefresh();

        void onLoadMore();

        void onLoaded();
    }

    public IOnScrollListener getListener() {
        return listener;
    }

	//設定事件監聽
    public void setListener(IOnScrollListener listener) {
        this.listener = listener;
    }

    public Boolean getLoadMore() {
        return isLoadMore;
    }

	//設定是否支援加載更多
    public void setLoadMoreEnable(Boolean loadMore) {
        isLoadMore = loadMore;
    }

    public Boolean getRefresh() {
        return isRefresh;
    }

	//設定是否支援下拉重新整理
    public void setRefreshEnable(Boolean refresh) {
        isRefresh = refresh;
    }
}
           

二、實際用例

已經定義好了RecyclerView,下面在Demo中實際使用和處理。

1、定義布局

布局檔案很簡單,就是一個RecyclerView

2、定義RecyclerView.Adapter

RecyclerView.Adapter在這裡就簡單處理了,清單布局直接使用Android自帶的。

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.List;

/**
 * Package:com.liuting.refreshloadmorelistview.adapter
 * author:liuting
 * Date:2017/2/16
 * Desc:清單Adapter
 */

public class RefreshLoadMoreRecycleAdapter extends RecyclerView.Adapter
      
        {
    private List
       
         list;
    private Context context;

    public RefreshLoadMoreRecycleAdapter(Context context,List
        
          list) {
        this.context =context;
        this.list = list;
    }

    @Override
    public RefreshLoadMoreRecycleAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_expandable_list_item_1, parent, false);
        RefreshLoadMoreRecycleAdapter.ViewHolder viewHolder = new RefreshLoadMoreRecycleAdapter.ViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.text.setText(list.get(position));
        holder.itemView.setTag(position);
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

    class ViewHolder extends RecyclerView.ViewHolder{
        private TextView text;

        public ViewHolder(View itemView) {
            super(itemView);
            text=(TextView)itemView.findViewById(android.R.id.text1);
        }
    }
}
        
       
      
           

3、在Activity中定義好控件以及資料加載操作

實作自定義RecyclerView中的資料加載事件監聽,重新整理、加載更多以及加載完成。

import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.widget.Toast;

import com.liuting.library.RefreshLoadMoreRecycleView;
import com.liuting.refreshloadmorelistview.adapter.RefreshLoadMoreRecycleAdapter;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements RefreshLoadMoreRecycleView.IOnScrollListener{
    private RefreshLoadMoreRecycleView recycleView;//下拉重新整理RecycleView
    private List
       
         list;//清單
    private RefreshLoadMoreRecycleAdapter adapter;//Adapter
    private ProgressDialog dialog;//提示框
    private static final int REFRESH_Load=0;//下拉重新整理
    private static final int MORE_Load=1;//加載更多
    private Handler handler =new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case REFRESH_Load:
                    recycleView.setLoadMoreEnable(true);
                    dismissDialog();
                    if(list!=null){
                        list.clear();
                    }
                    loadData();
                    adapter.notifyDataSetChanged();
                    break;
                case MORE_Load:
                    recycleView.setLoadMoreEnable(false);
                    dismissDialog();
                    loadData();
                    adapter.notifyDataSetChanged();
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    public void initView(){
        dialog = new ProgressDialog(MainActivity.this);

        list=new ArrayList<>();
        loadData();
        recycleView = (RefreshLoadMoreRecycleView)findViewById(R.id.main_recycle_view_data);

        final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(MainActivity.this);
        recycleView.setLayoutManager(linearLayoutManager);
        adapter = new RefreshLoadMoreRecycleAdapter(MainActivity.this,list);
        recycleView.setAdapter(adapter);
        recycleView.setListener(this);
        recycleView.setRefreshEnable(true);
        recycleView.setLoadMoreEnable(true);
    }

    /**
     * 加載資料
     */
    public void loadData(){
        for(int i=0;i<10;i++ ){
            list.add("It is "+i);
        }
    }

    @Override
    public void onRefresh() {
        showDialog();
        new Thread(){
            @Override
            public void run() {
                super.run();
                try {
                    sleep(5000);
                    handler.sendEmptyMessage(REFRESH_Load);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    @Override
    public void onLoadMore() {
        showDialog();
        new Thread(){
            @Override
            public void run() {
                super.run();
                try {
                    sleep(5000);
                    handler.sendEmptyMessage(MORE_Load);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    @Override
    public void onLoaded() {
        Toast.makeText(MainActivity.this,"Loaded all",Toast.LENGTH_SHORT).show();
    }

    /**
     * dismiss dialog
     */
    private void dismissDialog(){
        if (dialog!=null&&dialog.isShowing()){
            dialog.dismiss();
        }
    }

    /**
     * show dialog
     */
    private void showDialog(){
        if (dialog!=null&&!dialog.isShowing()){
            dialog.show();
        }
    }
}
       
           

三、最終效果圖

Android之RecyclerView輕松實作下拉重新整理和加載更多

到這裡就輕松實作了RecyclerView的下拉重新整理和加載更多了。

源代碼在Github上:https://github.com/LT5505/RefreshLoadMoreRecycleView