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

标签 android notifications android-recyclerview

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

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

除了尖括号文本之外,它是代表那些的实际 View ,包括图像、实际通知详细信息和分隔线。

我已经有了在 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>

Java:

@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...");
        }
    });
}

这一切都很好,足以显示所有通知,并且它们都按照从最新到最旧的降序排列。但是每个都有一个 bool 属性“已确认”,如果用户以前没有见过它们,则该属性设置为 false。我想使用此标志将列表分成我在上面解释过的两组,但我不知道如何放入标题。我考虑过对 Notification 进行子类化以创建 NotificationHeader View 并将它们插入适当的列表中,但这对我来说感觉很草率。我还考虑过做两个回收 View ,一个用于新 View ,另一个用于旧 View ,但在视觉上并没有按照我预期的方式工作(我还没有确认,但看起来每个回收 View 都独立于其他人,我不想要的东西)。有什么建议吗?

我知道创建特殊通知 header 的第一个想法可能会奏效,我以前也做过类似的事情,但感觉这是一种糟糕的做法。

最佳答案

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

@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 展开。

这里有一些我应该做的更好的样式/最佳实践决定,例如让我的通知适配器保存一个 NotificationListItems 列表而不是通知,这将允许我自己放入一种新的 NotificationHeader 对象而不是制作不是真正通知的通知对象并使用一堆常量值。但基本原则仍然存在:

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

关于android - 如何在 recyclerview 中对列表项进行分类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32789529/

相关文章:

java - android TextWatcher 中的 stackoverflow

java - 如何从 ListView 启动一个 Activity

android - 如何将不同的图像添加到 android 中不同选择的 ListView ?

android - 让 Android 的 ZoomButtonsController 和 GestureDetector 相处融洽

java - 获取解雇通知 ID

android - 检测 RecyclerView 中呈现项目的列

android - 如何创建类似instagram的底部导航栏

.net - Microsoft.WindowsAzure.Messaging.NotificationHub 和 Microsoft.Azure.NotificationHubs.NotificationHubClient 之间有什么区别?

java - Java 中 'event' 驱动的内容通知服务的设计模式是什么?

android - 滑动以在回收站 View android 中显示另一个隐藏的布局