RecyclerView - 具有未知数量元素的listitem

时间:2017-01-11 19:11:39

标签: android android-recyclerview listitem

我面临以下情况:我有一个带有3种不同视图类型的RecyclerView。每个都包含一个副标题,然后是一个广播组,复选框或editText。问题是:元素的大小(edittext,checkbox,radiobuttons)是可变的,因此我无法创建静态模板作为视图类型。所以我试图达到这样的目的(使用radiobuttons的例子):

LISTVIEW
------------------
row1
      1) choice1
      2) choice2
------------------
row2
      1) choice1
      2) choice2
      3) choice3
------------------
row3
      1) choice1
-------------------

关于好方法的任何想法?谢谢你的时间和帮助! :)

编辑:ChaitanyaAtkuris的答案非常有用,但我在onBindViewHolder()中获得了ClassCastException。它说“不能将TitleHolder转换为InputHolder”......但是我无法弄清楚为什么holder对象实际上是TitleHolder,因为它使用了正确的情况(INPUT)。这是我的适配器代码

public class RecAdapter extends RecyclerView.Adapter {

private List<Object> items;
private final int TITLE_VIEW = 0; 
private final int RADIO_GROUP = 1; 
private final int CHECK_BOX = 2; 
private final int INPUT = 3; 

public RecAdapter(List<Object> data) {
    this.items = data;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    RecyclerView.ViewHolder viewHolder = null;
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());

    switch (viewType) {
        case CHECK_BOX:
            View v1 = inflater.inflate(R.layout.child_checkbox, parent, false);
            viewHolder = new CheckboxHolder(v1);
            break;
        case TITLE_VIEW:
            View v2 = inflater.inflate(R.layout.child_title, parent, false);
            viewHolder = new TitleHolder(v2);
            break;
        case INPUT:
            View v3 = inflater.inflate(R.layout.child_inputfield, parent, false);
            viewHolder = new TitleHolder(v3);
            break;

    }

    return viewHolder;
}

@Override
public int getItemViewType(int position) {
    ListItem item = (ListItem) items.get(position);
    if (item.getviewType()==TITLE_VIEW) {
        return TITLE_VIEW;
    } else if (item.getviewType()==RADIO_GROUP) {
        return RADIO_GROUP;
    } else if (item.getviewType()==CHECK_BOX) {
        return CHECK_BOX;
    } else if (item.getviewType()==INPUT) {
        return INPUT;
    }
        return -1;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    switch (holder.getItemViewType()) {
        case CHECK_BOX:
            CheckboxHolder checkboxHolder = (CheckboxHolder) holder;
            configureCheckBoxHolder(checkboxHolder, position);
            break;
        case TITLE_VIEW:
            TitleHolder titleHolder = (TitleHolder) holder;
            configureTitleHolder(titleHolder, position);
            break;
        case INPUT:
            InputHolder inputHolder = (InputHolder) holder;
            configureInputHolder(inputHolder, position);
            break;
    }
}

private void configureCheckBoxHolder(CheckboxHolder holder,int position)    {
    CheckBoxElement boxElement = (CheckBoxElement) items.get(position);
    if (boxElement != null) {
        holder.box.setText(boxElement.getText());
    }
}

private void configureInputHolder(InputHolder holder,int position)    {
    InputField field = (InputField) items.get(position);
    if (field != null) {
        holder.title.setText(field.getSubtitle());
    }
}

private void configureTitleHolder(TitleHolder holder,int position)    {
    TitlePojo titlePojo = (TitlePojo) items.get(position);
    if (titlePojo != null) {
        holder.titleText.setText(titlePojo.getTitle());
    }
}

@Override
public int getItemCount() {
    return items.size();
}

private class InputHolder extends RecyclerView.ViewHolder {
    private TextView title;
    private EditText inputfield;

    public InputHolder(View v1) {
        super(v1);
        title = (TextView) v1.findViewById(R.id.inputTitleItem);
        inputfield = (EditText) v1.findViewById(R.id.fieldItem);
    }
}

private class TitleHolder extends RecyclerView.ViewHolder {
    private TextView titleText;

    public TitleHolder(View v1) {
        super(v1);
        titleText = (TextView)  v1.findViewById(R.id.titleView);
    }
}

private class CheckboxHolder extends RecyclerView.ViewHolder {
    private CheckBox box;

    public CheckboxHolder(View v1) {
        super(v1);
        box = (CheckBox)   v1.findViewById(R.id.checkboxItem);
    }
}

private class RadioGroupHolder extends RecyclerView.ViewHolder {
    private RadioGroup group;

    public RadioGroupHolder(View v1) {
        super(v1);

    }
}

}

1 个答案:

答案 0 :(得分:1)

@Pynnie,这不是什么大问题。我相信你会解决它。 Lemme为你解决这个问题提供了一些帮助。

步骤1:由于我们提到了三种不同类型的视图,我们可以选择List<Object> dataList= new ArrayList();此列表将决定要显示的总视图。

步骤2:现在,让我们为每个可用组件创建一个viewType。例如

private final int TEXT_VIEW = 0; //For TextView
private final int RADIO_GROUP = 1; //For RadioGroup
private final int CHECK_BOX = 2; //For individual Checkbox
private final int EDIT_TEXT = 3; //For Edit text individual

现在,在根据结构动态存储数据时,按以下方式存储。

public class TextViewPojo { // This will used for identifying textViews

public String text;
//Any other necessary variables to hold data to display
}

public class EditTextPojo { // This will used for identifying editText

public String text;
//Any other necessary variables to hold data to display
}

public class RadioGroupPojo { // This will used for identifying RadioGroup

public int noOfRadioButtons;
//Any other necessary variables to hold data to display
}

public class CheckBoxPojo { // This will used for identifying checkbox

public String text;
//Any other necessary variables to hold data to display
}

// ------------------     row1 - 指示subTitle的TextView - &gt; dataList.add(new TextViewPojo());           1)choice1 - EditText - &gt; dataList.add(new EditTextPojo());           2)choice2- EditText - &gt; dataList.add(new EditTextPojo());     // ------------------     row2- TextView指示subTitle - &gt; dataList.add(new TextViewPojo());           1)choice1 -CheckBox - &gt; dataList.add(new CheckBoxPojo());           2)choice2-CheckBox - &gt; dataList.add(new CheckBoxPojo());           3)choice3-CheckBox - &gt; dataList.add(new CheckBoxPojo());     // ------------------     row3 - 指示subTitle的TextView - &gt; dataList.add(new TextViewPojo());           1)choice1 - RadioGroup对于choice1,choice2考虑为一组单选按钮, - &gt; RadioGroup -> dataList.add(new RadioGroupPojo());           2)选择2     // -------------------

现在进入RecyclerView Adapter Implementation

公共类RecyclerViewsAdapter扩展了RecyclerView.Adapter {

// The items to display in your RecyclerView
private List<Object> items; 
private final int TEXT_VIEW = 0; //For TextView
private final int RADIO_GROUP = 1; //For RadioGroup
private final int CHECK_BOX = 2; //For individual Checkbox
private final int EDIT_TEXT = 3; //For Edit text individual

public RecyclerViewsAdapter(List<Object> data,) {
this.items = data;
}

现在要区分数据,我们将使用getViewType()方法

//为了视图回收的目的,返回位置处项目的视图类型。

@Override
  public int getItemViewType(int position) {
      if (items.get(position) instanceof CheckBoxPojo) {
          return CHECK_BOX;
      } else if (items.get(position) instanceof RadioGroupPojo) {
          return RADIOGROUP;
      } //All the conditions follow..
      return -1;
  }

现在为每种类型创建视图。

public class ViewHolder1 extends RecyclerView.ViewHolder {

    private TextView label1;

    public ViewHolder1(View v) {
        super(v);
        label1 = (TextView) v.findViewById(R.id.text1);
    }

    public TextView getLabel1() {
        return label1;
    }

    public void setLabel1(TextView label1) {
        this.label1 = label1;
    }
}

//相应的所有其他viewHolders。

@Override
  public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {

      RecyclerView.ViewHolder viewHolder;
      LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());

      switch (viewType) {
          case CHECKBOX:
              View v1 = inflater.inflate(R.layout.layout_viewholder1, viewGroup, false);
              viewHolder = new ViewHolder1(v1);
              break;
          case RADIOGROUP:
              View v2 = inflater.inflate(R.layout.layout_viewholder2, viewGroup, false);
              viewHolder = new ViewHolder2(v2);
              break;

//其他案例如下。

NExt将数据设置为视图

@Override
  public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
      switch (viewHolder.getItemViewType()) {
          case CHECKBOX:
              ViewHolder1 vh1 = (ViewHolder1) viewHolder;
              configureViewHolder1(vh1, position);
              break;
          case RADIOGROUp:
              ViewHolder2 vh2 = (ViewHolder2) viewHolder;
              configureViewHolder2(vh2, position);
              break;
//Rest cases follow.
          default:
              RecyclerViewSimpleTextViewHolder vh = (RecyclerViewSimpleTextViewHolder) viewHolder;
              configureDefaultViewHolder(vh, position);
              break;
      }
  }

private void configureViewHolder1(ViewHolder1 vh1, int position) {
      CheckBoxPojo user = (CheckBoxPojo) items.get(position);
      if (user != null) {
          vh1.getCheckBox1().setChecked(user.isChecked);
      }
  }

  private void configureViewHolder2(ViewHolder2 vh2) {
      //vh2.getImageView().setImageResource(R.drawable.sample_golden_gate);
Similarly rest follows.
  }

这就完成了!你可以用任何方式配置,它可能有多少,它们可能是多么随机。

参考:https://guides.codepath.com/android/Heterogenous-Layouts-inside-RecyclerView

编辑:

要了解您添加的代码段中的问题。以下是问题:

case TITLE_VIEW: View v2 = inflater.inflate(R.layout.child_title, parent, false); viewHolder = new TitleHolder(v2); break; case INPUT: View v3 = inflater.inflate(R.layout.child_inputfield, parent, false); viewHolder = new TitleHolder(v3); break;

在这两种情况下,您只使用标题持有人。