如何在另一个 recyclerView 中添加一个 recyclerView

新手上路,请多包涵

我打算开发一个应用程序,在 recyclerCardView 中显示一些动态数据。所以我决定在我的主要 recyclerView 中添加一个 recyclerView 称为 CheckBoxRecyclerView 。这是我的应用程序代码:

我的主要活动:

 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>

他们的适配器 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();
    }
}

第二个适配器:

 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 中看到的,仅显示构造函数的 日志 消息。

更新:如果有另一种方法可以在另一个动态卡中显示一些动态数据,如果是,使用它而不是 recyclerView 更好吗?

有人帮我吗?

输出:您看到的 应用程序输出 只是 RAdapter 的 setTitle 有效。

原文由 Mohammad Fatemi 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 529
2 个回答

我想建议使用单个 RecyclerView 并动态填充您的列表项。我添加了一个 github 项目 来描述如何做到这一点。你可能会看看。虽然其他解决方案可以正常工作,但我想建议,这是在 RecyclerView 中显示多个列表的更快、更有效的方法。

这个想法是在您的 onCreateViewHolderonBindViewHolder 方法中添加逻辑,以便您可以为 RecyclerView 中的确切位置添加正确的视图。

我也添加了一个 示例项目 以及该 wiki。您可以克隆并检查它的作用。为方便起见,我发布了我使用过的适配器。

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

    private static final int FOOTER_VIEW = 1;
    private static final int FIRST_LIST_ITEM_VIEW = 2;
    private static final int FIRST_LIST_HEADER_VIEW = 3;
    private static final int SECOND_LIST_ITEM_VIEW = 4;
    private static final int SECOND_LIST_HEADER_VIEW = 5;

    private ArrayList<ListObject> firstList = new ArrayList<ListObject>();
    private ArrayList<ListObject> secondList = new ArrayList<ListObject>();

    public DynamicListAdapter() {
    }

    public void setFirstList(ArrayList<ListObject> firstList) {
        this.firstList = firstList;
    }

    public void setSecondList(ArrayList<ListObject> secondList) {
        this.secondList = secondList;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        // List items of first list
        private TextView mTextDescription1;
        private TextView mListItemTitle1;

        // List items of second list
        private TextView mTextDescription2;
        private TextView mListItemTitle2;

        // Element of footer view
        private TextView footerTextView;

        public ViewHolder(final View itemView) {
            super(itemView);

            // Get the view of the elements of first list
            mTextDescription1 = (TextView) itemView.findViewById(R.id.description1);
            mListItemTitle1 = (TextView) itemView.findViewById(R.id.title1);

            // Get the view of the elements of second list
            mTextDescription2 = (TextView) itemView.findViewById(R.id.description2);
            mListItemTitle2 = (TextView) itemView.findViewById(R.id.title2);

            // Get the view of the footer elements
            footerTextView = (TextView) itemView.findViewById(R.id.footer);
        }

        public void bindViewSecondList(int pos) {

            if (firstList == null) pos = pos - 1;
            else {
                if (firstList.size() == 0) pos = pos - 1;
                else pos = pos - firstList.size() - 2;
            }

            final String description = secondList.get(pos).getDescription();
            final String title = secondList.get(pos).getTitle();

            mTextDescription2.setText(description);
            mListItemTitle2.setText(title);
        }

        public void bindViewFirstList(int pos) {

            // Decrease pos by 1 as there is a header view now.
            pos = pos - 1;

            final String description = firstList.get(pos).getDescription();
            final String title = firstList.get(pos).getTitle();

            mTextDescription1.setText(description);
            mListItemTitle1.setText(title);
        }

        public void bindViewFooter(int pos) {
            footerTextView.setText("This is footer");
        }
    }

    public class FooterViewHolder extends ViewHolder {
        public FooterViewHolder(View itemView) {
            super(itemView);
        }
    }

    private class FirstListHeaderViewHolder extends ViewHolder {
        public FirstListHeaderViewHolder(View itemView) {
            super(itemView);
        }
    }

    private class FirstListItemViewHolder extends ViewHolder {
        public FirstListItemViewHolder(View itemView) {
            super(itemView);
        }
    }

    private class SecondListHeaderViewHolder extends ViewHolder {
        public SecondListHeaderViewHolder(View itemView) {
            super(itemView);
        }
    }

    private class SecondListItemViewHolder extends ViewHolder {
        public SecondListItemViewHolder(View itemView) {
            super(itemView);
        }
    }

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

        View v;

        if (viewType == FOOTER_VIEW) {
            v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_footer, parent, false);
            FooterViewHolder vh = new FooterViewHolder(v);
            return vh;

        } else if (viewType == FIRST_LIST_ITEM_VIEW) {
            v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_first_list, parent, false);
            FirstListItemViewHolder vh = new FirstListItemViewHolder(v);
            return vh;

        } else if (viewType == FIRST_LIST_HEADER_VIEW) {
            v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_first_list_header, parent, false);
            FirstListHeaderViewHolder vh = new FirstListHeaderViewHolder(v);
            return vh;

        } else if (viewType == SECOND_LIST_HEADER_VIEW) {
            v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_second_list_header, parent, false);
            SecondListHeaderViewHolder vh = new SecondListHeaderViewHolder(v);
            return vh;

        } else {
            // SECOND_LIST_ITEM_VIEW
            v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_second_list, parent, false);
            SecondListItemViewHolder vh = new SecondListItemViewHolder(v);
            return vh;
        }
    }

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

        try {
            if (holder instanceof SecondListItemViewHolder) {
                SecondListItemViewHolder vh = (SecondListItemViewHolder) holder;
                vh.bindViewSecondList(position);

            } else if (holder instanceof FirstListHeaderViewHolder) {
                FirstListHeaderViewHolder vh = (FirstListHeaderViewHolder) holder;

            } else if (holder instanceof FirstListItemViewHolder) {
                FirstListItemViewHolder vh = (FirstListItemViewHolder) holder;
                vh.bindViewFirstList(position);

            } else if (holder instanceof SecondListHeaderViewHolder) {
                SecondListHeaderViewHolder vh = (SecondListHeaderViewHolder) holder;

            } else if (holder instanceof FooterViewHolder) {
                FooterViewHolder vh = (FooterViewHolder) holder;
                vh.bindViewFooter(position);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public int getItemCount() {

        int firstListSize = 0;
        int secondListSize = 0;

        if (secondList == null && firstList == null) return 0;

        if (secondList != null)
            secondListSize = secondList.size();
        if (firstList != null)
            firstListSize = firstList.size();

        if (secondListSize > 0 && firstListSize > 0)
            return 1 + firstListSize + 1 + secondListSize + 1;   // first list header, first list size, second list header , second list size, footer
        else if (secondListSize > 0 && firstListSize == 0)
            return 1 + secondListSize + 1;                       // second list header, second list size, footer
        else if (secondListSize == 0 && firstListSize > 0)
            return 1 + firstListSize;                            // first list header , first list size
        else return 0;
    }

    @Override
    public int getItemViewType(int position) {

        int firstListSize = 0;
        int secondListSize = 0;

        if (secondList == null && firstList == null)
            return super.getItemViewType(position);

        if (secondList != null)
            secondListSize = secondList.size();
        if (firstList != null)
            firstListSize = firstList.size();

        if (secondListSize > 0 && firstListSize > 0) {
            if (position == 0) return FIRST_LIST_HEADER_VIEW;
            else if (position == firstListSize + 1)
                return SECOND_LIST_HEADER_VIEW;
            else if (position == secondListSize + 1 + firstListSize + 1)
                return FOOTER_VIEW;
            else if (position > firstListSize + 1)
                return SECOND_LIST_ITEM_VIEW;
            else return FIRST_LIST_ITEM_VIEW;

        } else if (secondListSize > 0 && firstListSize == 0) {
            if (position == 0) return SECOND_LIST_HEADER_VIEW;
            else if (position == secondListSize + 1) return FOOTER_VIEW;
            else return SECOND_LIST_ITEM_VIEW;

        } else if (secondListSize == 0 && firstListSize > 0) {
            if (position == 0) return FIRST_LIST_HEADER_VIEW;
            else return FIRST_LIST_ITEM_VIEW;
        }

        return super.getItemViewType(position);
    }
}

还有另一种方法可以将您的项目保存在单个 ArrayList 对象中,以便您可以设置一个属性标记项目以指示哪个项目来自第一个列表,哪个项目属于第二个列表。然后将 ArrayList 传递到您的 RecyclerView 中,然后在适配器内部实现逻辑以动态填充它们。

希望有帮助。

原文由 Reaz Murshed 发布,翻译遵循 CC BY-SA 4.0 许可协议

前一段时间我遇到了类似的问题,在我的案例中发生的事情是外部回收器视图工作得很好但是内部/第二个回收器视图的适配器有一些小问题所有方法都像构造函数一样被启动甚至 getCount() 方法被调用,虽然最终方法负责生成视图,即..

1. onBindViewHolder() 方法从未被调用。 –> 问题1。

2. 当它最终被调用时,它从不显示回收者视图的列表项/行。 –> 问题2。

发生这种情况的原因:当您将一个回收器视图放入另一个回收器视图时,第一个/外部回收器视图的高度不会自动调整。它是在创建第一个/外部视图时定义的,然后它保持固定。那时你的第二个/内部回收者视图还没有加载它的项目,因此它的高度被设置为零并且即使在它获取数据时也不会改变。然后,当调用第二个/内部回收器视图 的 onBindViewHolder() 时,它会获取项目但没有空间显示它们,因为它的高度仍然为零。因此,即使 onBindViewHolder() 将它们添加到其中,第二个回收器视图中的项目也不会显示。

解决方案:: 您必须为第二个回收器视图创建自定义 LinearLayoutManager,仅此而已。要创建您自己的 LinearLayoutManager: 创建一个名称为 CustomLinearLayoutManager 的 Java 类并将下面的代码粘贴到其中。 无需更改

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

原文由 Khay 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题