我正在尝试重新创建:
我有一个数据列表:
List<Block> blocks;
Block.java
类有一个方法getNumBlocks()
,它返回该项应显示的块数。块的数量范围可以从小到1块到大到20块。
我创建了一个普通的RecyclerView适配器,以及块的ImageView
布局:
public class BlockAdapter extends RecyclerView.Adapter<BlockAdapter.ViewHolder> {
private Context context;
private List<Block> blocks;
public BlockAdapter(Context context, List<Block> blocks) {
this.context = context;
this.blocks = blocks;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ImageView block;
public ViewHolder(View v) {
super(v);
block = (ImageView) v.findViewById(R.id.block);
}
}
@Override
public BlockAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.block_layout, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
Block block = blocks.get(position);
// How to use block.getNumBlocks() to show the correct number of blocks?
}
@Override
public int getItemCount() {
return blocks.size();
}
}
以下是block_layout.xml
(它只是一个空的LinearLayout,应该在此LinearLayout中添加块):
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/card_bg"
android:padding="16dp">
</LinearLayout>
这是block.xml
布局:
<ImageView
android:id="@+id/block"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp" />
所以我的问题是,如何实现这一点,以便它显示每个RecyclerView项目的正确数量的块?
表现明智的最佳方式是什么?
答案 0 :(得分:2)
你关心表现很好。每次要显示一行时创建新的ImageViews
都违背了回收视图的想法。基本上在滚动时,您只会重复使用顶级视图,但每次在屏幕上显示任何项目时仍会创建新的ImageViews
。
为了解决这个问题,您可以创建自己的视图池:
public class BlockAdapter extends RecyclerView.Adapter<BlockAdapter.ViewHolder> {
private final List<Block> blocks;
private final List<ImageView> imageViewPool = new LinkedList<>();
public BlockAdapter(List<Block> blocks) {
this.blocks = blocks;
}
@Override
public int getItemCount() {
return blocks.size();
}
@Override
public BlockAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.block_layout, parent, false));
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.bind(blocks.get(position));
}
public class ViewHolder extends RecyclerView.ViewHolder {
private final List<ImageView> imageViews = new ArrayList<>();
private final ViewGroup container;
public ViewHolder(View v) {
super(v);
container = (ViewGroup) itemView;
}
public void bind(Block block) {
recycleImageViews();
for (int i = 0; i < block.getNumBlocks(); ++i) {
final ImageView imageView = getRecycledImageViewOrCreate();
imageViews.add(imageView);
container.addView(imageView);
}
}
private ImageView getRecycledImageViewOrCreate() {
if (imageViewPool.isEmpty()) {
return (ImageView)LayoutInflater.from(container.getContext()).inflate(R.layout.block, container, false);
}
return imageViewPool.remove(0);
}
public void recycleImageViews() {
imageViewPool.addAll(imageViews);
imageViews.clear();
container.removeAllViews();
}
}
@Override
public void onViewRecycled(ViewHolder holder) {
super.onViewRecycled(holder);
holder.recycleImageViews();
}
}
这个解决方案背后的想法与RecyclerView
非常相似。
每次ViewHolder
想要展示子项时,它都会:
imageViewPool
获取ImageView。如果池中没有备用的,则新的将膨胀。 ImageView
附加到自身。稍后,当重新使用或回收特定ViewHolder
时,它将:
ImageViews
。ImageViews
返回到可重复使用的池中,以便屏幕上显示的下一个项目可以使用这些项目。答案 1 :(得分:0)
首先更改viewholader并获取根布局的参考 -
public class ViewHolder extends RecyclerView.ViewHolder {
LinearLayout root;
public ViewHolder(View v) {
super(v);
root = (LinearLayout) v.findViewById(R.id.root);
}
}
之后,内部bindview持有者遍历一个块大小的循环
for(int i=0;i<block.size;i++) {
ImageView blockImg = new ImageView(context);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(left, top, right, bottom);
blockImg.setLayoutParams(lp);
holder.root.addView(blockImg);
}
使用LayoutParams,您也可以提供所需的边距并将其应用于imageview