RecylerView 的 onScrollChanged() 在 Android 中未检测到屏幕底部
Posted
技术标签:
【中文标题】RecylerView 的 onScrollChanged() 在 Android 中未检测到屏幕底部【英文标题】:RecylerView's onScrollChanged() does not detects bottom of screen in Android 【发布时间】:2020-04-20 23:25:56 【问题描述】:我正在实现一个功能,我需要在列表到达末尾时再次点击 API 来获取数据。我已经使用 RecyclerView 的 onScrollListener 来检测它是否到达结束,但代码仅在我打开屏幕时第一次运行,但到达屏幕结束时它不起作用. 如何检查列表何时结束。
片段代码:
@SuppressLint("RestrictedApi")
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
View v = inflater.inflate(R.layout.fragment_home, container, false);
initScrollListener();
private void initScrollListener()
list.addOnScrollListener(new RecyclerView.OnScrollListener()
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState)
super.onScrollStateChanged(recyclerView, newState);
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy)
super.onScrolled(recyclerView, dx, dy);
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
Toast.makeText(getActivity(), "Loading", Toast.LENGTH_SHORT).show();
if (!isLoading)
if (linearLayoutManager != null && linearLayoutManager.findLastCompletelyVisibleItemPosition() == rowsArrayList.size() - 1)
//bottom of list!
loadMore();
isLoading = true;
);
private void loadMore()
rowsArrayList.add(null);
postListAdapter.notifyItemInserted(rowsArrayList.size() - 1);
Handler handler = new Handler();
handler.postDelayed(new Runnable()
@Override
public void run()
rowsArrayList.remove(rowsArrayList.size() - 1);
int scrollPosition = rowsArrayList.size();
postListAdapter.notifyItemRemoved(scrollPosition);
int currentSize = scrollPosition;
int nextLimit = currentSize + 10;
while (currentSize - 1 < nextLimit)
rowsArrayList.add("Item " + currentSize);
currentSize++;
postListAdapter.notifyDataSetChanged();
isLoading = false;
, 2000);
适配器代码:
public class PostListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
Context context;
List<StoriesDatum> storiesDatumList;
StoriesDatum storiesDatum;
FragmentHome fragmentHome;
int qty;
View itemView;
private final int VIEW_TYPE_ITEM = 0;
private final int VIEW_TYPE_LOADING = 1;
public PostListAdapter(Context context, List<StoriesDatum> storiesDatumList, FragmentHome fragmentHome)
this.context = context;
this.storiesDatumList = storiesDatumList;
this.fragmentHome = fragmentHome;
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
if (viewType == VIEW_TYPE_ITEM)
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_post, parent, false);
return new MyViewHolder(view);
else
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_loading, parent, false);
return new LoadingViewHolder(view);
@Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position)
if (holder instanceof MyViewHolder)
populateItemRows((MyViewHolder) holder, position);
else if (holder instanceof LoadingViewHolder)
showLoadingView((LoadingViewHolder) holder, position);
@Override
public long getItemId(int position)
return position;
@Override
public int getItemViewType(int position)
return storiesDatumList.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
@Override
public int getItemCount()
return storiesDatumList.size();
private class LoadingViewHolder extends RecyclerView.ViewHolder
ProgressBar progressBar;
public LoadingViewHolder(@NonNull View itemView)
super(itemView);
progressBar = itemView.findViewById(R.id.progressBar);
private void showLoadingView(LoadingViewHolder viewHolder, int position)
//ProgressBar would be displayed
private void populateItemRows(MyViewHolder myViewHolder, final int position)
String item = storiesDatumList.get(position).toString();
storiesDatum = storiesDatumList.get(position);
myViewHolder.txtCommunityName.setText(storiesDatum.getComTitle());
myViewHolder.txtPostTitle.setText(storiesDatum.getTitle());
String comm_photo = String.valueOf(storiesDatum.getComImage());
if (comm_photo == null || comm_photo.equals("null") || comm_photo.equals(""))
myViewHolder.ivImage.setImageResource(R.mipmap.top_communities_circle);
else
if (comm_photo.startsWith("https://") || comm_photo.startsWith("http://"))
long interval = 5000 * 1000;
Glide.with(context).load(comm_photo)
.into(myViewHolder.ivImage);
else
Glide.with(context).load(Constants.image_url + comm_photo)
.into(myViewHolder.ivImage);
myViewHolder.txtNamePosted.setText("Posted by " + storiesDatum.getUsername());
String created_date = storiesDatum.getCreatedAt();
//call date
String corecDate = fragmentHome.createDate(created_date);
myViewHolder.txtTime.setText(corecDate);
myViewHolder.txtCommentCount.setText(storiesDatum.getCommentsCount() + " Comments");
myViewHolder.txtLikeCount.setText(storiesDatum.getStoryemojiCount() + " Reactions");
/*change code for adapter*/
myViewHolder.tvPost.setText(storiesDatum.getSnapshots());
if (storiesDatum.getStoryBody() != null)
myViewHolder.tvBody.setVisibility(View.VISIBLE);
myViewHolder.tvBody.setText(storiesDatum.getStoryBody());
else
myViewHolder.tvBody.setVisibility(View.GONE);
if (storiesDatum.getStoryType() == 2)
myViewHolder.videoPost.setVisibility(View.GONE);
myViewHolder.youTubePlayerView.setVisibility(View.GONE);
if (storiesDatum.getStoryUpload() == null && (storiesDatum.getStoryUrl() != null))
myViewHolder.ivImageViaLink.setVisibility(View.VISIBLE);
myViewHolder.ivPostImage.setVisibility(View.GONE);
String story_url = storiesDatum.getStoryUrl().toString();
Log.e("TAG", "onResponse:story1 " + story_url);
if (story_url.startsWith("https://") || story_url.startsWith("http://"))
Glide.with(context).load(story_url)
.into(myViewHolder.ivImageViaLink);
else
Glide.with(context).load(story_url)
// .placeholder(R.mipmap.top_communities_circle)
//.error(R.drawable.ic_launcher_background)
.into(myViewHolder.ivImageViaLink);
else if (storiesDatum.getStoryUrl() == null && (storiesDatum.getStoryUpload() != null))
myViewHolder.ivImageViaLink.setVisibility(View.GONE);
myViewHolder.ivPostImage.setVisibility(View.VISIBLE);
String story_url = storiesDatum.getStoryUpload().toString();
Log.e("TAG", "onResponse:story2 " + story_url);
if (story_url.startsWith("https://") || story_url.startsWith("http://"))
Glide.with(context).load(story_url)
// .placeholder(R.mipmap.top_communities_circle)
//.error(R.drawable.ic_launcher_background)
.into(myViewHolder.ivPostImage);
else
Glide.with(context).load(Constants.image_url + story_url)
// .placeholder(R.mipmap.top_communities_circle)
// .error(R.drawable.ic_launcher_background)
.into(myViewHolder.ivPostImage);
else
myViewHolder.ivImageViaLink.setVisibility(View.VISIBLE);
myViewHolder.ivPostImage.setVisibility(View.VISIBLE);
String story_upload = storiesDatum.getStoryUpload().toString();
Log.e("TAG", "onResponse:story3 " + story_upload);
if (story_upload.startsWith("https://") || story_upload.startsWith("http://"))
Glide.with(context).load(story_upload)
//.placeholder(R.mipmap.top_communities_circle)
//.error(R.drawable.ic_launcher_background)
.into(myViewHolder.ivPostImage);
else
Glide.with(context).load(Constants.image_url + story_upload)
// .placeholder(R.mipmap.top_communities_circle)
// .error(R.drawable.ic_launcher_background)
.into(myViewHolder.ivPostImage);
String story_url = storiesDatum.getStoryUrl().toString();
Log.e("TAG", "onResponse:story4 " + story_url);
if (story_url.startsWith("https://") || story_url.startsWith("http://"))
Glide.with(context).load(story_url)
//.placeholder(R.mipmap.top_communities_circle)
// .error(R.drawable.ic_launcher_background)
.into(myViewHolder.ivImageViaLink);
else
Glide.with(context).load(story_url)
// .placeholder(R.mipmap.top_communities_circle)
// .error(R.drawable.ic_launcher_background)
.into(myViewHolder.ivImageViaLink);
else if (storiesDatum.getStoryType() == 3)
myViewHolder.videoPost.setVisibility(View.GONE);
myViewHolder.youTubePlayerView.setVisibility(View.GONE);
if (storiesDatum.getStoryUpload() == null && (storiesDatum.getStoryUrl() != null))
myViewHolder.ivImageViaLink.setVisibility(View.VISIBLE);
myViewHolder.btn_play.setVisibility(View.VISIBLE);
myViewHolder.ivPostImage.setVisibility(View.GONE);
String story_url1 = storiesDatum.getStoryUrl().toString();
String[] cutLink = story_url1.split("frameborder");
String[] cutLink1 = cutLink[0].split("embed/");
String link = cutLink1[1];
final String played_link = link.split("\"")[0];
String story_url = "https://img.youtube.com/vi/" + played_link + "/0.jpg";
Log.e("TAG", "onResponse:story1 " + story_url);
if (story_url.startsWith("https://") || story_url.startsWith("http://"))
Glide.with(context).load(story_url)
// .placeholder(R.mipmap.top_communities_circle)
// .error(R.drawable.ic_launcher_background)
.into(myViewHolder.ivImageViaLink);
else
Glide.with(context).load(story_url)
// .placeholder(R.mipmap.top_communities_circle)
// .error(R.drawable.ic_launcher_background)
.into(myViewHolder.ivImageViaLink);
else if (storiesDatum.getStoryUrl() == null && (storiesDatum.getStoryUpload() != null))
myViewHolder.ivImageViaLink.setVisibility(View.GONE);
myViewHolder.ivPostImage.setVisibility(View.VISIBLE);
myViewHolder.play.setVisibility(View.VISIBLE);
String story_url = storiesDatum.getStoryUpload().toString();
Log.e("TAG", "onResponse:story2 " + story_url);
else
myViewHolder.ivImageViaLink.setVisibility(View.VISIBLE);
myViewHolder.ivPostImage.setVisibility(View.VISIBLE);
myViewHolder.btn_play.setVisibility(View.VISIBLE);
myViewHolder.play.setVisibility(View.VISIBLE);
String story_upload = storiesDatum.getStoryUpload().toString();
Uri videoURI;
videoURI = Uri.parse(Constants.image_url + story_upload);
Log.e("TAG", "onResponse:story3 " + videoURI);
String story_url1 = storiesDatum.getStoryUrl().toString();
String[] cutLink = story_url1.split("frameborder");
String[] cutLink1 = cutLink[0].split("embed/");
String link = cutLink1[1];
final String played_link = link.split("\"")[0];
String story_url = "https://img.youtube.com/vi/" + played_link + "/0.jpg";
Log.e("TAG", "onResponse:story4 " + story_url);
if (story_url.startsWith("https://") || story_url.startsWith("http://"))
Glide.with(context).load(story_url)
// .placeholder(R.mipmap.top_communities_circle)
// .error(R.drawable.ic_launcher_background)
.into(myViewHolder.ivImageViaLink);
else
Glide.with(context).load(story_url)
// .placeholder(R.mipmap.top_communities_circle)
// .error(R.drawable.ic_launcher_background)
.into(myViewHolder.ivImageViaLink);
// viewHolder.tvItem.setText(item);
myViewHolder.txtCommunityName.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
storiesDatum = storiesDatumList.get(position);
fragmentHome.sendToCommunityPage(storiesDatum.getComTitle(), storiesDatum.getCommunityId(), storiesDatum.getComImage());
);
myViewHolder.txtNamePosted.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
storiesDatum = storiesDatumList.get(position);
fragmentHome.sendToUserProfile(storiesDatum.getUserId(), storiesDatum.getUsername(), storiesDatum.getProfile_pic());
);
myViewHolder.ivAdd.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
storiesDatum = storiesDatumList.get(position);
fragmentHome.addCommunity(storiesDatum.getCommunityId());
);
Log.e("tag", "jpined_favourite" + storiesDatum.getJoined() + storiesDatum.getFav());
if (storiesDatum.getJoined() == 0)
myViewHolder.ivAdd.setVisibility(View.VISIBLE);
else
myViewHolder.ivAdd.setVisibility(View.GONE);
if (storiesDatum.getFav() == 1)
myViewHolder.ivFav.setImageResource(R.mipmap.mark_as_favorite_filled);
else
myViewHolder.ivFav.setImageResource(R.mipmap.mark_favorite);
myViewHolder.txtComment.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
fragmentHome.openCommentbox();
);
myViewHolder.ivFav.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
storiesDatum = storiesDatumList.get(position);
if (storiesDatum.getFav() == 0)
fragmentHome.addFavt(storiesDatum.getCommunityId().toString(), "markfav");
else
fragmentHome.addFavt(storiesDatum.getCommunityId().toString(), "unmarkfav");
);
myViewHolder.relativeLayout.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
//fragmentHome.sendToSinglePost();
StoriesDatum storiesDatum1 = storiesDatumList.get(position);
fragmentHome.sendToSinglePost(storiesDatum1.getId().toString());
);
myViewHolder.relativeShare.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
StoriesDatum storiesDatum1 = storiesDatumList.get(position);
fragmentHome.sharepost(storiesDatum1.getSlugid(), storiesDatum1.getSlug());
);
public class MyViewHolder extends RecyclerView.ViewHolder
【问题讨论】:
这将在onScrollStateChanged
下方为您提供if (!recyclerView.canScrollVertically(1))
或与此if(linearLayoutManager.findLastVisibleItemPosition() == linearLayoutManager.getItemCount()-1)
一起使用
list.addOnScrollListener
其中list
是recyclerview
实例,您在哪里启动或设置了适配器?
我在从 API 获取数据时设置了适配器
我没有找到你究竟在哪里创建了RecyclerView
到list
的实例
【参考方案1】:
使用这个方法
RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener()
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState)
super.onScrollStateChanged(recyclerView, newState);
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy)
super.onScrolled(recyclerView, dx, dy);
if (dy > 0) //check for scroll down
if (!mNoMoreLoad)
if ((mLayoutManager.getChildCount() +
mLayoutManager.findFirstVisibleItemPosition()) >= mLayoutManager.getItemCount())
mPage++;
mNoMoreLoad = true;
loadMore(mPage);
private void loadMore(int mPage)
if (Utils.getInstance().isNetworkAvailable(getActivity()))
hit api with page number
收到响应后,根据您的数据限制检查新数据的大小
if (response.getData().size() < Constants.DATA_LIMIT)
mNoMoreLoad = true;
else
mNoMoreLoad = false;
【讨论】:
不工作。我检查了 。 OnScrolld 方法不起作用 recyclerview.addOnScrollListener(onScrollListener); 也使用这一行【参考方案2】:您可以通过以下方式做到这一点:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener()
@Override
public void onScrollStateChanged( RecyclerView recyclerView, int newState)
if(!recyclerView.canScrollVertically(1))
Log.e(TAG,TAG+"<<end-333->>"); //Here is one way
super.onScrollStateChanged(recyclerView, newState);
@Override
public void onScrolled( RecyclerView recyclerView, int dx, int dy)
super.onScrolled(recyclerView, dx, dy);
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
Log.e(TAG,TAG+"<<end-->>"+linearLayoutManager.findLastVisibleItemPosition());
if(linearLayoutManager.findLastVisibleItemPosition() == linearLayoutManager.getItemCount()-1)
Log.e(TAG,TAG+"<<end-22->>"+linearLayoutManager.findLastVisibleItemPosition()); //Here is another way
);
【讨论】:
不工作。 On Scrolled 方法不调用仅 onScrollChanged 调用 @mobiledeveloper,我添加了两种方法,两种方法都可以正常工作。你检查了吗? 我只检查了这一项,但它不起作用。以上是关于RecylerView 的 onScrollChanged() 在 Android 中未检测到屏幕底部的主要内容,如果未能解决你的问题,请参考以下文章
XamarinAndroid组件教程RecylerView适配器动画动画种类
XamarinAndroid组件教程RecylerView动画组件使用动画