Android - 垂直滚动视图中的两个Vertical RecyclerView,我需要为每个recyclerview执行更多加载

时间:2016-05-20 10:29:15

标签: android android-recyclerview

我需要RecyclerView内的两个垂直ScrollView。我需要为RecyclerView中的每个列表添加加载更多页脚。如何在Android中实现这一目标?

2 个答案:

答案 0 :(得分:2)

我认为这就是你要找的东西。 Showing multiple lists in a single RecyclerView。我将wiki中的描述用来描述如何轻松实现这一目标。

这是一个简单的模型,可以清楚地说明我们想要实现的目标。

列表标题(第一个列表)

  • 第一个清单第1项
  • 第一个清单第2项
  • 第一个清单第3项

列表标题(第二个列表)

  • 第二个清单第1项
  • 第二个清单第2项
  • 第二个清单第3项
  • 第二个清单第4项

页脚视图

我们来看两个名为firstListsecondList的列表。两者都是一些对象的列表。 您需要在全局范围内声明它们并在全局范围内初始化它们。这样您就不必将任何特定列表传递给Adapter

定义您的观点

因此,在初始化Adapter之前,您需要声明一些常量,以便区分您将在列表中填充的不同类型的视图。例如,在我的情况下,我有五个不同的视图,我为每个项目分配了一个唯一值,以便我可以明确告诉在getItemViewType上调用Adapter时显示哪个视图

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;

定义ViewHolder课程并正确绑定每个项目

现在让我们自定义您的ViewHolder。我们将在这里列出每个列表项中显示的项目实例。我们在这里维护两个不同的列表,让我们假设每个列表都有一个标题和一个描述作为列表项。

因此我们需要获取这些实例并将它们与适当的值绑定。我在我的代码中添加了一个示例,您将在此处看到两个不同的函数bindViewFirstList()bindViewSecondList,以便将UI字段与适当的值绑定。还有另一个函数bindViewFooter()来自定义第二个列表的页脚视图。您可以声明其他一些功能,例如bindViewHeaderFirstList()bindViewHeaderSecondList,以便从此处自定义和设置标头的值。这是ViewHolder的代码示例。

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

        // Have a close look here. We're calculating the appropriate position of the item in the secondList
        // Second list will be populated after the firstList
        // So if the firstList doesn't have any item the secondList will have a header and its items.
        if (firstList == null) pos = pos - 1;
        else {
            // If the firstList is not empty, it'll have its header and its items. See the else part.
            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) {

        // Have a close look here. We're calculating the appropriate position of the item in the firstList
        // 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");
    }
}

为每种类型的视图获取自定义ViewHolder

现在为每个元素声明自定义ViewHolder,以便在onBindViewHolder上调用Adapter时区分它们。

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

为每种类型的列表项获取正确的布局文件

onCreateViewHolder中,您需要return与特定列表项关联的布局。这是我的。

@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;
    }
}

使用onBindViewHolder

中的适当元素填充每种类型的观看次数

检查传递给ViewHolder的{​​{1}}是否是您要在特定 onBindViewHolder 中显示的项目的实例。

position

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

的项目数

这是RecyclerView的一个棘手的部分。你可能有三个案例。您的第一个列表可以是空的,也可以是第二个列表。第三种情况是,两个列表都填充了一些数据。

因此,我们需要在这里考虑这三种情况。在我的例子中,我的第一个列表中有一个标题。如果是我的第二个列表,我想显示一个标题和一个页脚。所以我的Adapter看起来像这样。

getItemCount

@Override public int getItemCount() { int firstListSize = 0; int secondListSize = 0; if (secondList == null && firstList == null) return 0; // Get the sizes of the lists if (secondList != null) secondListSize = secondList.size(); if (firstList != null) firstListSize = firstList.size(); // Case 1: When both lists have data if (secondListSize > 0 && firstListSize > 0) return 1 + firstListSize + 1 + secondListSize + 1; // first list header, first list size, second list header , second list size, footer // Case 2: When only the second list have data else if (secondListSize > 0 && firstListSize == 0) return 1 + secondListSize + 1; // second list header, second list size, footer // Case 3: When only the first list have data else if (secondListSize == 0 && firstListSize > 0) return 1 + firstListSize; // first list header , first list size else return 0; }

返回正确的项目视图

我猜这是getItemViewType中最棘手的部分。您需要计算在给出列表中特定Adapter项目时要返回的项目视图。

完成这项工作的最简单方法是编写首先返回页眉和页脚视图的逻辑。当您完成编写定义页眉和页脚position的逻辑时,很容易为其他人编写。

这就是我管理我的方式。看,我首先定义了页眉和页脚的位置,这些位置为我简化了其他方程式。

position

当需要在单个@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); } 中显示多个列表时,您已完成自定义Adapter的实施。我在code部分添加了一个演示项目。您可以构建和运行项目。

干杯!

答案 1 :(得分:0)

看看这个library,您可以构建如下图所示的内容:

enter image description here

您可以找到该屏幕的完整代码here

然后当用户点击"查看更多" (或"加载更多"在您的情况下),您只需加载更多项目,将它们添加到相应的部分并通知适配器。类似的东西:

worldSection.addItem("Another world news item here");
sectionAdapter.notifyDataSetChanged();