在没有数据的情况下在RecyclerView/ListView中创建视图

问题描述:

我想创建一个类似于WhatsApp的视图。我收到的数据是存储在对象的ArrayList中的一组对话。该对象具有消息的所有属性,即, sendersID,receiversID,MessageID,消息,时间戳等。我已经能够创建基于sendersID == myID条件膨胀的发送者/接收者视图。在没有数据的情况下在RecyclerView/ListView中创建视图

我面临的问题是用什么条件来膨胀datelayout。我不想在我的arrayList中添加新数据来检测日期更改。是否可以在不操纵列表数据的情况下获取视图?我已经完成了页眉和页脚视图,这很容易检测到第一个/最后一个项目。但是从适配器检测日期变化并从那里创建视图看起来是一个挑战。为了扩大同样的想法,我计划在我的List/Recycler中添加不同种类的视图,并且会喜欢解决这类问题的解决方案。

+0

如果你喜欢做有风险的,在使用测试版的产品没有问题,你可以看看机器人会数据绑定功能 - 这将帮助你更新你的看法。 我想说,使用RecyclerView.Adapter将不同的布局膨胀为'sectionheader'并不难,只需在正确的条件下设置并检查Adapters方法中的viewType即可。 – yennsarah

+0

只需在更新数据模型后调用适配器上的notifyDataSetChanged即可实现该功能,那么问题是什么? – Nanoc

+0

问题是关于基于某些条件(如检测和显示日期更改)创建额外的视图,其数据在arrayList中不可用。数组列表仅包含与对话时间戳的对话。你可以参考相同的whatsapp。 – Roadblock

注意:为清楚起见,我将把您的数据对象称为“消息”。

您可以用两种方法之一处理日期TextView。无论哪种方法都行得通,尽管我的倾向是#2的效果更好一些。

1.日期TextView是一个独立的项目,除了收集消息之外,适配器还需要考虑它们。

2.日期TextView包含在表示消息的项目(例如,它是在该行的布局XML),你只需要确定哪些行使其可见,哪些没有。


适配器端更有趣一点。根据上面采用的方法,您需要修改由getCount()ListView)或getItemCount()RecyclerView)报告的项目数,或者您需要跟踪哪些项目具有其他显示逻辑。当然,您可能需要预先处理集合(如果可能,在后台进行),以发现并存储这些额外的信息。以下可能性是我过去使用过的所有东西:

A.修改您的数据结构以跟踪日期及其在数据集中的位置;它可能仅仅是封装在某个包装类中的两个集合。您的数据提取逻辑可能应该返回此结构,而不是收集消息。这可以与以上的#1numItems = numMessages + numDates)或#2numItems = numMessages)一起使用。

B.不要修改您的数据结构,但在消息中添加一个可变字段(boolean)。您的预处理只是标记哪些消息需要显示日期。这几乎只适用于#2以上。

C.如果日期是真正“分离”两个消息的唯一事情,那么可以让您的适配器知道数据的“部分”,并且您只需在开始(或结束时显示日期,由你决定)。你并不需要修改您的收藏要做到这一点,例如:

List<Message> items; 
List<AdapterSection> sections; 

static class AdapterSection { 
    int start; // an index of the items list, e.g. in the range [0, items.size()) 
    int count; // how many items in the section 
} 

切片适配器可以同#1#以上2工作。如果您正在使用#1,那么您可以让每个部分报告其自己的大小(日期加1),并且仅对部分大小进行求和。这种方法的主要缺点是在数据发生变化时使这些部分与您的数据保持同步。

我会打电话D的最后一个选项根本不需要任何预处理。当您的适配器绑定某个项目的数据时,您可以查看下一个项目并确定是否需要显示日期。这只适用于#2以上。下面是基于RecyclerView适配器上一些伪代码:

@Override 
public void onBindViewHolder(MessageViewHolder holder, int position) { 
    Message item = getItem(position); 
    // bind stuff to views ... 

    if (position < getItemCount() - 1) { 
     Message nextItem = getItem(position + 1); 
     if (hasDifferentDates(item, nextItem) { 
      // show TextView, bind date ... 
     } else { 
      // hide TextView 
     } 
    } 
}