如何在recyclerview中对列表项进行分类?

时间:2015-09-25 19:43:09

标签: android notifications android-recyclerview

我正在为我正在处理的应用程序构建通知列表,但我无法找到从服务器获取通知列表并将其显示在RecyclerView的单独列表中的方法。最终产品将显示带有最近通知和旧通知标题的通知列表,la:

<RECENT HEADER>
    <NOTIF-1>
    <NOTIF-2>
<OLDER HEADER>
    <NOTIF-3>
    <NOTIF-4>
    <NOTIF-5>
    <NOTIF-6>

除了角括号文本之外,它代表那些实际视图,包括图像,实际通知细节和分隔符。

我已经有了在RecyclerView中显示它们的代码:

XML:

<!-- Main layout -->
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/include_toolbar"/>

    <RelativeLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v4.widget.SwipeRefreshLayout
            android:id="@+id/notification_swipe_refresh"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <com.mapjungle.mymoose.ui.widget.EmptyRecyclerView
                android:id="@+id/notification_list"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

        </android.support.v4.widget.SwipeRefreshLayout>

    </RelativeLayout>

</LinearLayout>

爪哇:

@InjectView(R.id.notification_list) RecyclerView mRecyclerView;
@Inject Picasso mPicasso;
@Inject NotificationService mUserService;
private NotificationAdapter mAdatper;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_notifications);
    ButterKnife.inject(this);
    setTitle("Notifications");
    mAdatper = new NotificationAdapter(mPicasso);
    mRecyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this)
            .color(getResources().getColor(R.color.secondary_color))
            .size(1)
            .build());
    final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    mRecyclerView.setLayoutManager(layoutManager);
    mRecyclerView.setAdapter(mAdatper);
    updateList();
}

@Override
protected int getSelfNavDrawerItem() {
    return NAVDRAWER_ITEM_PHOTO_POST;
}

public void updateList() {
    mUserService.getNotifications(new Callback<List<Notification>>() {

        @Override
        public void success(List<Notification> notificationList, Response response) {
            mAdatper.replaceWith(notificationList);
        }

        @Override
        public void failure(RetrofitError error) {
            Timber.e(error, "Failed to load notifications...");
        }
    });
}

这一切都足以显示所有通知,并且它们按照从最新到最低的顺序排序。但每个都有一个布尔属性&#34;承认&#34;如果用户之前没有看到它,则设置为false。我想把列表拆分成我上面用这个标志解释的两个组,但我不知道怎么扔进标题。我已经考虑过继承Notification以创建NotificationHeader视图并将它们插入到适当的列表中,但这对我来说感觉很草率。我还想过做两个回收者的观点,一个用于新的,另一个用于旧的,但在视觉上没有按照我的意图工作(我还没有确认它,但它看起来像每个回收站视图独立于其他视图滚动,这是我不想要的。有什么建议吗?

我知道创建特殊通知标题的第一个想法可能会起作用,我以前做过类似的事情,但这只是感觉不好的做法。

1 个答案:

答案 0 :(得分:1)

RecyclerView.Adapter有一个名为getItemViewType()的方法,它获取适配器列表中项目的位置,并返回它应该使用的视图类型。就我而言,该方法如下所示:

@Override
public int getItemViewType(int position){
    Notification n = mNotifications.get(position);
    boolean useHeader = n.getType().equals(Notification.HEADER_OLDER) ||
            n.getType().equals(Notification.HEADER_RECENT);
    return useHeader ? this.USE_HEADER : this.DONT_USE_HEADER;
}

检查通知列表中的项目,看看它们是否是特殊的静态“标题通知”对象。这在Adapter类内部使用,它将'viewType'参数传递给onCreateViewHolder()方法,我们也覆盖它:

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
    int layout = viewType ==  USE_HEADER ?
            R.layout.view_item_notification_header :
            R.layout.view_item_notification;

    NotificationItemView view = (NotificationItemView) LayoutInflater.from(viewGroup.getContext())
            .inflate(layout, viewGroup, false);
    return new ViewHolder(view);
}

重写此方法允许我们使用viewType参数为ViewHolder选择适当的布局。

我应该在这里做一些更好的风格/良好做法决定,例如让我的Notification适配器保存一个NotificationListItems列表而不是Notifications,这将允许我在它自己上面放入一种新的NotificationHeader对象而不是使Notification对象不是真正的通知并使用一堆常量值。但基本原则仍然存在:

  1. 在您的模型中,有一个返回布局视图的方法
  2. 在你的适配器中覆盖getItemViewType()以使用上述方法并返回一个对应于应该膨胀的布局的int
  3. 在你的适配器中也覆盖onCreateViewHolder()以使用getItemViewType()中的int并相应地膨胀相应的视图