12

Die Aktivität, über die ich spreche, muss eine RecyclerView zeigen, die von CardViews als Elemente befüllt wird. Mein Ziel ist es, in jedem CardView ein RecyclerView zu zeigen.Android: Wie kann ich einen RecyclerView in CardView einfügen?

Hier grundlegende xml meiner Aktivität suchen:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context=".ConjActivity" > 

    <android.support.v7.widget.RecyclerView 
     android:id="@+id/conjCardList" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:clickable="false" /> 

</LinearLayout> 

Und hier ist das Layout RecyclerView meine CardView suchen:

<?xml version="1.0" encoding="utf-8"?> 
<android.support.v7.widget.CardView 
    xmlns:card_view="http://schemas.android.com/apk/res-auto" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/card_analysis" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_marginTop="@dimen/activity_vertical_margin" 
    android:layout_marginBottom="@dimen/activity_vertical_margin" 
    android:layout_marginLeft="@dimen/activity_horizontal_margin" 
    android:layout_marginRight="@dimen/activity_horizontal_margin" 
    android:padding="5dp" 
    card_view:cardCornerRadius="5dp" > 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:orientation="vertical" > 

     <android.support.v7.widget.RecyclerView 
      android:id="@+id/item_mode" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:paddingTop="5dp" 
      android:paddingLeft="@dimen/activity_horizontal_margin" > 

     </android.support.v7.widget.RecyclerView> 
    </LinearLayout> 
</android.support.v7.widget.CardView> 

So machte ich kühn meinen ersten Versuch, durch die Implementierung von zwei RecyclerView.Adapters , eine für die (nennen wir es) "Haupt" RecyclerView und eine für die einzelnen in jedem CardView:

Hier sind t er zwei Stücke von Code:

"Main" RecyclerView (w/ViewHolders):

public class ConjCardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{ 

    private static Context context; 
    private LinearLayoutManager llm; 
    private static ConjFormAdapter formAdapt; 
    private ArrayList<String> adapterList; 
    private List<Object> items; 
    private static final int 
      HEADER = 0, 
      CONJTYPE = 1, 
      ITEM = 2; 
    private Paradigma par; 
    private String sel_vb; 

    public ConjCardAdapter(List<Object> items){ 
     this.items = items; 
     context = ConjActivity.context; 
     adapterList = new ArrayList<String>(); 
     formAdapt = new ConjFormAdapter(adapterList); 
    } 

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

     switch(viewType){ 
     case HEADER: 
      return new HeaderHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_header, viewGroup, false)); 
     case CONJTYPE: 
      return new ConjTypeHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_conjtext, viewGroup, false)); 
     case ITEM: 
      return new ItemModeHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_item, viewGroup, false)); 
     default: 
      return null; 
     } 
    } 

    public void onBindViewHolder(RecyclerView.ViewHolder vvh, final int pos) { 
     HeaderItem headerItem; 
     String stringItem; 
     ArrayList<String> listItem; 
     HeaderHolder hh; 
     ConjTypeHolder cjh; 
     ItemModeHolder imh; 

     switch(getItemViewType(pos)){ 
     case HEADER: 
      // it doesn't really matter... 
      break; 
     case CONJTYPE: 
      // it doesn't really matter... 
      break; 
     case ITEM: 
      listItem = (ArrayList<String>) items.get(pos); 
      imh = (ItemModeHolder) vvh; 
      llm = new LinearLayoutManager(context); 
      imh.rv_mode.setLayoutManager(llm); 
      adapterList.addAll(listItem); 
      imh.rv_mode.setAdapter(formAdapt); 
      formAdapt.notifyDataSetChanged(); 
      break; 
     }   
    } 

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

    @Override 
    public int getItemViewType(int position) { 

     switch(position){ 
     case 0: 
      return HEADER; 
     case 1: 
      return CONJTYPE; 
     default: 
      return ITEM; 
     } 
    } 


    static class HeaderHolder extends RecyclerView.ViewHolder{ 

     TextView verbo, 
       paradigma, 
       analisi; 
     View divider; 

     public HeaderHolder(View itemView) { 
      super(itemView); 
      verbo = (TextView) itemView.findViewById(R.id.verb); 
      paradigma = (TextView) itemView.findViewById(R.id.paradigm); 
      analisi = (TextView) itemView.findViewById(R.id.analysis); 
      divider = (View) itemView.findViewById(R.id.divider); 
     } 
    } 

    static class ConjTypeHolder extends RecyclerView.ViewHolder{ 

     TextView type; 

     public ConjTypeHolder(View itemView) { 
      super(itemView); 
      type = (TextView) itemView.findViewById(R.id.conj_type); 
     } 
    } 
: 
    static class ItemModeHolder extends RecyclerView.ViewHolder{ 

     RecyclerView rv_mode; 

     public ItemModeHolder(View itemView) { 
      super(itemView); 
      rv_mode = (RecyclerView) itemView.findViewById(R.id.item_mode); 
     } 
    } 

} 

Artikel RecyclerView (w/ViewHolder):

public class ConjFormAdapter extends RecyclerView.Adapter<ConjFormAdapter.FormHolder>{ 

    private Context context; 
    private ArrayList<String> list; 
    private Paradigma par; 
    private String sel_vb; 
    private ArrayList<Long> ids; 
    private HashMap<String, Long> mIdMap; 
    private StringAnalisi analisi; 
    private final int IND_MODE_TYPE=0, 
      ELSE_MODE_TYPE=1, 
      TENSE_TYPE=2, 
      FORM_TYPE=3; 

    public ConjFormAdapter(ArrayList<String> list){ 
     this.list = list; 
     // Constructor implementation 
    } 

    // other methods 

    @Override 
    public FormHolder onCreateViewHolder(ViewGroup viewGroup, int itemType) { 
     switch(itemType){ 
     case IND_MODE_TYPE: 
      return new FormHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_mode_ind, viewGroup, false)); 
     case ELSE_MODE_TYPE: 
      return new FormHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_mode_else, viewGroup, false)); 
     case TENSE_TYPE: 
      return new FormHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_tense, viewGroup, false)); 
     default: 
      return new FormHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_form, viewGroup, false)); 
     } 
    } 

    @Override 
    public void onBindViewHolder(FormHolder fh, int pos) { 

     fh.txt.setText(list.get(pos)); 

     // other implementation 

    } 

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

    @Override 
    public int getItemViewType(int position) { 
     String item = (String) list.get(position); 
     if(item.equals(context.getResources().getString(R.string.ind))){ 
      return IND_MODE_TYPE; 
     } else if(item.equals(context.getResources().getString(R.string.subj))||item.equals(context.getResources().getString(R.string.imp))||item.equals(context.getResources().getString(R.string.inf))||item.equals(context.getResources().getString(R.string.pt))||item.equals(context.getResources().getString(R.string.ger))||item.equals(context.getResources().getString(R.string.gerv))||item.equals(context.getResources().getString(R.string.sup))){ 
      return ELSE_MODE_TYPE; 
     } else if(item.equals(context.getResources().getString(R.string.pres))||item.equals(context.getResources().getString(R.string.impf))||item.equals(context.getResources().getString(R.string.fut))||item.equals(context.getResources().getString(R.string.pf))||item.equals(context.getResources().getString(R.string.ppf))||item.equals(context.getResources().getString(R.string.futant))){ 
      return TENSE_TYPE; 
     } else { 
      return FORM_TYPE; 
     } 
    } 

    @Override 
    public long getItemId(int position) { 

     String item = list.get(position); 
     return mIdMap.get(item); 
    } 

    @Override 
    public void setHasStableIds(boolean hasStableIds) { 
     super.setHasStableIds(true); 
    } 


    static class FormHolder extends RecyclerView.ViewHolder{ 

     TextView txt; 
     View divider1, divider2, divider3; 

     public FormHolder(View itemView) { 
      super(itemView); 
      txt = (TextView) itemView.findViewById(R.id.text1); 
      divider1 = (View) itemView.findViewById(R.id.conj_divider1); 
      divider2 = (View) itemView.findViewById(R.id.conj_divider2); 
      divider3 = (View) itemView.findViewById(R.id.conj_divider3); 
     } 
    } 
} 

Wie Sie dachte ich, es sehen können war richtig, den zweiten Adapter in der ersten Instanz zu instanziieren, und für jedes Element RecyclerView einen neuen LayoutManager anzuhängen und den zweiten Adapter festzulegen. Aber wie Sie sehen können, funktionieren die ersten zwei Elemente meiner "Haupt" Rec.View, die kein anderes Rec.View enthalten, gut, aber die anderen nicht.

The items with a RecyclerView don't show up like they should

Wie kann ich lösen das Problem? Bitte, ich habe keine Ideen mehr.

Antwort

16

Ich konfrontiert das genau gleiche Problem. Sie müssen die Layouthöhe der RecyclerView im CardView angeben. Ändern Sie den Wert von wrap_content in einen bestimmten Wert in dp. Nested RecyclerView umschließt den Inhalt nicht in seiner Höhe, wenn das übergeordnete Bildlaufbild VERTIKAL ist, und umschließt den Inhalt in ähnlicher Weise nicht in seiner Breite, wenn das übergeordnete Bildlauffeld HORIZONTAL ist.

<?xml version="1.0" encoding="utf-8"?> 
<android.support.v7.widget.CardView 
xmlns:card_view="http://schemas.android.com/apk/res-auto" 
xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/card_analysis" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:layout_marginTop="@dimen/activity_vertical_margin" 
android:layout_marginBottom="@dimen/activity_vertical_margin" 
android:layout_marginLeft="@dimen/activity_horizontal_margin" 
android:layout_marginRight="@dimen/activity_horizontal_margin" 
android:padding="5dp" 
card_view:cardCornerRadius="5dp" > 

<LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" > 

    <android.support.v7.widget.RecyclerView 
     android:id="@+id/item_mode" 
     android:layout_width="wrap_content" 
     android:layout_height="100dp" 
     android:paddingTop="5dp" 
     android:paddingLeft="@dimen/activity_horizontal_margin" > 

    </android.support.v7.widget.RecyclerView> 
</LinearLayout> 
</android.support.v7.widget.CardView> 
+2

Aber was, wenn meine Recycler-Ansicht variablen Inhalt hat? Gibt es eine Möglichkeit, die Höhe automatisch abhängig von der Anzahl der Artikel zu wählen? –

+0

Eine Lösung kann darin bestehen, verschiedene Layouts für das CardView zu verwenden, die unterschiedlich hohe RecylerViews enthalten, und sie mit switch case (oder bedingten Anweisungen) zu implementieren. –

+1

Dank Ihrer Hinweise habe ich das Problem endlich gelöst, und wenn Sie interessiert sind, wurde die Lösung für meine zweite Frage von @DenisNek unter http://stackoverflow.com/questions/26649406/nested-recycler-view-height gebracht -doesnt-wrap-its-content/27616854 # 27616854 –

5

Ab Support-Bibliothek 23.2 bringt die Layoutmanager API Auto-Messung, die eine RecyclerView Größe läßt sich auf der Basis der Größe des Inhalts. Dies bedeutet, dass WRAP_CONTENT für eine Dimension des RecyclerViews jetzt möglich ist. Sie werden feststellen, dass alle integrierten LayoutManager jetzt automatische Messungen unterstützen.

Source