Recyclerview瀑布流上下滑动的时候item位置错乱,闪烁,item间距错乱问题解决方法

时间:2024-04-13 07:23:28

之前要做一个瀑布流效果 需要动态设置图片的高度  按照普通的recyclerview设置瀑布流的操作来写  结果出现一个现象:向下滑动超出一屏的距离再滑动回顶部的时候  出现Item错位,间距消失等问题 (注:截图没体现出瀑布流效果是因为这几张图片的高度一样 )

先贴效果图和有问题的代码

效果图:

Recyclerview瀑布流上下滑动的时候item位置错乱,闪烁,item间距错乱问题解决方法

有问题的代码:

  private void initRecyclerview() {
        mRecyclerviewFind.setHasFixedSize(true);
        staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
        mRecyclerviewFind.setLayoutManager(staggeredGridLayoutManager);
        mRecyclerviewFind.setItemAnimator(null);
        if (mRecyclerviewFind.getItemDecorationCount() == 0) {
            mRecyclerviewFind.addItemDecoration(new StaggeredDividerItemDecorationFind(getActivity(), DisplayUtils.dp2px(getActivity(), 4)));
        }

        mStaggerAdapter = new MyRecyclerAdapter(getActivity(),mDataList);
        mStaggerAdapter.setHasStableIds(true);
        mRecyclerviewFind.setAdapter(mStaggerAdapter);

 {

    }
  class MyRecyclerAdapter  extends  RecyclerView.Adapter<MyRecyclerAdapter.MyViewHolder>{
        private List<FindBean.DataBean> mDatas;
        private Context mContext;
        private LayoutInflater inflater;
        private HashMap<Integer,Integer> map=new HashMap<>();
        private int item_width=App.SCREEN_WIDTH/2-DisplayUtils.dp2px(getActivity(),2);  //item宽度

         public MyRecyclerAdapter(Context context,List<FindBean.DataBean> datas){
             this. mContext=context;
             this. mDatas=datas;
             inflater=LayoutInflater. from(mContext);
         }

         
         @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = inflater.inflate(R.layout.adapter_find,parent, false);
            MyViewHolder holder= new MyViewHolder(view);
            return holder;
        }


         @Override
        public void onBindViewHolder(final MyViewHolder holder, final int position)
        {

            try {
                int width = mDatas.get(position).getCover().getWidth();
                int height = mDatas.get(position).getCover().getHeight();
                ViewGroup.LayoutParams layoutParams = holder.mIvPic.getLayoutParams();
                layoutParams.width=item_width;
                layoutParams.height=height*layoutParams.width/width;
                holder.mIvPic.setLayoutParams(layoutParams);
                Log.e("xxxxxxxx",position+"----宽:"+layoutParams.width+"------高"+layoutParams.height);

                FindBean.DataBean bean = mDatas.get(position);
                FindBean.DataBean.AuthorInfoBean authorInfo = bean.getAuthorInfo();
                if (null!=authorInfo){
                    holder.mTvName.setText(authorInfo.getName());
                }

                holder.mTvTitle.setText(bean.getTitle());
//                RoundedCorners roundedCorners = new RoundedCorners(DisplayUtils.dp2px(getActivity(), 5));
//                //通过RequestOptions扩展功能,override:采样率,因为ImageView就这么大,可以压缩图片,降低内存消耗
//                RequestOptions options = RequestOptions.bitmapTransform(roundedCorners).override(300, 300);
                //加载图片
                GlideApp.with(getActivity()).asBitmap().placeholder(R.mipmap.ic_pic_placeholder).load( bean.getCover().getUrl()).diskCacheStrategy(DiskCacheStrategy.ALL).into(holder.mIvPic);
                if (null!=authorInfo)
                GlideApp.with(getActivity()).asBitmap().placeholder(R.mipmap.ic_userdefault).apply(RequestOptions.circleCropTransform()).load(authorInfo.getOwnerUrl()).into(holder.mIvUserIcon);
                holder.mIvLaudView.setBackgroundResource(true == mDatas.get(position).isLaudedStatus() ? R.mipmap.ic_like_red : R.mipmap.ic_like_black);
            } catch (Exception e) {
                e.printStackTrace();
            }

            holder.mIvPic.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
             
                }
            });
            
            holder.mIvLaudView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                }
            });
        }

         
         @Override
        public int getItemCount() {
            return mDatas.size();
        }
         
        class MyViewHolder extends RecyclerView.ViewHolder{
            TextView mTvTitle;
            TextView mTvName;
            ImageView mIvPic;
            ImageView mIvUserIcon;
            ImageView mIvLaudView;
            RelativeLayout mParentView;

            public MyViewHolder(View itemView) {
                super(itemView);
                mTvName= itemView.findViewById(R.id.tv_name);
                mTvTitle= itemView.findViewById(R.id.tv_title);
                mIvPic= itemView.findViewById(R.id.iv_pic);
                mIvUserIcon= itemView.findViewById(R.id.iv_usericon);
                mIvLaudView= itemView.findViewById(R.id.iv_laudedstatus);
                mParentView= itemView.findViewById(R.id.parent);
            }
        }
    }

然后我百度recyclerview瀑布流滑动item错乱问题 发现很多的解决办法

最多的就是设置以下代码

staggeredGridLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);//不设置的话,图片闪烁错位,有可能有整列错位的情况。

        mRecyclerviewFind.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                staggeredGridLayoutManager.invalidateSpanAssignments();
            }
        });

我设置setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE)后发现item都不可见了   然后继续找解决办法

网上说在adapter的layout布局外面套一层Framelayout,我在布局外面套了一层RelaytiveLayout,发现有效果,Item可见了,但是滑动数据错乱问题依旧没有解决

最后查到有的解决方案是重写getitemId   返回position  有的是重写  getItemViewType方法  return position,没办法  只好一个个试一下  结果发现重写getItemViewType方法有效果,Item不再错位

在adapter中重写

      @Override
         public int getItemViewType(int position) {
             return position;
         }

但是现在还有个问题 就是每次滑动  Item虽然不错位  但是会闪烁和间距消失(就是图片上同一行的两个item左边的item右间距没了 右边Item的左间距没有变成右间距) 如图:

Recyclerview瀑布流上下滑动的时候item位置错乱,闪烁,item间距错乱问题解决方法

 

我猜测是滑动的时候重绘引起的 于是将下面这段代码注销  

        mRecyclerviewFind.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                staggeredGridLayoutManager.invalidateSpanAssignments();
            }
        });

Ok,功夫不负有心人 ,终于  问题解决  特此记录下。希望能帮到遇到同样问题的你

最后贴上我完整的正确代码:

public class StaggeredDividerItemDecorationFind extends RecyclerView.ItemDecoration {
    private Context context;
    private int interval;

    public StaggeredDividerItemDecorationFind(Context context, int interval) {
        this.context = context;
        this.interval = interval;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
        // 获取item在span中的下标
        int spanIndex = params.getSpanIndex();
        int interval = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                this.interval, context.getResources().getDisplayMetrics());
        // 中间间隔
        if (spanIndex % 2 == 0) {       //左
            outRect.left = 0;
            outRect.right=interval/2;
        } else {                        //右
            // item为奇数位,设置其左间隔为5dp
            outRect.left=interval/2;
            outRect.right = 0;
        }
        // 下方间隔
        outRect.bottom = interval;
    }
}
    private void initRecyclerview() {
        mRecyclerviewFind.setHasFixedSize(true);
        staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
        //staggeredGridLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);//不设置的话,图片闪烁错位,有可能有整列错位的情况。
        mRecyclerviewFind.setLayoutManager(staggeredGridLayoutManager);
        mRecyclerviewFind.setItemAnimator(null);
        if (mRecyclerviewFind.getItemDecorationCount() == 0) {
            mRecyclerviewFind.addItemDecoration(new StaggeredDividerItemDecorationFind(getActivity(), DisplayUtils.dp2px(getActivity(), 4)));
        }
        mStaggerAdapter = new MyRecyclerAdapter(getActivity(),mDataList);
        mStaggerAdapter.setHasStableIds(true);
        mRecyclerviewFind.setAdapter(mStaggerAdapter);
    }
 class MyRecyclerAdapter  extends  RecyclerView.Adapter<MyRecyclerAdapter.MyViewHolder>{
        private List<FindBean.DataBean> mDatas;
        private Context mContext;
        private LayoutInflater inflater;
        private HashMap<Integer,Integer> map=new HashMap<>();
        private int item_width=App.SCREEN_WIDTH/2-DisplayUtils.dp2px(getActivity(),2);  //item宽度

         public MyRecyclerAdapter(Context context,List<FindBean.DataBean> datas){
             this. mContext=context;
             this. mDatas=datas;
             inflater=LayoutInflater. from(mContext);
         }


         @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = inflater.inflate(R.layout.adapter_find,parent, false);
            MyViewHolder holder= new MyViewHolder(view);
            return holder;
        }


         @Override
         public int getItemViewType(int position) {
             return position;
         }

         @Override
        public void onBindViewHolder(final MyViewHolder holder, final int position)
        {

            try {
                //动态设置图片的高度
                int width = mDatas.get(position).getCover().getWidth();
                int height = mDatas.get(position).getCover().getHeight();
                ViewGroup.LayoutParams layoutParams = holder.mIvPic.getLayoutParams();
                layoutParams.width=item_width;
                layoutParams.height=height*layoutParams.width/width;
                holder.mIvPic.setLayoutParams(layoutParams);
                Log.e("xxxxxxxx",position+"----宽:"+layoutParams.width+"------高"+layoutParams.height);

                FindBean.DataBean bean = mDatas.get(position);
                FindBean.DataBean.AuthorInfoBean authorInfo = bean.getAuthorInfo();
                if (null!=authorInfo){
                    holder.mTvName.setText(authorInfo.getName());
                }

                holder.mTvTitle.setText(bean.getTitle());
//                RoundedCorners roundedCorners = new RoundedCorners(DisplayUtils.dp2px(getActivity(), 5));
//                //通过RequestOptions扩展功能,override:采样率,因为ImageView就这么大,可以压缩图片,降低内存消耗
//                RequestOptions options = RequestOptions.bitmapTransform(roundedCorners).override(300, 300);
                //加载图片
                GlideApp.with(getActivity()).asBitmap().placeholder(R.mipmap.ic_pic_placeholder).load( bean.getCover().getUrl()).diskCacheStrategy(DiskCacheStrategy.ALL).into(holder.mIvPic);
                if (null!=authorInfo)
                GlideApp.with(getActivity()).asBitmap().placeholder(R.mipmap.ic_userdefault).apply(RequestOptions.circleCropTransform()).load(authorInfo.getOwnerUrl()).into(holder.mIvUserIcon);
                holder.mIvLaudView.setBackgroundResource(true == mDatas.get(position).isLaudedStatus() ? R.mipmap.ic_like_red : R.mipmap.ic_like_black);
            } catch (Exception e) {
                e.printStackTrace();
            }

            holder.mIvPic.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                }
            });

            holder.mIvLaudView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
        
                }
            });
        }


         @Override
        public int getItemCount() {
            return mDatas.size();
        }

        class MyViewHolder extends RecyclerView.ViewHolder{
            TextView mTvTitle;
            TextView mTvName;
            ImageView mIvPic;
            ImageView mIvUserIcon;
            ImageView mIvLaudView;

            public MyViewHolder(View itemView) {
                super(itemView);
                mTvName= itemView.findViewById(R.id.tv_name);
                mTvTitle= itemView.findViewById(R.id.tv_title);
                mIvPic= itemView.findViewById(R.id.iv_pic);
                mIvUserIcon= itemView.findViewById(R.id.iv_usericon);
                mIvLaudView= itemView.findViewById(R.id.iv_laudedstatus);
    
            }
        }
    }
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white">


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <RelativeLayout
            android:id="@+id/rl_pic"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <ImageView
                android:id="@+id/iv_pic"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@mipmap/ic_pic_placeholder"
                android:scaleType="centerCrop" />


            <ImageView
                android:id="@+id/iv_laudedstatus"
                android:layout_width="18dp"
                android:layout_height="17dp"
                android:layout_alignParentRight="true"
                android:layout_alignParentTop="true"
                android:layout_marginRight="10dp"
                android:layout_marginTop="10dp"
                android:background="@mipmap/ic_like_black" />
        </RelativeLayout>


        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/rl_pic"
            android:layout_marginLeft="18dp"
            android:background="@mipmap/ic_arrow_up_white" />

        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/rl_pic"
            android:layout_marginBottom="14dp">


            <ImageView
                android:id="@+id/iv_usericon"
                android:layout_width="24dp"
                android:layout_height="24dp"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="11dp"
                android:layout_marginTop="10dp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent" />


            <TextView
                android:id="@+id/tv_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="6dp"
                android:singleLine="true"
                android:text=""
                android:textColor="#262628"
                android:textSize="12dp"
                android:textStyle="bold"
                app:layout_constraintBottom_toBottomOf="@+id/iv_usericon"
                app:layout_constraintLeft_toRightOf="@id/iv_usericon"
                app:layout_constraintTop_toTopOf="@+id/iv_usericon" />

            <TextView
                android:id="@+id/tv_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dp"
                android:layout_marginLeft="11dp"
                android:layout_marginRight="11dp"
                android:layout_marginTop="9dp"
                android:ellipsize="end"
                android:fontFamily="@font/roboto_light"
                android:lineSpacingExtra="3dp"
                android:maxLines="2"
                android:text=""
                android:textColor="#676768"
                android:textSize="12dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@id/iv_usericon" />

        </android.support.constraint.ConstraintLayout>

    </RelativeLayout>
</RelativeLayout>

总结:在我遇到的问题里  实际有效的解决方案是在adapter里重写getItemViewType方法

      @Override
         public int getItemViewType(int position) {
             return position;
         }