无第三方库实现RecyclerView粘性Header时透明度导致重复问题求助
解决RecyclerView粘性Header设置透明度后重复显示的问题
这个问题的核心是:当你给悬浮Header设置透明度后,列表中原本被悬浮Header覆盖的真实Header会透过透明区域显示出来,看起来像是重复了。
给你两个可行的解决办法:
方法一:绘制悬浮Header前先覆盖背景
修改StickyHeaderDecoration里的onDrawOver方法,在绘制悬浮Header视图之前,先用RecyclerView的背景色填充悬浮区域,把下面的真实Header挡住:
@Override public void onDrawOver(Canvas canvas, RecyclerView recyclerView, RecyclerView.State state) { super.onDrawOver(canvas, recyclerView, state); int firstVisibleItemPosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition(); if (firstVisibleItemPosition == RecyclerView.NO_POSITION) { return; } View currentHeader = getHeaderView(recyclerView, firstVisibleItemPosition); fixLayoutSize(recyclerView, currentHeader); int contactPoint = currentHeader.getBottom(); View childInContact = recyclerView.findChildViewUnder(canvas.getWidth() / 2, contactPoint + 1); if (childInContact != null && isHeader(recyclerView.getChildAdapterPosition(childInContact))) { moveHeader(canvas, currentHeader, childInContact); return; } // 新增:用背景色填充悬浮区域,避免下方Header透出 int bgColor = recyclerView.getBackground() != null ? ((ColorDrawable) recyclerView.getBackground()).getColor() : Color.WHITE; Paint bgPaint = new Paint(); bgPaint.setColor(bgColor); canvas.drawRect(currentHeader.getLeft(), currentHeader.getTop(), currentHeader.getRight(), currentHeader.getBottom(), bgPaint); canvas.save(); canvas.translate(0, 0); currentHeader.draw(canvas); canvas.restore(); }
方法二:隐藏即将被覆盖的真实Header
在Adapter的onBindViewHolder方法里,判断当前Header是否处于被悬浮Header覆盖的位置,如果是,就把它设为不可见:
@Override public void onBindViewHolder(ViewHolder holder, int position) { // 原有绑定逻辑... // 判断当前item是Header,且不是第一个可见的Header(即被悬浮Header覆盖的那个) if (isHeader(position)) { RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if (layoutManager instanceof LinearLayoutManager) { int firstVisiblePos = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition(); // 如果当前Header不是第一个可见的Header,且它的顶部已经进入悬浮区域 if (position != firstVisiblePos) { View headerView = holder.itemView; int[] location = new int[2]; headerView.getLocationOnScreen(location); int recyclerViewTop = recyclerView.getTop() + recyclerView.getPaddingTop(); if (location[1] <= recyclerViewTop + headerView.getHeight()) { headerView.setVisibility(View.INVISIBLE); } else { headerView.setVisibility(View.VISIBLE); } } else { holder.itemView.setVisibility(View.VISIBLE); } } } }
注意方法二需要在Adapter里持有RecyclerView的引用,或者通过其他方式获取布局管理器的状态。优先用方法一,逻辑更简单,不会影响列表item的复用状态。
内容的提问来源于stack exchange,提问作者GHH
相关产品推荐
相关产品推荐

