2016-01-02 3 views
17

Я планирую разработать приложение, которое показывает некоторые динамические данные внутри recyclerCardView. Поэтому я решил добавить recyclerView под названием CheckBoxRecyclerView внутри моего основного recyclerView. Это мой код для моего приложения:Как добавить recyclerView внутри другого recyclerView

Моей Основная деятельность:

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{ 

} 

И это расположение файл:

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

и внутри этого recyclerView есть другой:

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

Их адаптеры, главный (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(); 
    } 
} 

И второй адаптер:

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

} 

И моя проблема: как вы видите в CAdapter, Log сообщение только конструктора отображается.

UPDATE: если есть другой способ отображения некоторых динамических данных внутри другой динамической карты, если да, то лучше использовать его вместо recyclerView?
Кто-нибудь мне помогает?
Выход: Application output , как вы видите, только setTitle для RAdapter работает.

+0

Вы пытаетесь изобрести [ExpandableListView] (http://developer.android.com/intl/es/reference/android/widget/ExpandableListView.html)? –

+0

Данные моего списка не подлежат расширению. Я думаю, проблема связана с моим адаптером, но не знаю, в чем проблема? –

+0

y вы хотите recyclerview внутри другого recyclerview просто ваше решение больше это не хорошо для производительности – sector11

ответ

24

Его не очень обычный добавить RecyclerView внутри другого. Я хотел бы предложить использовать один RecyclerView и динамически заполнять элементы списка. Я добавил github project, чтобы описать, как это можно сделать. Вы можете взглянуть. Хотя другие решения будут работать очень хорошо, я хотел бы предложить, это гораздо более быстрый и эффективный способ отображения нескольких списков в RecyclerView.

Идея состоит в том, чтобы добавить логику в ваш метод onCreateViewHolder и onBindViewHolder, чтобы вы могли надуть правильный вид для точных позиций в RecyclerView.

Я добавил sample project вместе с этой вики. Вы можете клонировать и проверять, что он делает.

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

Надеюсь, что это поможет.

+0

Благодарим за внимание +1. –

+15

«Не очень обычный добавить RecyclerView внутри другого» -> Что относительно вертикального списка прокрутки, который содержит горизонтально прокручиваемые изображения? Как вы это сделаете, если оба списка могут быть очень большими? Кажется, что вложенный recyclerview очень полезен здесь. –

+0

Даже внутри вертикального представления Recycler внутри другого не так уж редко, только в том, что внутренний вид прокрутки не имеет прокрутки, включенных в основном. –

4

вы можете использовать LayoutInflater для раздувания ваших динамических данных в виде файла макета.

ОБНОВЛЕНИЕ: сначала создайте LinearLayout внутри макета CardView и назначьте ему ID. после этого создайте файл макета, который вы хотите раздуть. наконец, в вашем методе onBindViewHolder в вашем классе «RAdaper». напишите эти коды:

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

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

После этого вы можете инициализировать данные и ClickListeners с помощью данных RAdapter. Надеюсь, поможет.

this и this может полезно :)

+1

спасибо, я попробую –

+2

Было бы здорово иметь краткий обзор важных точек из ссылок в вашем ответе.У другого пользователя будет возможность увидеть ответ, если ссылки уже недействительны. – Patrick

+0

ОК спасибо за внимание –

11

я столкнулся с подобной проблемой, некоторое время назад, и что происходит в моем случае был внешний вид утилизатор работает прекрасно, но адаптер внутреннего/второго зрения ресайклера было второстепенные проблемы, все методы, такие как конструктор, были инициированы и даже вызывается метод getCount(), хотя конечные методы, ответственные за создание вида, то есть ...

1. Методы onBindViewHolder() никогда не вызывались. -> Проблема 1.

2. Когда он был призван, наконец, никогда не показывать элементы списка/строк зрения ресайклера. -> Проблема 2.

Причина, почему это произошло :: Когда вы кладете вид ресайклера в другой точке зрения ресайклера, то высота первого/внешнего зрения ресайклера автоматически не регулируются. Он определяется, когда создается первый/внешний вид, а затем он остается фиксированным. В этот момент ваше второе/внутреннее представление ресайклера еще не загрузило его элементы, и поэтому его высота устанавливается равной нулю и никогда не изменяется даже при получении данных. Затем, когда onBindViewHolder() в вашем втором/внутреннем просмотре recycler называется, он получает элементы, но у него нет места, чтобы показать их, потому что его высота все равно равна нулю. Таким образом, элементы во втором просмотре ресайклеров никогда не отображаются, даже когда onBindViewHolder() добавляет их в него.

Решение :: вам необходимо создать свой собственный LinearLayoutManager для второго вида ресайклера, и это все. Чтобы создать свой собственный LinearLayoutManager: Создайте класс Java с именем CustomLinearLayoutManager и вставьте в него код ниже. НЕТ ИЗМЕНЕНИЙ ТРЕБУЕТСЯ

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

Как насчет второго является gridlayout? –

+0

Это сработало для меня! Большое вам спасибо за ваше объяснение. +1 – diegot

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