Android不推荐使用View作为 Recyclerview.Adapter的数据源;弊端像回收或复用就不多说了,要展示List<View>肯定是有原由的!
方式一、FrameLayout.addView:
public class ViewListAdapter extends RecyclerView.Adapter<ViewListAdapter.ViewHolder> {
private final List<View> viewList;
public ViewListAdapter(List<View> views) {
this.viewList = views;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// 使用 FrameLayout 作为容器,避免布局嵌套问题
FrameLayout container = new FrameLayout(parent.getContext());
container.setLayoutParams(new RecyclerView.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT
));
return new ViewHolder(container);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
View currentView = viewList.get(position);
// 移除容器中已有的 View(避免复用冲突)
holder.container.removeAllViews();
if(currentView.getParent() != null){
// 移除需要添加View的父布局(避免复用冲突)
((ViewGroup)currentView.getParent()).removeView(currentView);
}
// 确保 View 有布局参数
if (currentView.getLayoutParams() == null) {
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT
);
currentView.setLayoutParams(params);
}
holder.container.addView(currentView);
}
@Override
public int getItemCount() {
return viewList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
FrameLayout container;
public ViewHolder(View itemView) {
super(itemView);
container = (FrameLayout) itemView;
}
}
}
方式二、XML文件addView:
public class ViewAdapter extends RecyclerView.Adapter<ViewAdapter.ViewHolder> {
private final List<View> viewList;
public ViewAdapter(List<View> views) {
this.viewList = views;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_rv, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
View currentView = viewList.get(position);
// 移除容器中已有的 View(避免复用冲突)
holder.container.removeAllViews();
if(currentView.getParent() != null){
// 移除需要添加View的父布局(避免复用冲突)
((ViewGroup)currentView.getParent()).removeView(currentView);
}
holder.container.addView(currentView);
}
@Override
public int getItemCount() {
return viewList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
FrameLayout container;
public ViewHolder(View itemView) {
super(itemView);
container = (FrameLayout) itemView;
}
}
}
R.layout.layout_rv
XML
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:padding="10dp"
android:layout_height="300dp">
</FrameLayout>
方式三、viewType代替position:
XML
public class ViewTypeListAdapter extends RecyclerView.Adapter<ViewTypeListAdapter.ViewHolder> {
private final List<View> viewList;
public ViewTypeListAdapter(List<View> views) {
this.viewList = views;
}
@Override
public int getItemViewType(int position) {
return position;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ViewHolder(viewList.get(viewType));
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return viewList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
}
}
}
方式三不推荐,notifyDataSetChanged等刷新会有问题;
java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling androidx.recyclerview.widget.RecyclerView
IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
没必要使用RecyclerView时,可以使用 ScrollView + LinearLayout + addView