首页 > 解决方案 > 当用户滚动时如何显示或隐藏日期文本视图就像whatsapp聊天android Kotlin

问题描述

嘿,我正在开发聊天应用程序。我完成了我的传入和传出消息如何为传入和传出的聊天消息使用不同的布局。我也试过这个How to show date in between conversation in recyclerview 或 in listview。我添加了输出我的一切看起来如何。

对话适配器.kt

class ConversationAdapter : ListAdapter<Message, RecyclerView.ViewHolder>(MESSAGE_COMPARATOR) {

    companion object {
        private val MESSAGE_COMPARATOR = object : DiffUtil.ItemCallback<Message>() {
            override fun areItemsTheSame(oldItem: Message, newItem: Message): Boolean {
                return oldItem.id == newItem.id
            }

            override fun areContentsTheSame(oldItem: Message, newItem: Message): Boolean {
                return ((oldItem.name == newItem.name) && (oldItem.text == oldItem.text)
                        && (oldItem.time == newItem.time) && (oldItem.type == newItem.type))
            }

        }

        private const val INCOMING_MESSAGE = 1
        private const val OUTGOING_MESSAGE = 2
        private const val TIMING = 3
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            INCOMING_MESSAGE -> {
                IncomingViewHolder(
                    IncomingLayoutBinding.inflate(
                        LayoutInflater.from(parent.context),
                        parent,
                        false
                    )
                )
            }
            OUTGOING_MESSAGE -> {
                OutGoingViewHolder(
                    OutgoingLayoutBinding.inflate(
                        LayoutInflater.from(parent.context),
                        parent,
                        false
                    )
                )
            }
            else -> {
                TimingViewHolder(
                    TimingLayoutBinding.inflate(
                        LayoutInflater.from(parent.context),
                        parent,
                        false
                    )
                )
            }
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            is IncomingViewHolder -> {
                holder.bindItem(getItem(position))
            }
            is OutGoingViewHolder -> {
                holder.bindItem(getItem(position))
            }
            is TimingViewHolder -> {
                holder.bindItem(getItem(position))
            }
        }
    }

    override fun getItemViewType(position: Int): Int {
        return when {
            getItem(position).type.equals("incoming") -> {
                INCOMING_MESSAGE
            }
            getItem(position).type.equals("outgoing") -> {
                OUTGOING_MESSAGE
            }
            getItem(position).type.equals("added") -> {
                TIMING
            }
            else -> {
                super.getItemViewType(position)
            }
        }
    }


    inner class IncomingViewHolder(val binding: IncomingLayoutBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bindItem(item: Message) {
            binding.incomingMessage.text = item.text
        }
    }

    inner class OutGoingViewHolder(val binding: OutgoingLayoutBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bindItem(item: Message) {
            binding.outGoingMessage.text = item.text
        }
    }

    inner class TimingViewHolder(val binding: TimingLayoutBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bindItem(item: Message) {
            binding.timing.text = item.time
        }
    }
}

MM.kt

data class Message(
    val id: String? = null,
    val text: String? = null,
    val time: String? = null,
    val type: String? = null,
    val name: String? = null
)

MainActivity.kt

class MainActivity : BaseActivity() {
    
        lateinit var binding: MainLayoutBinding
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            binding = MainLayoutBinding.inflate(layoutInflater)
            setContentView(binding.root)
            setupAdapter()
        }
    
        private fun setupAdapter() {
     val list = listOf<Message>(
            Message(id = "1", text = "avc", time = "2021-10-08T15:34:00", type = "outgoing"),
            Message(id = "2", text = "dsds", time = "2021-10-08T15:36:00", type = "incoming"),
            Message(id = "3", type = "added", time = "2021-10-08T00:00:00", name = "ABC"),
            Message(id = "4", type = "added", time = "2021-10-07T15:50:00", name = "XYZ"),
            Message(id = "5", text = "asvc", time = "2021-10-07T15:46:00", type = "outgoing"),
            Message(id = "6", text = "asvc", time = "2021-10-07T15:46:00", type = "incoming"),
            Message(id = "6", text = "asvc", time = "2021-10-06T12:34:00", type = "outgoing"),
            Message(id = "8", text = "asvc", time = "2021-10-06T12:50:00", type = "incoming"),
            Message(id = "9", type = "added", time = "2021-10-06T12:46:00", name = "DEF")
        )
        val adapter = ConversationAdapter()
        binding.conversationRecyclerView.adapter = adapter
        adapter.submitList(list)
    
        }
    }

计时布局.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:background="@color/aqua"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/timing"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

传入布局.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:background="@color/red"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/incomingMessage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

传出布局.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:background="@color/yellow"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/outGoingMessage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

输出

在此处输入图像描述

如何实现其他功能。

1.如何对我的日期进行分类以有效地显示每天对话之间的日期,因为我的列表太大了。我刚刚添加了示例

2.用户滚动聊天时如何显示日期的滚动效果,就像whatsapp有昨天,今天和其他日期格式一样。

3.在上面的列表示例中,添加了一个属性,这意味着在群聊中添加了某人。在 whatsapp XYZ 中使用群组邀请链接加入。

我正在添加 whatsapp 的屏幕截图

在此处输入图像描述 在此处输入图像描述

标签: androidkotlinandroid-layoutandroid-recyclerviewandroid-adapter

解决方案


即使不清楚“这在我的解决方案中不起作用”是什么意思,我也不知道问题是崩溃还是空列表还是......但是检查方法中的项目的逻辑areItemsTheSameareContentsTheSame错误的:该方法areItemsTheSame用于检查旧项目的身份是否等于新项目的身份。该方法areContentsTheSame用于检查 2 项中的值是否相等

因此,areContentsTheSame您必须只检查id项目,因为其他事物是项目的值,而您所写的内容areContentsTheSame没有意义,因为您只是在检查项目的参考。所以把它改成这样:

   private val MESSAGE_COMPARATOR = object : DiffUtil.ItemCallback<MM>() {
        override fun areItemsTheSame(oldItem: MM, newItem: MM): Boolean {
            return oldItem.id == newItem.id
        }

        override fun areContentsTheSame(oldItem: MM, newItem: MM): Boolean {
   return ((oldItem.added == newItem.added)
                    && (oldItem.addedTime == newItem.addedTime)
                    && (oldItem.sentAt == newItem.sentAt)
                    && (oldItem.text == newItem.text))            }

    }

推荐阅读