一、分页显示
1.问题
getRecent方法默认返回一页包含100个结果的数据。不过,该方法还有个叫作page的参数, 可以用它返回第二页、第三页等更多页数据。 请实现一个RecyclerView.OnScrollListener方法,只要用户看完当前页,就使用下页返 回结果替换当前页。想更有挑战的话,可以尝试把后续结果页添加到当前结果页后面。
2.提示
onScrollListener 有两个可以重写的方法,一个是 onScrollStateChanged(),还有一个是 onScrolled,对我们这个需求来说,显然 onScrollStateChanged 比较合适,ScrollState 也有三种:
SCROLL_STATE_IDLE: 视图没有被拖动,处于静止
SCROLL_STATE_DRAGGING: 视图正在拖动中
SCROLL_STATE_SETTLING: 视图在惯性滚动
3.解决办法
3.1.实现RecyclerView.OnScrollListener方法
private RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
//获取LayoutManager
GridLayoutManager layoutManager = (GridLayoutManager)recyclerView.getLayoutManager();
//最后显示位置
int mLastPosition = layoutManager.findLastCompletelyVisibleItemPosition();
if (mPhotoAdapter == null) {
return;
}
if (newState == RecyclerView.SCROLL_STATE_IDLE && mLastPosition >= mPhotoAdapter.getItemCount() -1){
if (mFetchItemsTask.getStatus() == AsyncTask.Status.FINISHED){
mNextPage++;
if (mNextPage <= MAX_PAGES){
Toast.makeText(getActivity(),"waiting to loading......",Toast.LENGTH_SHORT).show();
mFetchItemsTask = new FetchItemsTask();
mFetchItemsTask.execute(mNextPage);
}else {
Toast.makeText(getActivity(),"This is the end!",Toast.LENGTH_SHORT).show();
}
}
}
}
};
3.2.添加数据并展示
在 Adapter 中加入一个 addData 方法,将新的数据加入到数据集中,然后使用 notifyDataSetChanged 方法更新视图。
public void addData(List<GalleryItem> mItem) {
mGalleryItems.addAll(mItem);
notifyDataSetChanged();
}
然后修改setAdapter方法
private void setupAdapter() {
if (isAdded()){
if (mNextPage == 1){
mPhotoAdapter = new PhotoAdapter(mItem);
mPhotoRecyclerView.setAdapter(mPhotoAdapter);
mPhotoRecyclerView.addOnScrollListener(onScrollListener);
}else {
mPhotoAdapter.addData(mItem);
}
}
}
二、动态调整网格列
1.问题
当前,显示图片标题的网格固定有3列。编写代码动态调整网格列数,实现在横屏或大屏幕 设备上显示更多列标题。
2.提示
实现这个目标有个简单方法:分别为不同的设备配置或屏幕尺寸提供整数修饰资源。这实际和第17章中为不同尺寸屏幕提供不同布局的方式差不多。整数修饰资源应放置在res/values目录 中。具体实施细节可参阅Android开发者文档。 提供整数修饰资源的方式不太好确定网格列细分粒度(只能凭经验预先定义列数)。下面再 介绍一个颇具挑战的方法:在fragment的视图创建时就计算并设置好网格列数。显然,这种方式 更加灵活实用。基于RecyclerView的当前宽度和预定义网格列宽,就可以计算出列数。 实施前还有个问题要解决:你不能在onCreateView()方法中计算网格列数,因为这个时候 RecyclerView还没有改变。不过,可以实现ViewTreeObserver.OnGlobalLayoutListener监 听器方法和计算列数的onGlobalLayout()方法,然后使用addOnGlobalLayoutListener()把 监听器添加给RecyclerView视图。
3.解决办法
实现OnGlobalLayoutListener
mPhotoRecyclerView.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// 计算列数,以 1080p 屏幕显示3列为基准
int columns = mPhotoRecyclerView.getWidth() / 350;
// 重新设置 LayoutManager、Adapter 和 Listener
mPhotoRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(), columns));
mPhotoRecyclerView.setAdapter(mPhotoAdapter);
mPhotoRecyclerView.addOnScrollListener(onButtomListener);
// 滚动到之前看到的位置
mPhotoRecyclerView.getLayoutManager().scrollToPosition(mLastPosition);
//将 GlobalLayoutListener 去掉以避免多次触发
mPhotoRecyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});