【问题标题】:Mutiple RecyclerView items not appearing correctly多个 RecyclerView 项目未正确显示
【发布时间】:2018-10-08 14:37:41
【问题描述】:

我正在尝试为我的 RecyclerView 中的多个项目充气,但它部分有效。 A、B、F 和 G 项按预期完美显示,但 C、D 和 E 项并非如此。

问题

  1. 为什么项目 G 应该只出现一次却会重复多次?
  2. 为什么Section C只显示Item C1,而不显示Item C1Item C7
  3. 为什么 Section D 只显示 Item D1 而不是显示 Item D1Item D4
  4. 为什么Section E只显示Item E1而不是显示Item E1Item E4

不确定在正确使用android:layout_height="wrap_content" 时会发生上述情况。我感觉position 和/或getItemCount 方法与这些问题有关,但我不确定。

当前结果

fragment_rv.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearLayout_recyclerView"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.RecyclerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/my_recyclerview"
        android:clipToPadding="false"
        android:paddingStart="12dp"
        android:paddingEnd="12dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="vertical"
        android:scrollbarSize="3dp">
    </android.support.v7.widget.RecyclerView>
</LinearLayout>

rv_item_tv.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:focusable="true"
    android:id="@+id/cv_tv"
    android:layout_marginTop="10dp"
    android:layout_marginBottom="20dp">

    <LinearLayout
        android:id="@+id/cardview_tv_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="10dp">

        <LinearLayout
            android:id="@+id/cardview_titlerow"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginBottom="2dp"
            android:weightSum="100">

            <TextView
                android:id="@+id/tv_expandcollapsearrow"
                android:importantForAccessibility="no"
                android:clickable="true"
                android:focusable="true"
                android:layout_weight="10"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginEnd="10dp"
                android:textColor="?android:attr/textColorPrimary"
                style="@android:style/TextAppearance.Large" />

            <TextView
                android:id="@+id/tv_title"
                android:layout_weight="90"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                style="@android:style/TextAppearance.Large" />
        </LinearLayout>

        <LinearLayout
            android:id="@+id/ll_information_tv"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/tv_for_rv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="?android:attr/textColorPrimary"
                style="@android:style/TextAppearance.Medium" />
        </LinearLayout>
    </LinearLayout>
</android.support.v7.widget.CardView>

片段类

public class MyFragment extends android.support.v4.app.Fragment {

    private static final int HEADER_TYPE_EXPANDALL = 101;
    private static final int HEADER_TYPE_COLLAPSEALL = 102;
    private static final int ITEM_TYPE_A = 103;
    private static final int ITEM_TYPE_B = 104;
    private static final int SECTION_TYPE_C = 105;
    private static final int ITEM_TYPE_C = 106;
    private static final int SECTION_TYPE_D = 107;
    private static final int ITEM_TYPE_D = 108;
    private static final int SECTION_TYPE_E = 109;
    private static final int ITEM_TYPE_E = 110;
    private static final int ITEM_TYPE_F = 111;
    private static final int ITEM_TYPE_G = 112;

    public MyFragment() {}

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_rv, container, false);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        View v = getView();
        assert v != null;

        recyclerView = v.findViewById(R.id.my_recyclerview);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));

        dataSectionCTitle = new ArrayList<>();
        dataSectionCTitle.add(getString(R.string.c1));
        dataSectionCTitle.add(getString(R.string.c2));
        dataSectionCTitle.add(getString(R.string.c3));
        dataSectionCTitle.add(getString(R.string.c4));
        dataSectionCTitle.add(getString(R.string.c5));
        dataSectionCTitle.add(getString(R.string.c6));
        dataSectionCTitle.add(getString(R.string.c7));

        dataSectionCDescription = new ArrayList<>();
        dataSectionCDescription.add(getString(R.string.c1_description));     
        dataSectionCDescription.add(getString(R.string.c2_description));
        dataSectionCDescription.add(getString(R.string.c3_description));
        dataSectionCDescription.add(getString(R.string.c4_description));
        dataSectionCDescription.add(getString(R.string.c5_description));
        dataSectionCDescription.add(getString(R.string.c6_description));
        dataSectionCDescription.add(getString(R.string.c7_description));

        dataSectionDTitle = new ArrayList<>();
        dataSectionDTitle.add(getString(R.string.d1));
        dataSectionDTitle.add(getString(R.string.d2));
        dataSectionDTitle.add(getString(R.string.d3));
        dataSectionDTitle.add(getString(R.string.d4));

        dataSectionDDescription = new ArrayList<>();
        dataSectionDDescription.add(getString(R.string.d1_description));
        dataSectionDDescription.add(getString(R.string.d2_description));
        dataSectionDDescription.add(getString(R.string.d3_description));
        dataSectionDDescription.add(getString(R.string.d4_description));

        dataSectionETitle = new ArrayList<>();
        dataSectionETitle.add(getString(R.string.e1));
        dataSectionETitle.add(getString(R.string.e2));
        dataSectionETitle.add(getString(R.string.e3));
        dataSectionETitle.add(getString(R.string.e4));

        dataSectionEDescription = new ArrayList<>();
        dataSectionEDescription.add(getString(R.string.e1_description));
        dataSectionEDescription.add(getString(R.string.e2_description));
        dataSectionEDescription.add(getString(R.string.e3_description));
        dataSectionEDescription.add(getString(R.string.e4_description));

        adapter = createAdapter();
        recyclerView.setAdapter(adapter);

        super.onActivityCreated(savedInstanceState);
    }

    RecyclerView recyclerView;
    ArrayList<String> dataSectionCTitle;
    ArrayList<String> dataSectionCDescription;
    ArrayList<String> dataSectionDTitle;
    ArrayList<String> dataSectionDDescription;
    ArrayList<String> dataSectionETitle;
    ArrayList<String> dataSectionEDescription;
    RecyclerView.Adapter<MyFragment.ViewHolder> adapter;

    private RecyclerView.Adapter<MyFragment.ViewHolder> createAdapter() {
        return new RecyclerView.Adapter<MyFragment.ViewHolder>() {
            private boolean expandedAll;
            private boolean collapsedAll;

            @NonNull
            @Override
            public MyFragment.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int type) {
                switch (type) {
                    case HEADER_TYPE_EXPANDALL:
                        return new MyFragment.ViewHolder(inflateHelper(R.layout.recyclerview_header, parent));

                    case HEADER_TYPE_COLLAPSEALL:
                        return new MyFragment.ViewHolder(inflateHelper(R.layout.recyclerview_header, parent));

                    case ITEM_TYPE_A:
                        return new MyFragment.ViewHolder(inflateHelper(R.layout.rv_item_tv, parent));

                    case ITEM_TYPE_B:
                        return new MyFragment.ViewHolder(inflateHelper(R.layout.rv_item_tv, parent));

                    case SECTION_TYPE_C:
                        return new MyFragment.ViewHolder(inflateHelper(R.layout.linearlayout_rvsectionheader, parent));

                    case ITEM_TYPE_C:
                        return new MyFragment.ViewHolder(inflateHelper(R.layout.rv_item_tv, parent));

                    case SECTION_TYPE_D:
                        return new MyFragment.ViewHolder(inflateHelper(R.layout.linearlayout_rvsectionheader, parent));

                    case ITEM_TYPE_D:
                        return new MyFragment.ViewHolder(inflateHelper(R.layout.rv_item_tv, parent));

                    case SECTION_TYPE_E:
                        return new MyFragment.ViewHolder(inflateHelper(R.layout.linearlayout_rvsectionheader, parent));

                    case ITEM_TYPE_E:
                        return new MyFragment.ViewHolder(inflateHelper(R.layout.rv_item_tv, parent));

                    case ITEM_TYPE_F:
                        return new MyFragment.ViewHolder(inflateHelper(R.layout.rv_item_tv, parent));

                    case ITEM_TYPE_G:
                        return new MyFragment.ViewHolder(inflateHelper(R.layout.rv_item_tv, parent));

                    default:
                        return new MyFragment.ViewHolder(inflateHelper(R.layout.rv_item_tv, parent));
                }
            }

            /**
             * Keep the viewholder simple and all the view finding here.
             * This way you only have one viewholder.
             */
            @Override
            public void onBindViewHolder(@NonNull MyFragment.ViewHolder viewHolder, int position) {
                final Typeface iconFont = FontManager.getTypeface(getContext(), FontManager.FONTAWESOME);
                final LinearLayout llFacilityInformation = viewHolder.itemView.findViewById(R.id.ll_information_tv);
                final TextView txtArrowTitleSectionHeader = viewHolder.itemView.findViewById(R.id.tv_sectionheaderforrv_expandcollapsearrow);
                final TextView txtTitle = viewHolder.itemView.findViewById(R.id.tv_title);
                final TextView txtTVTitleSectionHeader = viewHolder.itemView.findViewById(R.id.tv_sectionheaderforrv_title);
                final TextView txtSubtitle = viewHolder.itemView.findViewById(R.id.tv_for_rv);

                final TextView txtArrowCV = viewHolder.itemView.findViewById(R.id.tv_expandcollapsearrow);

                //
                CardView cardView = viewHolder.itemView.findViewById(R.id.cv_tv);
                LinearLayout mLinearLayoutTV = viewHolder.itemView.findViewById(R.id.cardview_titlerow); 

                switch (getItemViewType(position)) {
                    case HEADER_TYPE_EXPANDALL:
                        Button expandButton = viewHolder.itemView.findViewById(R.id.button);
                        expandButton.setText(R.string.expand_all);
                        break;
                    case HEADER_TYPE_COLLAPSEALL:
                        Button collapseButton = viewHolder.itemView.findViewById(R.id.button);
                        collapseButton.setText(R.string.collapse_all);
                        break;
                    case ITEM_TYPE_A:
txtTitle.setText(R.string.a1);
                        txtSubtitle.setText(R.string.a1_description);
                        txtArrow.setVisibility(View.GONE);
                        break;
                    case ITEM_TYPE_B:
txtTitle.setText(R.string.b1);
txtSubtitle.setText(R.string.b1_description);
                        break;
                    case SECTION_TYPE_C:
                        txtArrowTitleSectionHeader.setText(R.string.fa_icon_chevron_down);
                        txtArrowTitleSectionHeader.setTypeface(iconFont);

                        txtTVTitleSectionHeader.setText(R.string.general);
                        txtTVTitleSectionHeader.setPaintFlags(txtArrowTitleSectionHeader.getPaintFlags()| Paint.UNDERLINE_TEXT_FLAG);
                        break;
                    case ITEM_TYPE_C:
                        String itemCTitle = dataSectionCTitle.get(position - 5);
                        String itemCSubtitle = dataSectionCSubtitle.get(position - 5);

                        txtTitle.setText(itemGeneralTitle);
                        txtSubtitle.setText(itemGeneralSubtitle);
                        txtArrowCV.setVisibility(View.GONE);
                        break;
                    case SECTION_TYPE_D:
                        txtArrowTitleSectionHeader.setText(R.string.fa_icon_chevron_down);
                        txtArrowTitleSectionHeader.setTypeface(iconFont);

                        txtTVTitleSectionHeader.setText(R.string.main_ticket_hall);
                        txtTVTitleSectionHeader.setPaintFlags(txtArrowTitleSectionHeader.getPaintFlags()| Paint.UNDERLINE_TEXT_FLAG);
                        break;
                    case ITEM_TYPE_D:
                        String itemDTitle = dataSectionDTitle.get(position - 7);
                        String itemDSubtitle = dataSectionDSubtitle.get(position - 7);

                        txtTitle.setText(itemDTitle);
                        txtSubtitle.setText(itemDSubtitle);

                        txtArrowCV.setVisibility(View.GONE);
                        break;
                    case SECTION_TYPE_E:
                        txtArrowTitleSectionHeader.setText(R.string.fa_icon_chevron_down);
                        txtArrowTitleSectionHeader.setTypeface(iconFont);

                        txtTVTitleSectionHeader.setText(R.string.section_e);
                        txtTVTitleSectionHeader.setPaintFlags(txtArrowTitleSectionHeader.getPaintFlags()| Paint.UNDERLINE_TEXT_FLAG);
                        break;
                    case ITEM_TYPE_E:
                        String itemETitle = dataSectionETitle.get(position - 9);
                        String itemESubtitle = dataSectionESubtitle.get(position - 9);

                        txtTitle.setText(itemETitle);
                        txtSubtitle.setText(itemESubtitle);

                        txtArrowCV.setVisibility(View.GONE);
                        break;
                    case ITEM_TYPE_F:
                        txtTitle.setText(R.string.item_f);
                        break;
                    case ITEM_TYPE_G:
                        txtTitle.setText(R.string.item_g);
                        txtSubtitle.setText(R.string.placeholder1);

                        txtArrowCV.setText(R.string.fa_icon_chevron_down);
                        txtArrowCV.setTypeface(iconFont);

                        break;
                }
            }

            @Override
            public int getItemCount() {
                return dataSectionCTitle.size() + 12;
            }

            @Override
            public int getItemViewType(int position) {
                switch (position) {
                    case 0:
                        return HEADER_TYPE_EXPANDALL;
                    case 1:
                        return HEADER_TYPE_COLLAPSEALL;
                    case 2:
                        return ITEM_TYPE_A;
                    case 3:
                        return ITEM_TYPE_B;
                    case 4:
                        return SECTION_TYPE_C;
                    case 5:
                        return ITEM_TYPE_C;
                    case 6:
                        return SECTION_TYPE_D;
                    case 7:
                        return ITEM_TYPE_D;
                    case 8:
                        return SECTION_TYPE_E;
                    case 9:
                        return ITEM_TYPE_E;
                    case 10:
                        return ITEM_TYPE_F;
                    case 11:
                        return ITEM_TYPE_G;
                    default:
                        return ITEM_TYPE_G;
                }
            }
        };
    }

    private View inflateHelper(int resId, ViewGroup parent) {
        return LayoutInflater.from(getActivity()).inflate(resId, parent, false);
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        ViewHolder(@NonNull View itemView) {
            super(itemView);
        }
    }
}

【问题讨论】:

  • 你为什么要在 getItemCount 中 +12?

标签: java android xml android-recyclerview android-cardview


【解决方案1】:

您的尺码看起来不正确

public int getItemCount() {
    return dataSectionCTitle.size() + 12;
}

它应该是所有部分的总和(包含在它自己的行中的每个项目)

这意味着getItemViewType(int position) 也是错误的,因为它硬编码了与视图类型相关的位置,而不是处理前面数据集的大小

【讨论】:

  • 如何查看前面数据集的大小?我刚刚尝试返回 dataSectionCTitle.size() + 22;Item G 只是重复更多。
  • @MacaronLover :: "G" 重复多次的部分问题是因为上面的代码getItemCount() 添加了比实际列表中明显更多的项目。而在getItemViewType() 中,“ITEM_TYPE_G”是你的默认类型。
  • @Barns in this secnario,你知道默认类型应该是什么吗?
  • @MacaronLover :: 说实话——代码看起来像是复制/粘贴的噩梦,无法灵活控制数据的呈现。你确实需要考虑一个模型和视图结构来适应你的数据集。抱歉,如果这听起来有点居高临下,但我真诚地建议您重新考虑和重新设计,重点放在数据模型上。祝你好运
  • @Barns 设计不是这里的问题。代码还可以。我不知道为这些数据编写代码的更好方法。
猜你喜欢
  • 1970-01-01
  • 2016-08-17
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
相关资源
最近更新 更多