RecyclerView 瀑布流错乱

记录一下,瀑布流错乱问题

问题

主要是在Item中图片并不会固定宽高,而是在加载后再去计算的,所以在复用子View时不断的进行重新排版,导致最后展示时出现了偏差,也就是错乱留白。

解决办法

解决办法也就是针对布局和留白去进行处理,总的来说这几句话:在布局时先计算布局尺寸,在滚到顶部时处理留白,在加载数据时注意刷新(刷新会重置布局和保存的尺寸)。

以下解决方法可重叠使用。

  1. layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
  2. 按照图片的宽高,在界面加载前,先设置ImageView的布局
    if (items.get(position).getHeight() > 0) {
                ViewGroup.LayoutParams layoutParams = imageView.getLayoutParams();
                layoutParams.height = items.get(position).getHeight();
            }
    
            Glide.with(context).load(items.get(position).getImg_url()).asBitmap()
                    .into(new SimpleTarget(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
                        @Override
                        public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
                            if (position != RecyclerView.NO_POSITION) {
                                if (items.get(position).getHeight() <= 0) {
                                    int imageWidth = resource.getWidth();
                                    int imageHeight = resource.getHeight();
                                    int width = (ScreenUtils.getScreenWidth(context) - DensityUtil.dip2px(context, 30)) / 2;
                                    //宽度固定,然后根据原始宽高比得到此固定宽度需要的高度
                                    int height = width * imageHeight / imageWidth;
                                    LogUtils.e("设置的高:" + height);
                                    items.get(position).setHeight(height);
                                    ViewGroup.LayoutParams para = item_note_img_iv.getLayoutParams();
                                    para.height = height;
                                    para.width = width;
                                }
                                imageView.setImageBitmap(resource);
                            }
                        }
                    });
    
  3. 实际上解决错乱与留白的问题 主要原因在于加载更多数据之后 使用的是notifyDataSetChanged()该方法将刷新一整个Recycleview的数据;所以解决方案将 notifyDataSetChanged()替换成 notifyItemRangeInserted(int positionStart, int itemCount)进行新增数据局部刷新。
  4. 第四种方法就是在滚动到顶部时,进行留白处理
    //防止顶部空白
    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    	@Override
    	public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
    		super.onScrollStateChanged(recyclerView, newState);
            //2为列数
    		int[] first = new int[2];
    		layoutManager.findFirstCompletelyVisibleItemPositions(first);
    		if (newState == RecyclerView.SCROLL_STATE_IDLE ){
    			if (first[0] == 1 || first[1] == 1) {
    				layoutManager.invalidateSpanAssignments();
    			}
    		}
    	}
    });

     

  5. 还有一种方法说是重写getItemViewType,但我没试过

    @Override
    public int getItemViewType(int position) {
          return Math.round((float) App.SCREEN_WIDTH / (float)         
          mList.get(position).getHeight() * 10f);
    }

     

你可能感兴趣的:(Android错误)