设置RecyclerView的ViewHolder的显示和隐藏
如果是ListView
的话,可以直接设置item
的visibility = View.GONE
就可以隐藏得一干二净。但如果是RecyclerView
的话,仅仅只是设置了item
的visibility = View.GONE
且没有任何margin
不会有同样的效果,还是会在隐藏了的item的位置留下空白。需要设置itemView
的LayoutParams
,以及把尽量不用margin
而是用padding
代替。
务必要在onAttachedToRecyclerView
之前设置LayoutParams
,而且这个LayoutParams
是RecyclerView.LayoutParams
。如果不小心写成LinearLayout.Params
或者RelativeLayout.LayoutParams
的话,可能会报错或者隐藏失败。
文章目录
可行的两种方法:
(1) ViewHolder里面设置LayoutParams
网上有一种最直接的方法,就是直接在ViewHolder里面加上一个setVisibility()
,然后在onBindViewHolder()
直接调用就可以了。
public static class ViewHolder extends RecyclerView.ViewHolder {
public void ViewHolder(View itemView) {
super(itemView);
}
public void setVisibility(int visibility) {
itemView.setVisibility(visibility);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) itemView.getLayoutParams();
if (visibility == View.VISIBLE) {
params.width = RecyclerView.LayoutParams.MATCH_PARENT;
params.height = RecyclerView.LayoutParams.WRAP_CONTENT;
} else {
params.width = 0;
params.height = 0;
}
itemView.setLayoutParams(params);
}
}
(2) 在onCreateViewHolder里面设置LayoutParams
onCreateViewHolder()
可以接收参数viewType
来判断要不要隐藏,所以要重写getItemViewType()
。
@Override
public int getItemViewType(int position) {
return mDataList.get(position).getVisibility();
}
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.item_recycler_view_layout, parent, false);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();
if (viewType == View.VISIBLE) {
params.width = RecyclerView.LayoutParams.MATCH_PARENT;
params.height = RecyclerView.LayoutParams.WRAP_CONTENT;
} else {
params.width = 0;
params.height = 0;
}
view.setLayoutParams(params);
return new ViewHolder(view);
}
(3) 如果好死不死设置了ItemDecoration的getItemOffsets的话
上面两种情况都是针对item本身设置的显示和隐藏的,所以才会把margin换padding。如果想做到显示出来的item保留设置好的ItemDecoration,隐藏的item没有ItemDecoration的话,那么就在上面改LayoutParams
的基础上,再修改一下ItemDecoration的getItemOffsets的实现。既然可以通过判断ViewType在OnCreateViewHolder
里面设置LayoutParams
,那一样可以通过获取的ViewType在getItemOffsets
里面设置距离。
public class SpaceDecoration extends RecyclerView.ItemDecoration {
private int mDistance;
public SpaceDecoration(int distance) {
mDistance = distance;
}
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
// 获得当前这个item在Adapter中的位置
int position = parent.getChildAdapterPosition(view);
if (parent.getAdpater() != null) {
// 获得这个item的ViewType
int viewType = parent.getAdapter().getItemViewType(position);
if (viewType == View.VISIBLE) {
outRect.right = mDistance;
} else {
outRect.right = 0;
}
}
}
}