2016-01-02 35 views
17

Ich plane, eine App zu entwickeln, die einige dynamische Daten in einem recyclerCardView zeigt. Also entschied ich, fügen Sie eine recyclerView namens CheckBoxRecyclerView in meinem Haupt recyclerView. Dies ist mein Code für meine App:So fügen Sie eine RecyclerView in einem anderen RecyclerView hinzu

Meine Haupttätigkeit:

setContentView(R.layout.activity_startup); 
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
reminderView = (RecyclerView) findViewById(R.id.reminder_recycler_view); 
RlayoutManager = new LinearLayoutManager(this); 
reminderView.setLayoutManager(RlayoutManager); 

setSupportActionBar(toolbar); 
cardView = (CardView) findViewById(R.id.card_first); 
cardView.setOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View v) { 
     Intent intent = new Intent(getApplicationContext() , ReminderActivity.class); 
     startActivity(intent); 
    } 
}); 
ReminderHelper helper = new ReminderHelper(getApplicationContext()); 
ReminderAdapter reminderAdapter = new ReminderAdapter(helper); 
ContentValues reminderValues = new ContentValues(); 
ContentValues checkboxValues = new ContentValues(); 
// Devlopment Part -> 
reminderValues.put("reminderTitle" , "A Reminder Title"); 
reminderValues.put("reminderLastModDate" , 0); 
reminderValues.put("reminderAlarm" , 0); 
reminderValues.put("reminderPicURI" , "skjshksjh"); 
reminderValues.put("ReminderBackground" , "#00796b"); 
checkboxValues.put("checkboxText" , "This is a CheckBox"); 
checkboxValues.put("isDone" , false); 
checkboxValues.put("checkboxReminderID" , 0); 
reminderAdapter.INSERT_REMINDER(reminderValues); 
reminderAdapter.INSERT_CHECKBOX(checkboxValues); 
File dbPath = getApplicationContext().getDatabasePath(ReminderHelper.DATABASE_NAME); 
if(dbPath.exists()){ 
    List<Reminder> reminders = new ReminderAdapter(helper).getAllReminders(); 
    List<CheckBoxItem> checkBoxItems = new ReminderAdapter(helper).getAllCheckBoxes(); 
    RAdapter = new RAdapter(reminders , getApplicationContext() , checkBoxItems); 
    reminderView.setAdapter(RAdapter); 
}else{ 

} 

Und es ist das Layout-Datei:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" 
    android:paddingBottom="8dp" 
    android:paddingLeft="8dp" 
    android:paddingRight="8dp" 
    android:paddingTop="8dp" 
    app:layout_behavior="@string/appbar_scrolling_view_behavior" 
    tools:context="com.smflog.sreminder.StartupActivity" 
    tools:showIn="@layout/app_bar_startup"> 

    <android.support.v7.widget.RecyclerView 
     android:layout_width="match_parent" 
     android:id="@+id/reminder_recycler_view" 
     android:scrollbars="vertical" 
     android:layout_height="match_parent"> 

und in diesem recyclerView es eine andere ist:

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:card_view="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:id="@+id/reminder_card" 
    card_view:cardCornerRadius="2dp" 
    card_view:cardElevation="4dp" 
    card_view:cardUseCompatPadding="true"> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:orientation="vertical" 
     android:paddingBottom="16dp" 
     android:paddingLeft="8dp"> 

     <com.smflog.sreminder.utils.TitleView 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:id="@+id/reminder_title" 
      android:paddingTop="8dp" 
      android:text="Wellcome To Google Keep !" 
      android:textSize="15dp" 
      android:textStyle="bold" /> 
     <LinearLayout 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" android:orientation="horizontal"> 
<android.support.v7.widget.RecyclerView 
    android:layout_width="wrap_content" 
    android:id="@+id/checkbox_recycler_view" 
    android:layout_height="wrap_content"> 

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

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

Ihre Adapter, Main (RAdapter):

public class RAdapter extends RecyclerView.Adapter<RAdapter.ViewHolder> { 
    List<Reminder> reminder; 
    private Context context; 
    private LinearLayoutManager lln; 
    private CAdapter checkBoxAdapter; 
    private List<CheckBoxItem> checkBoxItems; 
    public static class ViewHolder extends RecyclerView.ViewHolder { 
     public CardView rCardView; 
     public RecyclerView recyclerView; 
     public TitleView rTitleView; 
     public ViewHolder(View itemView) { 
      super(itemView); 
      rCardView = (CardView) itemView.findViewById(R.id.reminder_card); 
      rTitleView = (TitleView) itemView.findViewById(R.id.reminder_title); 
      recyclerView = (RecyclerView) itemView.findViewById(R.id.checkbox_recycler_view); 
     } 
    } 

    public RAdapter(List<Reminder> reminder, Context context, List<CheckBoxItem> checkBoxItems) { 
     this.reminder = reminder; 
     this.context = context; 
     this.checkBoxItems = checkBoxItems; 
    } 

    @Override 
    public RAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.reminder_card, parent, false); 
     ViewHolder vh = new ViewHolder(v); 
     return vh; 
    } 

    @Override 
    public void onBindViewHolder(RAdapter.ViewHolder holder, int position) { 
     lln = new LinearLayoutManager(context); 
     holder.recyclerView.setLayoutManager(lln); 
     checkBoxAdapter = new CAdapter(checkBoxItems, context); 
     holder.recyclerView.setAdapter(checkBoxAdapter); 
     holder.rCardView.setCardBackgroundColor(Color.parseColor("#00796b")); 
     holder.rTitleView.setText(reminder.get(position).getReminderTitle()); 
    } 

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

und zweiten Adapter:

public class CAdapter extends RecyclerView.Adapter<CAdapter.ViewHolder> { 
    List<CheckBoxItem> checkBoxItems; 
    Context context; 

    public static class ViewHolder extends RecyclerView.ViewHolder { 
     public TitleView checkBoxTitle; 
     public ImageView deleteCheckBox; 
     public CheckBox checkBoxCheckBox; 

     public ViewHolder(View itemView) { 
      super(itemView); 
      checkBoxTitle = (TitleView) itemView.findViewById(R.id.checkbox_item_text); 
      checkBoxCheckBox = (CheckBox) itemView.findViewById(R.id.checkbox_item_checkbox); 
      Log.d("CAdapterLog", "Adpater Holded !!!!! :("); 
      deleteCheckBox = (ImageView) itemView.findViewById(R.id.btn_delete_checkbox); 
     } 
    } 

    public CAdapter(List<CheckBoxItem> checkBoxItems, Context context) { 
     this.checkBoxItems = checkBoxItems; 
     this.context = context; 
     Log.d("CAdapterLog", "Adpater Created !!!!! :("); 
    } 


    @Override 
    public CAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.checkbox_item, parent, false); 
     ViewHolder vh = new ViewHolder(v); 
     Log.d("CAdapterLog", "Adpater ViewHolded :(!!!!! :("); 
     return vh; 
    } 

    @Override 
    public void onBindViewHolder(CAdapter.ViewHolder holder, int position) { 
     Boolean isCheckboxChecked = Boolean.parseBoolean(checkBoxItems.get(position).getCheckBoxIsDone()); 
     String checkBoxText = checkBoxItems.get(position).getCheckBoxBody(); 
     Log.d("CAdapterLog", "Adpater Binded :("); 
     final int checkboxID = Integer.parseInt(checkBoxItems.get(position).getCheckBoxID()); 
     int reminderCheckBoxID = Integer.parseInt(checkBoxItems.get(position).getCheckBoxReminderID()); 
     holder.deleteCheckBox.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       Log.d("CAdapterLog", "Cross Button Clicked !"); 
      } 
     }); 
     holder.checkBoxCheckBox.setChecked(isCheckboxChecked); 
     holder.checkBoxTitle.setText(checkBoxText); 
    } 

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

} 

Und mein Problem:, wie Sie in CAdapter sehen, nur Log Nachricht Konstruktor angezeigt.

UPDATE: Wenn es eine andere Möglichkeit gibt, einige dynamische Daten in einer anderen dynamischen Karte anzuzeigen, wenn ja, ist es besser, sie anstelle von recycleView zu verwenden?
jemand mir helfen?
Die Ausgabe: Application output wie Sie sehen, nur die SetTitle für RAdapter funktioniert.

+0

Versuchen Sie, die [ExpandableListView] (http://developer.android.com/intl/es/reference/android/widget/ExpandableListView.html) neu zu erfinden? –

+0

Meine Liste Daten ist nicht erweiterbar. Ich denke, das Problem ist von meinem Adapter, aber weiß nicht, was ist das Problem? –

+0

Sie wollen Recyclerview in anderen Recyclerview einfach Ihre Lösung mehr das ist nicht gut für die Leistung – sector11

Antwort

24

Es ist nicht sehr üblich, ein RecyclerView in einem anderen hinzuzufügen. Ich würde vorschlagen, eine einzelne RecyclerView zu verwenden und Ihre Listenelemente dynamisch zu füllen. Ich habe eine github project hinzugefügt, um zu beschreiben, wie dies getan werden kann. Sie können es sich ansehen. Während die anderen Lösungen gut funktionieren, möchte ich vorschlagen, dies ist eine viel schnellere und effiziente Möglichkeit, mehrere Listen in einem RecyclerView anzuzeigen.

Die Idee ist, Logik in Ihre onCreateViewHolder und onBindViewHolder Methode hinzuzufügen, so dass Sie die richtige Ansicht für die genauen Positionen in Ihrem RecyclerView aufblasen können.

Ich habe ein sample project zusammen mit diesem Wiki hinzugefügt. Sie könnten klonen und überprüfen, was es tut.

Es gibt eine andere Möglichkeit, Ihre Objekte in einer einzigen ArrayList Objekte zu halten, so dass Sie ein Attribut festlegen können, das die Elemente markiert, um anzugeben, welches Objekt aus der ersten Liste und welches aus der zweiten Liste ist. Übergeben Sie dann das ArrayList in Ihrem RecyclerView und implementieren Sie dann die Logik in Adapter, um sie dynamisch zu füllen.

Hoffe, dass hilft.

+0

Vielen Dank für Ihre Aufmerksamkeit +1. –

+15

"Es ist nicht sehr üblich, einen RecyclerView in einen anderen einzufügen" -> Was ist mit einer vertikalen Scroll-Liste, die horizontal scrollende Bilder enthält? Wie würdest du es machen, wenn beide Listen sehr groß sein könnten? Scheint wie verschachtelte Recyclerview ist hier sehr nützlich. –

+0

Sogar innerhalb einer vertikalen Recycler-Ansicht in einem anderen ist nicht so ungewöhnlich, nur die innere Scroll-Ansicht wird meist nicht aktiviert. –

4

Mit LayoutInflater können Sie Ihre dynamischen Daten als Layoutdatei aufblasen.

UPDATE: Erstellen Sie zunächst ein LinearLayout in Ihrem CardView-Layout und weisen Sie ihm eine ID zu. Danach erstellen Sie eine Layoutdatei, die Sie aufblasen möchten. zuletzt in Ihrer onBindViewHolder Methode in Ihrer "RAdaper" -Klasse. schreibe diese Codes:

mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

    view = mInflater.inflate(R.layout.my_list_custom_row, parent, false); 

danach können Sie Daten und ClickListeners mit Ihren RAdapter Daten initialisieren. ich hoffe es hilft.

this und this kann nützlich :)

+1

danke lassen Sie mich versuchen –

+2

Es wäre toll, eine kurze Zusammenfassung der wichtigen Punkte aus den Links in Ihrer Antwort zu haben.Andere Benutzer haben die Möglichkeit, eine Antwort zu sehen, wenn die Links nicht mehr gültig sind. – Patrick

+0

ok danke für deine aufmerksamkeit –

11

ich in ähnliches Problem lief eine Weile zurück, und was in meinem Fall geschah war die äußere Recycler Sicht völlig in Ordnung, funktionierte aber der der Adapter von inneren/Sekunde Recycler Ansicht hatte kleinere Probleme alle Methoden wie Konstruktor wurde initiiert und sogar getCount() -Methode wurde aufgerufen, obwohl die endgültigen Methoden verantwortlich zu generieren, dh ie ..

1. onBindViewHolder() Methoden nie aufgerufen wurde. -> Problem 1.

2. Wenn es genannt habe es endlich zeigen nie die Listenelemente/Reihen Recycler Ansicht. -> Problem 2.

Grund, warum diese passierte :: Wenn Sie einen Recycler Blick in einer anderen Recycler Ansicht setzen, dann Höhe der ersten/Außen Recycler Ansicht ist nicht automatisch angepasst. Es wird definiert, wenn die erste/äußere Ansicht erstellt wird und dann bleibt sie fixiert. An diesem Punkt hat Ihre zweite/innere Recycler-Ansicht noch nicht ihre Elemente geladen und somit wird ihre Höhe auf Null gesetzt und verändert sich niemals, selbst wenn sie Daten erhält. Wenn onBindViewHolder() in Ihrer zweiten/inneren Recycler-Ansicht aufgerufen wird, erhält es Elemente, aber es hat nicht den Platz, um sie anzuzeigen, da seine Höhe immer noch Null ist. Daher werden die Elemente in der zweiten Recycleransicht niemals angezeigt, selbst wenn onBindViewHolder() sie hinzugefügt hat.

Lösung :: Sie haben Ihre individuellen LinearLayoutManager für die zweite Recycler Ansicht erstellen und das ist es. So erstellen Sie Ihren eigenen LinearLayoutManager: Erstellen Sie eine Java-Klasse mit dem Namen CustomLinearLayoutManager und fügen Sie den folgenden Code ein. keine Änderungen erforderlich

public class CustomLinearLayoutManager extends LinearLayoutManager { 

private static final String TAG = CustomLinearLayoutManager.class.getSimpleName(); 

public CustomLinearLayoutManager(Context context) { 
    super(context); 

} 

public CustomLinearLayoutManager(Context context, int orientation, boolean reverseLayout) { 
    super(context, orientation, reverseLayout); 
} 

private int[] mMeasuredDimension = new int[2]; 

@Override 
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) { 

    final int widthMode = View.MeasureSpec.getMode(widthSpec); 
    final int heightMode = View.MeasureSpec.getMode(heightSpec); 
    final int widthSize = View.MeasureSpec.getSize(widthSpec); 
    final int heightSize = View.MeasureSpec.getSize(heightSpec); 

    int width = 0; 
    int height = 0; 
    for (int i = 0; i < getItemCount(); i++) { 
     measureScrapChild(recycler, i, View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), 
       View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), 
       mMeasuredDimension); 


     if (getOrientation() == HORIZONTAL) { 
      width = width + mMeasuredDimension[0]; 
      if (i == 0) { 
       height = mMeasuredDimension[1]; 
      } 
     } else { 
      height = height + mMeasuredDimension[1]; 
      if (i == 0) { 
       width = mMeasuredDimension[0]; 
      } 
     } 
    } 
    switch (widthMode) { 
     case View.MeasureSpec.EXACTLY: 
      width = widthSize; 
     case View.MeasureSpec.AT_MOST: 
     case View.MeasureSpec.UNSPECIFIED: 
    } 

    switch (heightMode) { 
     case View.MeasureSpec.EXACTLY: 
      height = heightSize; 
     case View.MeasureSpec.AT_MOST: 
     case View.MeasureSpec.UNSPECIFIED: 
    } 

    setMeasuredDimension(width, height); 
} 

private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, 
           int heightSpec, int[] measuredDimension) { 
    try { 
     View view = recycler.getViewForPosition(position); 

     if (view != null) { 
      RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams(); 

      int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, 
        getPaddingLeft() + getPaddingRight(), p.width); 

      int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, 
        getPaddingTop() + getPaddingBottom(), p.height); 

      view.measure(childWidthSpec, childHeightSpec); 
      measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin; 
      measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin; 
      recycler.recycleView(view); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

}

+2

Wie wäre es mit der zweiten ist gridlayout? –

+0

Es hat für mich funktioniert! Vielen Dank für Ihre Zeit eine Erklärung. +1 – diegot

Verwandte Themen