这是我取得的成就?每个部分中 3 不同的部分, 10 不同的项。
以下是教程 link我正在关注以下是屏幕截图:
尝试为每个部分显示different Views
。的像:
对于第1节(layout_1.xml)
对于第2节(layout_2.xml)
对于第3节(layout_3.xml)
但在每个区中显示布局视图 <{1}} ...(第1,2,3节)
我可以知道我在代码中的错误,我错过了什么吗?
layout_1.xml
答案 0 :(得分:8)
在内部适配器的getItemViewType
:
@Override
public int getItemViewType(int position) {
if (position == 0) {
return 0;
} else if(position == 1) {
return 1;
} else {
return 2;
}
}
答案 1 :(得分:2)
根据recyclerview中的位置使用多个布局,你必须覆盖适配器内的getItemViewType(int position)方法: -
@Override
public int getItemViewType(int position) {
if(position==0)
return 0;
else if(position==1)
return 1;
else
return 2;
}
答案 2 :(得分:1)
<强> FYI 强>
RecyclerView还可用于扩充多种视图类型。
尝试
@Override
public SingleItemRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
switch (i) {
case 0:
View viewONE = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_1, null, false);
SingleItemRowHolder rowONE = new SingleItemRowHolder(viewONE);
return rowONE;
case 1:
View viewTWO = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_2, null, false);
SingleItemRowHolderTwo rowTWO = new SingleItemRowHolderTwo (viewTWO);
return rowTWO;
case 2:
View viewTHREE = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_3, null, false);
SingleItemRowHolderThree rowTHREE = new SingleItemRowHolderThree(viewTHREE);
return rowTHREE;
}
return null;
}
阅读 RecyclerView can also be used to inflate multiple view types
答案 3 :(得分:1)
正如已经提到的那样,为了getItemViewType
类的RecyclerView.Adapter
方法,因为如果您将在实现该方法时看到它,您将看到它只返回0
时间。
public int getItemViewType(int position) {
return 0;
}
此处调整适配器的代码,以解决您的问题。
public class SectionListDataAdapter extends RecyclerView.Adapter<SectionListDataAdapter.SingleItemRowHolder> {
private static final int ITEM_TYPE_ROW_1 = 0;
private static final int ITEM_TYPE_ROW_2 = 1;
private static final int ITEM_TYPE_ROW_3 = 2;
private ArrayList<SingleItemModel> itemsList;
private Context context;
public SectionListDataAdapter(Context context, ArrayList<SingleItemModel> itemsList) {
this.itemsList = itemsList;
this.context = context;
}
@Override
public int getItemViewType(int position) {
switch (position) {
case 0:
return ITEM_TYPE_ROW_1;
case 1:
return ITEM_TYPE_ROW_2;
case 2:
return ITEM_TYPE_ROW_3;
}
throw new RuntimeException(String.format("unexpected position - %d", position));
}
@Override
public SingleItemRowHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
switch (viewType) {
case ITEM_TYPE_ROW_1:
View viewOne = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_1, null, false);
return new SingleItemRowHolder(viewOne);
case ITEM_TYPE_ROW_2:
View viewTwo = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_2, null, false);
return new SingleItemRowHolder(viewTwo);
case ITEM_TYPE_ROW_3:
View viewThree = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_3, null, false);
return new SingleItemRowHolder(viewThree);
}
throw new RuntimeException(String.format("unexpected viewType - %d", viewType));
}
@Override
public void onBindViewHolder(SingleItemRowHolder holder, int i) {
SingleItemModel singleItem = itemsList.get(i);
holder.tvTitle.setText(singleItem.getName());
}
@Override
public int getItemCount() {
return (null != itemsList ? itemsList.size() : 0);
}
class SingleItemRowHolder extends RecyclerView.ViewHolder {
TextView tvTitle;
ImageView itemImage;
public SingleItemRowHolder(View view) {
super(view);
this.tvTitle = (TextView) view.findViewById(R.id.tvTitle);
this.itemImage = (ImageView) view.findViewById(R.id.itemImage);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(v.getContext(), tvTitle.getText(), Toast.LENGTH_SHORT).show();
}
});
}
}
}
答案 4 :(得分:1)
您可以通过更简单的方式完成此操作。在初始化适配器时传递任何flag
。
public class SectionListDataAdapter extends RecyclerView.Adapter<SectionListDataAdapter.SingleItemRowHolder> {
private ArrayList<SingleItemModel> itemsList;
private Context context;
private int view;
public SectionListDataAdapter(Context context, ArrayList<SingleItemModel> itemsList, int layoutFlag) {
this.itemsList = itemsList;
this.context = context;
switch(layoutFlag) {
case 0:
view = R.layout.layout_1;
break;
case 1:
view = R.layout.layout_2;
break;
case 2:
view = R.layout.layout_3;
break;
}
}
...
...
...
}
使用此view
进行布局参考。您只需要确定在设置适配器时要充气的布局。
答案 5 :(得分:0)
您需要覆盖方法
int getItemViewType (int position)
它接收行号,你需要返回行的“类型”,即1 2或3。
然后将结果传递给onCreateViewHolder。
答案 6 :(得分:0)
例如,如果要显示此视图列表:
TYPE1 TYPE2 3型 TYPE1 TYPE2 TYPE3
然后应该做的工作:
public class SectionListDataAdapter extends RecyclerView.Adapter<SectionListDataAdapter.SingleItemRowHolder> {
private static final int ITEM_TYPE_ROW_1 = 0;
private static final int ITEM_TYPE_ROW_2 = 1;
private static final int ITEM_TYPE_ROW_3 = 2;
private ArrayList<SingleItemModel> itemsList;
private Context context;
private ArrayList<Integer> viewTypes = new ArrayList<>();
public SectionListDataAdapter(Context context, ArrayList<SingleItemModel> itemsList) {
this.itemsList = itemsList;
this.context = context;
viewTypes.add(ITEM_TYPE_ROW_1);
viewTypes.add(ITEM_TYPE_ROW_2);
viewTypes.add(ITEM_TYPE_ROW_3);
viewTypes.add(ITEM_TYPE_ROW_1);
viewTypes.add(ITEM_TYPE_ROW_2);
viewTypes.add(ITEM_TYPE_ROW_3);
}
@Override
public int getItemViewType(int position) {
return viewTypes.get(position);
}
@Override
public int getItemCount() {
return viewTypes.size();
}
.......
........
如果要添加/删除行,则可以在 viewTypes 数组中插入/删除viewTypes,然后调用RecyclerView notifyItemInserted或notifyItemRemoved方法,列表将使用新订单和类型进行更新观点。
答案 7 :(得分:0)
只需在您的片段中使用框架布局,并将此片段添加到您的framelayout中,这将添加您想要的内容。所以它也很容易处理。希望这会对你有所帮助
答案 8 :(得分:0)
是的,你需要覆盖getItemViewType(int position)方法,这有助于在recyclerview中膨胀不同的视图。
我发布的示例代码可能对您有帮助。
public class TransactionHistoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int TYPE_HEADER = 1;
private final int TYPE_CHILD = 2;
private final Context mContext;
private final List<TransactionResultEntity> mTransactionList;
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_HEADER:
View headerView = LayoutInflater.from(mContext)
.inflate(R.layout.row_transaction_header, parent, false);
return new ParentTypeDataObjectHolder(headerView);
case TYPE_CHILD:
View childView = LayoutInflater.from(mContext)
.inflate(R.layout.row_transaction_child, parent, false);
return new ChildTypeDataObjectHolder(childView);
}
return null;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case TYPE_HEADER:
ParentTypeDataObjectHolder parentTypeDataObjectHolder = (ParentTypeDataObjectHolder) holder;
parentTypeDataObjectHolder.headerYearMonthTv.setText(mTransactionList.get(holder.getAdapterPosition()).getRowLabel());
break;
case TYPE_CHILD:
ChildTypeDataObjectHolder childTypeDataObjectHolder = (ChildTypeDataObjectHolder) holder;
childTypeDataObjectHolder.txnAmountTv.setText(mTransactionList.get(holder.getAdapterPosition()).getTransactionAmount());
break;
}
}
@Override
public int getItemCount() {
return mTransactionList.size();
}
@Override
public int getItemViewType(int position) {
if (mTransactionList.get(position).getDataType() == TYPE_HEADER)
return TYPE_HEADER;
else
return TYPE_CHILD;
}
class ParentTypeDataObjectHolder extends RecyclerView.ViewHolder {
private final TextView headerYearMonthTv;
public ParentTypeDataObjectHolder(View itemView) {
super(itemView);
headerYearMonthTv = (TextView) itemView.findViewById(R.id.row_transaction_header_tv);
}
}
class ChildTypeDataObjectHolder extends RecyclerView.ViewHolder {
TextView txnAmountTv;
public ChildTypeDataObjectHolder(View itemView) {
super(itemView);
txnAmountTv = (TextView) itemView.findViewById(R.id.transaction_child_txn_amount_tv);
}
}
}
答案 9 :(得分:0)
您需要做的只是覆盖适配器中的方法getItemViewType()
。
你可以把它写成:
@Override
public int getItemViewType(int position) {
if (position < 0) {
return 0;
} else if(position < 20) {
return 1;
} else {
return 2;
}
}
如果您的itemsList
ArrayList
包含第1部分的前10项,第2部分的下10项和第3部分的最后10项,则上述逻辑有效。
如果不是这种情况,那么您的sectionNumber
类中可以有一个整数字段SingleItemModel
,它指定该模型所属的部分编号。现在,您可以将方法getItemViewType()
修改为
@Override
public int getItemViewType(int position) {
SingleItemModel singleItemModel = itemsList.get(position);
if (singleItemModel.getSection() == 1) {
return 0;
} else if(singleItemModel.getSection() == 2) {
return 1;
} else {
return 2;
}
}
答案 10 :(得分:0)
好吧,如果我做对了,你想制作第二个适配器,提供行列表的变量,变量,所以它支持不同的布局,不是基于它的位置,而是基于主适配器的一些数据(一个提供部分)。因此,重写getItemViewType将不起作用,因为节数据包含在主适配器中,它甚至没有到达那里。所以,最好,最干净的课程是使用...... 抽象。忘记多个视图。使用一个,然后绑定自定义视图。自定义视图将提供特定的布局文件,并将设置其中包含的控件。持有者将完成它的目的:通过重用视图来保存ram。这方面的优点是,你可以拥有一个干净的层次结构,它可以在时间上增加复杂性,而不是一个很难维护的大型胖适配器。这就是:
由于这里有很多代码可以放在这里,我采用了你的示例项目并进行了修改,以提供我理解你想要做的事情。这是:
https://github.com/fcopardo/exampleCustomViewsInHolder/tree/master
亮点:
public class SectionListDataAdapter extends RecyclerView.Adapter<SectionListDataAdapter.SingleItemRowHolder> {
private ArrayList<SingleItemModel> itemsList;
private Context context;
private String section;
public SectionListDataAdapter(Context context, ArrayList<SingleItemModel> itemsList, String sectionName) {
this.itemsList = itemsList;
this.context = context;
this.section = sectionName;
}
@Override
public SingleItemRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
return new SingleItemRowHolder(RowFactory.getRow(context, section));
}
@Override
public void onBindViewHolder(SingleItemRowHolder holder, int i) {
holder.setData(itemsList.get(i));
}
@Override
public int getItemCount() {
return (null != itemsList ? itemsList.size() : 0);
}
public class SingleItemRowHolder extends RecyclerView.ViewHolder {
protected AbstractRowElement rowElement;
public SingleItemRowHolder(AbstractRowElement view) {
super(view);
this.rowElement = view;
}
public void setData(SingleItemModel singleItemModel){
rowElement.setItem(singleItemModel);
}
}
}
这是可变布局适配器。如您所见,它只使用一个ViewHolder和一个工厂来提供您需要的视图实例。
public class RowFactory {
public static AbstractRowElement getRow(Context context, String name){
switch (name){
case "Section 1": return new FullRowElement(context);
case "Section 2": return new TextRowElement(context);
case "Section 3": return new ImageRowElement(context);
default:
Log.e("inflate", name);
return new FullRowElement(context);
}
}
}
这提供了自定义视图,每个视图使用不同的布局,但基于节标题使用相同的数据集。
public abstract class AbstractRowElement extends CardView{
protected int layout = 0;
protected SingleItemModel singleItemModel;
public AbstractRowElement(Context context) {
super(context);
inflateBaseLayout();
}
public AbstractRowElement(Context context, AttributeSet attrs) {
super(context, attrs);
inflateBaseLayout();
}
public AbstractRowElement(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
inflateBaseLayout();
}
protected void inflateBaseLayout() {
this.setContainer();
if(this.layout != 0) {
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(layout, this, true);
this.inflateComponents();
}
}
protected abstract void setContainer();
protected abstract void inflateComponents();
public void setItem(SingleItemModel itemModel){
this.singleItemModel = itemModel;
this.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getContext(), singleItemModel.getName()+"\n"+singleItemModel.getDescription(), Toast.LENGTH_SHORT).show();
}
});
setData(singleItemModel);
}
public abstract void setData(SingleItemModel itemModel);
}
最后,这是适配器的基本视图类。子类定义要使用的布局文件,并将所需数据放入控件中。其余的很简单。
完全可以在没有自定义视图的情况下进行此操作。你可以做类似的事情:
int layoutFile = getLayoutForSection(section);
View v = LayoutInflater.from(viewGroup.getContext()).inflate(layoutFile, null);
但是,由于我不知道您打算创建的视图有多复杂,因此最好将事物分开。玩得开心!