如何使用 StaggeredGridLayoutManager 在 recyclerview 中实现无限滚动(分页)

Posted

技术标签:

【中文标题】如何使用 StaggeredGridLayoutManager 在 recyclerview 中实现无限滚动(分页)【英文标题】:How to implement endless scroll (pagination) in recyclerview with StaggeredGridLayoutManager 【发布时间】:2021-12-05 05:48:48 【问题描述】:

您好,我有一个 recyclerview,其中包含从 firebase 加载的图像

注意:- 我已经看到有关此主题的其他答案,但大多数 答案是LinearLayoutManager 和一些GridLayout 但有 是我为StaggeredGridLayoutManager 找到的唯一一个答案,我没有 知道为什么它不适合我

如果您想要更多代码参考,请告诉我,我会更新 问题

Profile_Fragment.java

 public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) 
    View view = inflater.inflate(R.layout.fragment_profile, container, false);
    requireActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    ImageView accountSettings = view.findViewById(R.id.account_Settings);
    RelativeLayout relativeLayout = view.findViewById(R.id.snipet_profile);
    profilePhoto = relativeLayout.findViewById(R.id.circleImageView);
    editProfileButton = relativeLayout.findViewById(R.id.edit_profile_button);
    uploadImageButton = view.findViewById(R.id.upload_image_profile);
    progressBar = view.findViewById(R.id.progressBar_Profile);
    editProfileButton.setOnClickListener(v -> 
        Fragment edit_profile = new Edit_Profile();
        assert getFragmentManager() != null;
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        transaction.add(R.id.fragment_container, edit_profile);
        transaction.addToBackStack(String.valueOf(edit_profile));
        transaction.commit();
    );
    uploadImageButton.setOnClickListener(v -> 
        BottomSheet_Upload bottomSheetSettings = new BottomSheet_Upload();
        bottomSheetSettings.show(requireActivity().getSupportFragmentManager(), bottomSheetSettings.getTag());
    );
    accountSettings.setOnClickListener(
            v -> 
                BottomSheet_Settings bottomSheetSettings = new BottomSheet_Settings();
                bottomSheetSettings.show(requireActivity().getSupportFragmentManager(), bottomSheetSettings.getTag());
            
    );
    postRecyclerView = view.findViewById(R.id.postRecyclerViewProfile);
    StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
    postRecyclerView.setLayoutManager(
            staggeredGridLayoutManager // I have 3 rows
    );


    postRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() 
        @Override
        public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) 

            visibleItemCount = staggeredGridLayoutManager.getChildCount();
            totalItemCount = staggeredGridLayoutManager.getItemCount();
            int[] firstVisibleItems = null;
            firstVisibleItems = staggeredGridLayoutManager.findFirstVisibleItemPositions(firstVisibleItems);
            if (firstVisibleItems != null && firstVisibleItems.length > 0) 
                pastVisibleItems = firstVisibleItems[0];
            

            if (loading) 
                if ((visibleItemCount + pastVisibleItems) >= totalItemCount) 
                    loading = false;
                    getData();
                    Log.d("tag", "LOAD NEXT ITEM");
                
            
        
    );
    postRecyclerView.setVisibility(View.INVISIBLE);
    progressBar.setVisibility(View.VISIBLE);
    initImageLoader();
    setProfileImage();
    mUploads = new ArrayList<>();
    postsAdapter = new PostAdapter(getContext(), mUploads);
    postRecyclerView.setAdapter(postsAdapter);
    postsAdapter.setOnItemClickListener(Profile_Fragment.this);
    return view;


private void initImageLoader() 
    UniversalImageLoader universalImageLoader = new UniversalImageLoader(getContext());
    ImageLoader.getInstance().init(universalImageLoader.getConfig());


private void setProfileImage() 
    String imgUrl = "www.64.media.tumblr.com/1276b4edef49034af70bda14325385e3/d8872c747cafa206-96/s500x750/aa915fc49a84b5295f0cd44145d655b66eb906a6.jpg";
    UniversalImageLoader.setImage(imgUrl, profilePhoto, null, "https://");


private void getData() 
    mStorage = FirebaseStorage.getInstance();
    databaseEventListener = databaseReference.addValueEventListener(new ValueEventListener() 
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) 
            if (snapshot.exists()) 
                progressBar.setVisibility(View.GONE);
                postRecyclerView.setVisibility(View.VISIBLE);
                mUploads.clear();
                for (DataSnapshot dataSnapshot : snapshot.getChildren()) 
                    Upload upload = dataSnapshot.getValue(Upload.class);
                    Objects.requireNonNull(upload).setmKey(dataSnapshot.getKey());
                    mUploads.add(upload);


                

            

            //notify the adapter
            postsAdapter.notifyDataSetChanged();
            loading = true;
        

        @Override
        public void onCancelled(@NonNull DatabaseError error) 
            loading = true;
        
    );

更新 1

根据当前答案更改主问题代码并添加适配器类

问题

实现答案后没有错误,但图像没有加载,所以我用添加的答案更新了主代码

PostAdapter.java

public class PostAdapter extends RecyclerView.Adapter<PostAdapter.PostViewHolder> 
    public static List<Upload> mUploads;
    public Context mcontext;
    private OnItemClickListener mListener;
    /* ShimmerFrameLayout shimmerFrameLayout; */


    public PostAdapter(Context context, List<Upload> uploads) 
        mUploads = uploads;
        mcontext = context;
    

    @NonNull
    @Override
    public PostViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) 
        View view;
        LayoutInflater.from(mcontext).inflate(R.layout.post_item_container_profile, parent, false);
        view = LayoutInflater.from(parent.getContext()).inflate(R.layout.post_item_container_profile, parent, false);
        return new PostViewHolder(view);

    

    @Override
    public void onBindViewHolder(@NonNull PostViewHolder holder, int position) 
        Upload uploadCurrent = mUploads.get(position);
        Shimmer shimmer = new Shimmer.ColorHighlightBuilder()
                .setBaseColor(Color.parseColor("#F3F3F3"))
                .setBaseAlpha(1)
                .setHighlightColor(Color.parseColor("#E7E7E7"))
                .setHighlightAlpha(1)
                .setDropoff(50)
                .build();
        ShimmerDrawable shimmerDrawable = new ShimmerDrawable();
        shimmerDrawable.setShimmer(shimmer);
        Glide.with(mcontext)
                .load(uploadCurrent.getmImageUrl())
                .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
                .placeholder(shimmerDrawable)
                .centerCrop()
                .fitCenter()
                .into(holder.imageView);

    

    @Override
    public int getItemCount() 
        return mUploads.size();
    

    public void setOnItemClickListener(OnItemClickListener listener) 
        mListener = listener;

    

    public interface OnItemClickListener 
        void onClick(View view);

        void onItemClick(int position);

        void onDeleteClick(int position);
    

    public class PostViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,
            View.OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener 
        ShapeableImageView imageView;

        PostViewHolder(@NonNull View itemView) 
            super(itemView);
            imageView = itemView.findViewById(R.id.imagePost);

            itemView.setOnClickListener(this);
            itemView.setOnCreateContextMenuListener(this);
        

        @Override
        public void onClick(View v) 
            if (mListener != null) 
                int position = getAdapterPosition();
                if (position != RecyclerView.NO_POSITION) 
                    mListener.onItemClick(position);
                
            
        

        @Override
        public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) 
            MenuItem delete = menu.add(Menu.NONE, 2, 2, "Delete");
            delete.setOnMenuItemClickListener(this);
        

        @Override
        public boolean onMenuItemClick(MenuItem item) 
            if (mListener != null) 
                int position = getAdapterPosition();
                if (position != RecyclerView.NO_POSITION) 
                    if (item.getItemId() == 2) 
                        mListener.onDeleteClick(position);
                        return true;
                    
                
            
            return false;
        
    

【问题讨论】:

您可以使用此示例enter link description here @OmidZakeri 这是我上面提到的答案,对我来说不起作用,我在实施该答案后发现了一些错误,但后来我不知道我可以把 getData();方法,总之对我来说是一团糟 @VasantRaval 您在实施链接中给出的解决方案时遇到什么问题? @akhilnair 你好兄弟谢谢你的回复我已经添加了我面临的 StaggeredGridLayoutManager 问题 【参考方案1】:

对于您的第一个问题,您已经有了解决方案。

StaggeredGridLayoutManager staggeredGridLayoutManager = new 
   StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
    postRecyclerView.setLayoutManager(
            staggeredGridLayoutManager // I have 3 rows
    );
    

第二个问题:

postRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener(
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) 

        visibleItemCount = staggeredGridLayoutManager .getChildCount();
        totalItemCount = staggeredGridLayoutManager .getItemCount();
        int[] firstVisibleItems = null;
        firstVisibleItems = mLayoutManager.findFirstVisibleItemPositions(firstVisibleItems);
        if(firstVisibleItems != null && firstVisibleItems.length > 0) 
            pastVisibleItems = firstVisibleItems[0];
        

        if (loading) 
            if ((visibleItemCount + pastVisibleItems) >= totalItemCount) 
                loading = false;
                getData()
            
        
    
 );
 ..........
 ..........
  private void getData() 
    mStorage = FirebaseStorage.getInstance();
    databaseEventListener = databaseReference.addValueEventListener(new ValueEventListener() 
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) 
            if (snapshot.exists()) 
                progressBar.setVisibility(View.GONE);
                postRecyclerView.setVisibility(View.VISIBLE);
                mUploads.clear();
                for (DataSnapshot dataSnapshot : snapshot.getChildren()) 
                    Upload upload = dataSnapshot.getValue(Upload.class);
                    Objects.requireNonNull(upload).setmKey(dataSnapshot.getKey());
                    mUploads.add(upload);
                
            
            //notify the adapter
            postsAdapter.notifyDataSetChanged();
            loading = true;
        

        @Override
        public void onCancelled(@NonNull DatabaseError error) 
           loading = true;
        
    );

您可能必须首先在您的onCreate() 中调用getData(),以便在屏幕上加载一些数据并且您有滚动行为。

更新: StaggeredGridLayoutManager 中的第二个参数是方向,因此您必须传递方向 StaggeredGridLayoutManager.VERTICAL 而不是 StaggeredGridLayoutManager.VERTICAL

【讨论】:

感谢您的回答我尝试了一种初始化 StaggeredGridLayoutManager 的方法,但出现错误请您查看我更新的问题 @VasantRaval 我已经更新了答案。让我知道它是否有效。 感谢您的回复,我已经实施了您的更新答案,没有问题,但图像未显示 如果您发现此答案对您提到的问题有帮助,请接受它,因为它对社区中的其他人有帮助。 在适配器中加载图像的方式可能存在一些问题。

以上是关于如何使用 StaggeredGridLayoutManager 在 recyclerview 中实现无限滚动(分页)的主要内容,如果未能解决你的问题,请参考以下文章

如何使用本机反应创建登录以及如何验证会话

如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]

如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?

如何使用laravel保存所有行数据每个行名或相等

如何使用 Math.Net 连接矩阵。如何使用 Math.Net 调用特定的行或列?

WSARecv 如何使用 lpOverlapped?如何手动发出事件信号?