2016-01-02 19 views
17

Sto pianificando di sviluppare un'applicazione che mostri alcuni dati dinamici all'interno di uno recyclerCardView. Così ho deciso di aggiungere uno recyclerView chiamato CheckBoxRecyclerView all'interno del mio principale recyclerView. Questo è il mio codice per la mia app:Come aggiungere un riciclatoreVedere all'interno di un altro riciclatoreVedere

la mia attività principale:

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{ 

} 

Ed è file di layout:

<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"> 

e all'interno di questa recyclerView c'è un altro:

<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> 

I loro adattatori, 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(); 
    } 
} 

E secondo adattatore:

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(); 
    } 

} 

E il mio problema: come si vede in CAdapter, Log messaggio solo del costruttore visualizzata.

UPDATE: se c'è un altro modo per visualizzare alcuni dati dinamici all'interno di un'altra scheda dinamica se sì è meglio usarlo al posto di recyclerView?
qualcuno mi aiuti?
L'output: Application output come si vede solo il setTitle per RAdapter funziona.

+0

Si sta tentando di reinventare [ExpandableListView] (http://developer.android.com/intl/es/reference/android/widget/ExpandableListView.html)? –

+0

I miei dati di lista non sono espandibili. Penso che il problema sia dal mio adattatore ma non so qual è il problema ?? –

+0

si desidera una panoramica del riciclaggio all'interno di altri ambienti di riciclaggio semplicemente la vostra soluzione più questo non è buono per le prestazioni – sector11

risposta

24

La sua non è molto usuale per aggiungere un RecyclerView all'interno di un altro. Vorrei suggerire di utilizzare un singolo RecyclerView e popolare gli elementi dell'elenco in modo dinamico. Ho aggiunto un github project per descrivere come questo può essere fatto. Potresti dare un'occhiata. Mentre le altre soluzioni funzioneranno bene, vorrei suggerire, questo è un modo molto più rapido ed efficiente di mostrare più elenchi in uno RecyclerView.

L'idea è di aggiungere la logica nel metodo onCreateViewHolder e onBindViewHolder in modo da poter gonfiare la vista corretta per le posizioni esatte nello RecyclerView.

Ho aggiunto un sample project insieme a quella wiki. Potresti clonare e controllare cosa fa.

C'è un altro modo di mantenere gli articoli in un unico ArrayList oggetti in modo da poter impostare un attributo che tagga gli elementi per indicare quale elemento proviene dal primo elenco e quale appartiene al secondo elenco. Quindi passare lo ArrayList nel numero RecyclerView e quindi implementare la logica all'interno dell'adattatore per popolarlo in modo dinamico.

Spero che questo aiuti.

+0

Grazie per l'attenzione +1. –

+15

"Non è molto usuale aggiungere un RecyclerView all'interno di un altro" -> Che dire di un elenco a scorrimento verticale che contiene immagini a scorrimento orizzontale? Come faresti se entrambe le liste possono essere molto grandi? Sembra che il recyclerview annidato sia molto utile qui. –

+0

Anche all'interno di una vista verticale di Recycler all'interno di un altro non è così raro, l'unica cosa è che la vista di scorrimento interno non ha per lo più abilitato lo scorrimento. –

4

è possibile utilizzare LayoutInflater per gonfiare i dati dinamici come file di layout.

UPDATE: innanzitutto creare un LinearLayout all'interno del layout di CardView e assegnare un ID per esso. dopo aver creato un file di layout che si desidera gonfiare. finalmente nel tuo metodo onBindViewHolder nella tua classe "RAdaper". scrivere questi codici:

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

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

dopodiché è possibile inizializzare i dati e ClickListeners con i dati di RAdapter. spero che sia d'aiuto.

this e this possono utile :)

+1

grazie lasciami provare –

+2

Sarebbe bello avere un breve riassunto dei punti importanti dai link nella tua risposta.Gli altri utenti avranno la possibilità di vedere una risposta se i collegamenti non sono più validi. – Patrick

+0

ok grazie per l'attenzione –

11

mi sono imbattuto in un problema simile po 'indietro e quello che stava accadendo nel mio caso era la vista riciclatore esterna stava funzionando perfettamente bene, ma il l'adattatore del secondo punto di vista interno/riciclatore avuto problemi minori tutti i metodi come costruttore ricevuti avviate e metodo ancora getCount() era stato chiamato, anche se i metodi finali responsabili per generare vista cioè .. metodi

1. onBindViewHolder() mai stato chiamato. -> Problema 1.

2. Quando è stato chiamato alla fine non è mai mostrare le voci di elenco/righe di vista riciclatore. -> Problema 2.

Motivo per cui questo è accaduto :: Quando si inserisce una vista all'interno di un altro riciclatore riciclatore vista, poi all'altezza del primo/esterno vista riciclatore non è automaticamente regolata. Viene definito quando viene creata la prima/vista esterna e quindi rimane fissa. A quel punto la tua seconda/interna view del riciclatore non ha ancora caricato i suoi articoli e quindi la sua altezza è impostata come zero e non cambia mai anche quando riceve i dati. Quindi, quando onBindViewHolder() nella visualizzazione secondo/interno del dispositivo di riciclo è chiamato, ottiene gli elementi ma non ha lo spazio per mostrarli perché la sua altezza è ancora zero. Pertanto, gli elementi nella seconda vista del riciclatore non vengono mai visualizzati anche quando onBindViewHolder() li ha aggiunti.

Soluzione :: è necessario creare il proprio LinearLayoutManager personalizzato per la seconda vista del riciclatore e il gioco è fatto. Per creare il proprio LinearLayoutManager: Creare una classe Java con il nome CustomLinearLayoutManager e incollare il codice riportato di seguito. Non occorre cambiare nulla

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

E il secondo è la griglia? –

+0

Ha funzionato per me! Grazie mille per il tuo tempo una spiegazione. +1 – diegot