2

Я создаю представление переробочика данных объектов, каждый из этих объектов будет меняться, например.Создать RecyclerView макета элемента на основе содержимого данных

Obj 1 - Строка Заголовок - Строка Desc - Изображение

Obj 2 - Строка Desc

Obj 3 - Изображение - Строка Link

Obj 4 - Строка Описание изделия - Видео

и т.д.

Так что мне нужно, чтобы создать свой макет элемента динамически, чтобы удовлетворить каждый объект данных. Я не хочу создавать макет элемента со всеми возможными видами и компонентами, а также показывать и скрывать, поскольку я считаю, что это плохая практика.

Так что мой вопрос мне нужно получить доступ к объекту из списка, используя позицию в onBindViewHolder, чтобы построить свой макет в классе ViewHolder.

Я попытался использовать метод, который я вызвал в классе onBindViewHolder, и передал в объект, в который я добавил пользовательские представления в массив, одновременно установив содержимое внутри, но это не сработало.

Кто-нибудь знает, как это можно сделать?

С уважением

+0

Duplicate of: http://stackoverflow.com/questions/26245139/how-to-create-recyclerview-with-multiple-view-type –

+0

@DeanWild Это не дубликат, я пытаюсь создать динамические макеты на на лету, эти ответы, насколько я могу судить, предлагают создать несколько зрителей –

+1

Это полностью дубликат. То, что, по вашему мнению, вы пытаетесь достичь, - это плохая практика. Создайте отдельные держатели, отдельные файлы макета и правильно реализуйте 'getItemViewType', это лучшая практика правильного ответа. – Budius

ответ

4

сначала собственно реализовать тип представления, как описано здесь How to create RecyclerView with multiple view type? на самом деле, ваш вопрос дублируется об этом, но я просто напишу некоторые дополнительные организации вещей, чтобы помочь вам справиться с большим количеством держателей.

  • на этот ответ я буду использовать нож для масла и Пикассо libraris, потому что они удивительным: http://jakewharton.github.io/butterknife/ и http://square.github.io/picasso/

  • Создать пакет на вашем проекте holders, а затем все вид держателя вы положили там внутри, ниже приведен пример держателя:

  • Создать AbstractHolder с public void bindData(Data data) так, то ваш адаптер extends RecyclerView.Adapter<AbstractHolder>:

  • Создание держателей, как показано ниже:

пример Holder1.java

public class Holder1 extends AbstractHolder { 

    // that's an example of views this would use 
    @Bind(R.id.text) TextView text; 
    @Bind(R.id.image) ImageView image; 

    // constructor as normal: 
    public Holder1(View itemView){ 
     super(itemView); 
     ButterKnife.bind(this, itemView); // init the views 
    } 

    // call this from the adapter 
    @Override public void bindData(Data data){ 
     text.setText(data.text); 
     Picasso.with(itemView.getContext()).load(data.url).into(image);   
    } 

    // here you create an instance of this holder, 
    // this way the holder and the layout it's associated with goes together 
    public static Holder1 create(ViewGroup parent){ 
     View root = LayoutInflater.from(parent.getContext()).inflate(R.layout.holder1, parent, false); 
     return new Holder1(root); 
    } 

} 
  • , то ваш код адаптера будет:

.

@Override public AbstractHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     switch(viewType){ 
      case TYPE_HOLDER_1: return Holder1.create(parent); 
      case TYPE_HOLDER_2: return Holder2.create(parent); 
      case TYPE_HOLDER_3: return Holder3.create(parent); 
      ... carry on for all types 
     } 
} 

@Override public void onBindViewHolder(AbstractHolder holder, int position) { 
    Object data = getItem(position); 
    holder.bindData(data); 
} 


// the get type would be similar to that: 
@Override 
public int getItemViewType(int position) { 
    Object data = getItem(position); 
    if(... some condition...) return TYPE_HOLDER_1; 
    else if(... other condition...) return TYPE_HOLDER_2; 
    else if(... other condition...) return TYPE_HOLDER_3; 
    ... etc ... 
} 

вывод:

С помощью этого метода вашего класса адаптера является только «распределительным центром» для возможных типов и каждого типом «знает», как создать себя и как обрабатывать данные.

Это делает ваш код легким в обслуживании и красиво организованным.

+0

Это превосходно, однако, после интеграции вашего примера с использованием Butterknife я получаю нулевые указатели на свои виджеты. Я отредактирую свой OP, чтобы отобразить реализацию. –

+0

Не делайте этого. Если у вас возникли трудности с использованием библиотеки, прочитайте документы или просто не используйте их. Но это действительно не часть вашего первоначального вопроса. – Budius

+0

ok ... просто отметить, что я его отсортировал .. –

0

В классе адаптера вы должны сделать эти изменения:

В вашем случае вы должны переопределить метод getItemViewType

@Override 
    public int getItemViewType(int position) { 
     if (position < arrayList.size()) { 
      return ITEM_X_TYPE; 
     } else 
      return ITEM_Y_TYPE; 
    } 

И в вашем onCreateViewHolder:

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


     if (viewType == ITEM_X_TYPE) { 
      return new XVH(mView); 
     } else if (viewType == ITEM_Y_TYPE) { 
      return new YVH(mView); 
     } 

     throw new RuntimeException("type not found"); 
    } 

И в onBindViewHolder это сделать:

@Override 
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 
     if (holder instanceof XVH) { 

      XVH m = (XVH) holder; 
      ... (continue your code) 

EDIT:

Теперь то, что я предлагаю, что в вашем onCreateViewHolder вы должны сделать что-л так:

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

View mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.your_linear_layout_container, parent, false); 
     if (viewType == ITEM_X_TYPE) { 
      return new XVH(mView,ITEM_X_TYPE,Object one); 
     } else if (viewType == ITEM_Y_TYPE) { 
      return new XVH(mView,ITEM_Y_TYPE, Object two, Object three); 
     } 

     throw new RuntimeException(type not found"); 
    } 

Так вот вы создали вид и вы передаете это своему владельцу и создаете разные экземпляры вашего владельца вида, называя разные конструкторы.

Затем в конструкторе В.Х. вы чего-л, как это:

public class XVH extends RecyclerView.ViewHolder implements { 
    int viewType; 
    public XVH(View itemView,int viewType,Object one) { 
     super(itemView); 
     this.viewType = viewType; 
     // manage your layouts here, build there here or you can inflate from other xml 
    } 

public XVH(View itemView,int viewType,Object two, Object three) { 
      super(itemView); 
      this.viewType = viewType; 
      // manage your layouts here, build there here or you can inflate from other xml 
     } 

И в вашем onBindViewHolder вы проверить, какой тип элемента, а затем вы загрузить данные.

Я надеюсь, что это поможет вам

+0

Но у меня будет 20 вариантов, ты предлагаешь, чтобы у меня было 20 + зрителей ?! –

+0

Хорошо, я понимаю, тогда у вас может быть один VH, а затем в зависимости от ваших данных вы можете создавать разные конструкторы VH и создавать представление из java и раздувать то, что вы можете легко сделать из 'XML' –

+0

@Utlimo_m жаль, что я не полностью понять. Не следует ли раздувать мой макет в onCreateViewHolder? Должен ли я создавать 20 + макеты? Не могли бы вы привести мне пример, пожалуйста ... извините, я просто не обнимаю его. –

Смежные вопросы