转载请注明出处:王亟亟的大牛之路
因为今天还有点工作上的事没做完,所以就不吹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);
整体实现不太难,但是有很好的思路,所以给大家推荐下。
源码地址:https://github.com/ddwhan0123/BlogSample/blob/master/InfiniteScroll-master.zip
git地址:https://github.com/ddwhan0123/InfiniteScroll#download
时间: 2024-10-09 09:18:58