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 来获取数据。我已经使用 RecyclerViewonScrollListener 来检测它是否到达结束,但代码仅在我打开屏幕时第一次运行,但到达屏幕结束时它不起作用. 如何检查列表何时结束。

片段代码:

@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 其中listrecyclerview 实例,您在哪里启动或设置了适配器? 我在从 API 获取数据时设置了适配器 我没有找到你究竟在哪里创建了RecyclerViewlist 的实例 【参考方案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动画组件使用动画

recylerView 未显示在应用程序中

RecylerView 的 onScrollChanged() 在 Android 中未检测到屏幕底部

一篇博客理解Recyclerview的使用

android Fragment - 我需要从 sqlite 检索数据并填充到 recylerview 的方法