1. 程式人生 > >翻翻git之---實現下拉到底重新整理RecycleView InfiniteScroll

翻翻git之---實現下拉到底重新整理RecycleView InfiniteScroll

因為今天還有點工作上的事沒做完,所以就不吹B了,介紹完庫寫完解釋就吃飯去了,下午還要幹活呢

InfiniteScroll

在傳統的ListView李有PullToFressh做下拉重新整理之類的實現,今天上一個類似的效果InfiniteScroll,不過他是寄存在RecycleView下的更符合發展趨勢

效果圖:

這裡寫圖片描述

拉到底就加在更多出現Dialog的效果,使用場景很多

how to use?

Grade:

dependencies {
  compile 'com.github.pwittchen:infinitescroll:0.0.1'
}

Maven:

<dependency
>
<groupId>com.github.pwittchen</groupId> <artifactId>infinitescroll</artifactId> <version>0.0.1</version> </dependency>

Eclipse:把圈圈那部分Copy了就行

這裡寫圖片描述

再來說下具體怎麼引用,直接貼例子程式碼在裡面有詳細解釋

public class MainActivity extends AppCompatActivity {
    private static
final int MAX_ITEMS_PER_REQUEST = 20;//每次請求item數 private static final int NUMBER_OF_ITEMS = 100;//最大item數 private static final int SIMULATED_LOADING_TIME_IN_MS = 1500;//模擬耗時操作睡執行緒的時間 public Toolbar toolbar; public RecyclerView recyclerView; public ProgressBar progressBar; private MyAdapter myAdapter; private
LinearLayoutManager layoutManager; private List<String> items; private int page = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化資料來源 this.items = createItems(); //獲取控制元件id initViews(); //初始化RecyclerView initRecyclerView(); setSupportActionBar(toolbar); } //如果<10 那就前面+"0" private List<String> createItems() { List<String> items = new LinkedList<>(); for (int i = 0; i < NUMBER_OF_ITEMS; i++) { String prefix = i < 10 ? "0" : ""; items.add("Item #".concat(prefix).concat(String.valueOf(i))); } return items; } private void initViews() { toolbar = (Toolbar) findViewById(R.id.toolbar); recyclerView = (RecyclerView) findViewById(R.id.recycler_view); progressBar = (ProgressBar) findViewById(R.id.progress_bar); } private void initRecyclerView() { layoutManager = new LinearLayoutManager(this); //如果item高度不變,提升效能操作 recyclerView.setHasFixedSize(true); //設定ListView樣式 recyclerView.setLayoutManager(layoutManager); //新增介面卡,subList方法截取了原本100長度的ArrayList的0->MAX_ITEMS_PER_REQUEST 部分 myAdapter = new MyAdapter(items.subList(page, MAX_ITEMS_PER_REQUEST)); recyclerView.setAdapter(myAdapter); //新增滑動監聽 recyclerView.addOnScrollListener(createInfiniteScrollListener()); myAdapter.setOnItemClickListener(new MyAdapter.OnRecyclerViewItemClickListener() { @Override public void onItemClick(View view, int position) { Toast.makeText(MainActivity.this, "第" + position + "被點選", Toast.LENGTH_SHORT).show(); } }); } @NonNull private InfiniteScrollListener createInfiniteScrollListener() { return new InfiniteScrollListener(MAX_ITEMS_PER_REQUEST, layoutManager) { //重新整理後第一個可見的item位置 @Override public void onScrolledToEnd(final int firstVisibleItemPosition) { Log.d("-->firstVisible","firstVisibleItemPosition : "+firstVisibleItemPosition); simulateLoading(); //每次載入X * 20個item int start = ++page * MAX_ITEMS_PER_REQUEST; final boolean allItemsLoaded = start >= items.size(); if (allItemsLoaded) { progressBar.setVisibility(View.GONE); } else { int end = start + MAX_ITEMS_PER_REQUEST; //合成新的資料來源 final List<String> items = getItemsToBeLoaded(start, end); //重新重新整理View refreshView(recyclerView, new MyAdapter(items), firstVisibleItemPosition); } } }; } @NonNull private List<String> getItemsToBeLoaded(int start, int end) { List<String> newItems = items.subList(start, end); final List<String> oldItems = ((MyAdapter) recyclerView.getAdapter()).getItems(); final List<String> items = new LinkedList<>(); items.addAll(oldItems); items.addAll(newItems); return items; } /** * WARNING! This method is only for demo purposes! * Don't do anything like that in your regular project! */ private void simulateLoading() { new AsyncTask<Void, Void, Void>() { @Override protected void onPreExecute() { progressBar.setVisibility(View.VISIBLE); } @Override protected Void doInBackground(Void... params) { try { Thread.sleep(SIMULATED_LOADING_TIME_IN_MS); } catch (InterruptedException e) { Log.e("MainActivity", e.getMessage()); } return null; } @Override protected void onPostExecute(Void param) { progressBar.setVisibility(View.GONE); } }.execute(); } }

流程是這樣的,一開始做了一個假資料,然後拉到底就重新整理,然後拉到底就重新整理然後重新整理到最大值就不做增加的操作了,但是判斷還是一直有的

這裡寫圖片描述
上圖是不重新整理但還在判斷的證據

那我們來大致看看這個下拉的判斷是如何實現的

//繼承於RecyclerView.OnScrollListener,也就有了一個很重要的方法
// onScrolled(RecyclerView recyclerView, int dx, int dy)
public abstract class InfiniteScrollListener extends RecyclerView.OnScrollListener
//建構函式分別傳入2個引數,一個是要被載入的最大值,還有個是LinearLayoutManager物件,然後再是做異常處理,為空什麼的
   public InfiniteScrollListener(int maxItemsPerRequest, LinearLayoutManager layoutManager) {
        Preconditions.checkIfPositive(maxItemsPerRequest, "maxItemsPerRequest <= 0");
        Preconditions.checkNotNull(layoutManager, "layoutManager == null");
        this.maxItemsPerRequest = maxItemsPerRequest;
        this.layoutManager = layoutManager;
    }
     //具體執行操作和回撥做事的地方,返回的也就是那個可見第一個item的position
     @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        //這邊就是判斷是否能加在
        if (canLoadMoreItems()) {
            onScrolledToEnd(layoutManager.findFirstVisibleItemPosition());
        }
    }
//載入完重新整理的操作,然後再移到那個標誌位的位置上去,這也就是為什麼每次我們重新整理完沒有跳到最上面的原因
protected void refreshView(RecyclerView view, RecyclerView.Adapter adapter, int position) {
        view.setAdapter(adapter);
        view.invalidate();
        view.scrollToPosition(position);
    }
  //抽象方法了,給我們實現用
  public abstract void onScrolledToEnd(final int firstVisibleItemPosition);

整體實現不太難,但是有很好的思路,所以給大家推薦下。