Я не знал, каким может быть подходящее название для этого выпуска.
Я делаю приложение для чата, и это часть внутри адаптера:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val msg = messages[position]
if (msg.who == "you"){
holder.messagemelayout.visibility = View.GONE
holder.messageyou.text = msg.message
}else{
holder.messageyoulayout.visibility = View.GONE
holder.messageme.text = msg.message
}
}
Поэтому, когда сообщение отправляется с помощью me, макет для «вас» (messageyoulayout) скрывается, и наоборот.
Не тогда, когда я добавляю новые сообщения вроде этого:
var count = 1
bbb.setOnClickListener {
messageslist.add(Chat("hey " + count.toString(), "me"))
adapter.notifyItemInserted(adapter.itemCount - 1)
count++
}
Результат такой:
И когда я не скрываю никаких макетов, тогда текст внутри макета, который не обновляется, все равно заполняется случайными старыми вещами:
Надеюсь, вопрос понятен.
Как я могу это исправить? Например, полностью удалить макет, который не обновляется или что-то в этом роде.
заранее спасибо
Обновлено:
Целый адаптер:
class ChatAdapter(val context: Context, private val messages: MutableList<Chat>) : RecyclerView.Adapter<ChatAdapter.ViewHolder>(){
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val msg = messages[position]
if (msg.who == "you"){
holder.messageyou.text = msg.message
holder.messageme.text = ""
holder.messageme.setBackgroundResource(0)
holder.messageyou.setBackgroundResource(R.drawable.round_corners_lightgray_color)
}else{
holder.messageme.text = msg.message
holder.messageyou.text = ""
holder.messageme.setBackgroundResource(R.drawable.round_corners_accent_color)
holder.messageyou.setBackgroundResource(0)
}
}
override fun getItemCount() = messages.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.chat, parent, false)
return ViewHolder(view)
}
class ViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView!!){
val messageyou = itemView!!.messageyou!!
val messageme = itemView!!.messageme!!
val messageyoulayout = itemView!!.messageyoulayout!!
val messagemelayout = itemView!!.messagemelayout!!
}
}
chat.xml:
<?xml version = "1.0" encoding = "utf-8"?>
<android.support.v7.widget.CardView xmlns:android = "http://schemas.android.com/apk/res/android"
xmlns:app = "http://schemas.android.com/apk/res-auto"
xmlns:card_view = "http://schemas.android.com/tools"
android:id = "@+id/malsehn"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_margin = "6dp"
app:cardBackgroundColor = "@android:color/transparent"
app:cardElevation = "0dp">
<LinearLayout
android:id = "@+id/messagemelayout"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:weightSum = "4">
<android.support.constraint.ConstraintLayout
android:layout_width = "0dp"
android:layout_height = "wrap_content"
android:layout_weight = "1">
</android.support.constraint.ConstraintLayout>
<android.support.constraint.ConstraintLayout
android:layout_width = "0dp"
android:layout_height = "wrap_content"
android:layout_weight = "3">
<TextView
android:id = "@+id/messageme"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:background = "@drawable/round_corners_accent_color"
android:paddingLeft = "8dp"
android:paddingTop = "6dp"
android:paddingRight = "8dp"
android:paddingBottom = "6dp"
android:text = "TextView"
android:textColor = "@android:color/white"
android:textSize = "16sp"
app:layout_constraintEnd_toEndOf = "parent"
app:layout_constraintTop_toTopOf = "parent" />
</android.support.constraint.ConstraintLayout>
</LinearLayout>
<LinearLayout
android:id = "@+id/messageyoulayout"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:weightSum = "4">
<android.support.constraint.ConstraintLayout
android:layout_width = "0dp"
android:layout_height = "wrap_content"
android:layout_weight = "3">
<TextView
android:id = "@+id/messageyou"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:background = "@drawable/round_corners_lightgray_color"
android:paddingLeft = "8dp"
android:paddingTop = "6dp"
android:paddingRight = "8dp"
android:paddingBottom = "6dp"
android:text = "TextView"
android:textColor = "@android:color/black"
android:textSize = "16sp"
app:layout_constraintStart_toStartOf = "parent"
app:layout_constraintTop_toTopOf = "parent" />
</android.support.constraint.ConstraintLayout>
<android.support.constraint.ConstraintLayout
android:layout_width = "0dp"
android:layout_height = "wrap_content"
android:layout_weight = "1">
</android.support.constraint.ConstraintLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
Я не понимаю, о каком «странном поведении» вы говорите. В «TextView» нет ничего случайного, и если вы не скроете View, он останется видимым.
Второе изображение просто показывает, что recyclerview все еще чем-то заполняет держатель. Основная проблема показана на первом изображении. Посмотрите на количество и расстояние между ними




После попытки установить ширину / высоту неиспользуемого держателя на 0, удалить фон и некоторые другие вещи, которые все «работали», но создавали другое странное поведение, я нашел единственное работающее решение без ошибок:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val msg = messages[position]
if (msg.who == "you"){
holder.messageyou.text = msg.message
holder.messageme.text = ""
holder.messageme.setBackgroundResource(0)
holder.messageyou.setBackgroundResource(R.drawable.round_corners_lightgray_color)
}else{
holder.messageme.text = msg.message
holder.messageyou.text = ""
holder.messageme.setBackgroundResource(R.drawable.round_corners_accent_color)
holder.messageyou.setBackgroundResource(0)
}
}
Да, вам нужно снова и снова определять фон на ОБЕИХ макетах и говорить держателю, что нечего заливать там, где его на самом деле нет. Android - это беспорядок, который тратит время зря ..
Не называйте это ошибочным беспорядком, если не понимаете, как работает паттерн ViewHolder.
Вам следовало использовать несколько itemViewType вместо последовательного переключения видимости представлений (обратите внимание, что весь этот код входит в ваш RecyclerView.Adapter):
// constants
companion object {
const val TYPE_YOU = 1
const val TYPE_ME = 2
}
/* This method is called to determine what type of ViewHolder should be used to represent item at [position] */
override fun getItemViewType(position: Int) = if (messages[position].who == "you") TYPE_YOU else TYPE_ME
/* [viewType] determines what ViewHolder we should create. */
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val layoutId = when(viewType){
TYPE_YOU -> {
// this viewholder will display only messages from "you", inflate only "you" layout
R.layout.chat_item_you
}
TYPE_ME ->{
// this viewholder will display only messages from "me", inflate only "me" layout
R.layout.chat_item_me
}
else -> throw IllegalArgumentException("Unknown viewType: $viewType")
}
val itemView = LayoutInflater.from(parent.context).inflate(layoutId, parent, false)
return ViewHolder(itemView)
}
// then you can use your original bind method, because "you" and "me" messages will never re-user others ViewHolder
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val msg = messages[position]
if (msg.who == "you"){
// holder.itemViewtype should always be equal to TYPE_YOU here
}else{
// holder.itemViewtype should always be equal to TYPE_ME here
}
holder.message.text = msg.message
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
val txtMessage : TextView = itemView.findViewById(R.id.message)
}
Затем разделите пузыри чата на два отдельных макета:
chat_item_you.xml
<FrameLayout xmlns:android = "http://schemas.android.com/apk/res/android"
android:layout_width = "match_parent"
android:layout_margin = "6dp"
android:layout_height = "wrap_content">
<TextView
android:id = "@+id/message"
style = "@style/ChatBubbleStyle"
android:background = "@drawable/round_corners_lightgray_color"
android:text = "TextView"
android:layout_gravity = "end" />
</FrameLayout>
И то же самое, но с другим цветом и гравитацией:
chat_item_me.xml
<FrameLayout xmlns:android = "http://schemas.android.com/apk/res/android"
android:layout_width = "match_parent"
android:layout_margin = "6dp"
android:layout_height = "wrap_content">
<TextView
android:id = "@+id/message"
style = "@style/ChatBubbleStyle"
android:background = "@drawable/round_corners_blue_color"
android:text = "TextView"
android:layout_gravity = "start" />
</FrameLayout>
Используйте общий стиль в styles.xml, чтобы предотвратить избыточный код:
<style name = "ChatBubbleStyle">
<item name = "android:layout_width">wrap_content</item>
<item name = "android:layout_height">wrap_content</item>
<item name = "android:paddingLeft">8dp</item>
<item name = "android:paddingTop">6dp</item>
<item name = "android:paddingRight">8dp</item>
<item name = "android:paddingBottom">6dp</item>
<item name = "android:textColor">@android:color/black</item>
<item name = "android:textSize">16sp</item>
</style>
Объясните, пожалуйста, как «раздуть только« свой »макет». Завтра протестирую, на сегодня готово.
@EduardUnruh, вы не разместили свой onCreateViewHolder (включая XML с расширенным макетом) или свой класс ViewHolder, поэтому я не буду гадать, как это сделать.
Но на самом деле было бы достаточно быстрого примера того, как раздуть разные макеты, чтобы другие тоже могли их использовать, а не только я ^^
@EduardUnruh добавил пример кода, использовал упрощенный макет, потому что я не был уверен, почему у вас было 8 макетов только для отображения 1 текстового представления.
Вы не должны использовать
if (msg.who == "you"), вместо этого используйтеif (msg.who.contentEquals("you"))в вашем операторе if.