Android kotlin / java - Странное поведение ReclerView при скрытии деталей в файле holder / xml

Я не знал, каким может быть подходящее название для этого выпуска.

Я делаю приложение для чата, и это часть внутри адаптера:

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++
        }

Результат такой:

Android kotlin / java - Странное поведение ReclerView при скрытии деталей в файле holder / xml

И когда я не скрываю никаких макетов, тогда текст внутри макета, который не обновляется, все равно заполняется случайными старыми вещами:

Android kotlin / java - Странное поведение ReclerView при скрытии деталей в файле holder / xml

Надеюсь, вопрос понятен.

Как я могу это исправить? Например, полностью удалить макет, который не обновляется или что-то в этом роде.

заранее спасибо

Обновлено:

Целый адаптер:

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>

Вы не должны использовать if (msg.who == "you"), вместо этого используйте if (msg.who.contentEquals("you")) в вашем операторе if.

Barns 06.11.2018 18:19

Я не понимаю, о каком «странном поведении» вы говорите. В «TextView» нет ничего случайного, и если вы не скроете View, он останется видимым.

Barns 06.11.2018 18:31

Второе изображение просто показывает, что recyclerview все еще чем-то заполняет держатель. Основная проблема показана на первом изображении. Посмотрите на количество и расстояние между ними

user9567456 06.11.2018 18:36
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
120
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

После попытки установить ширину / высоту неиспользуемого держателя на 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>

Объясните, пожалуйста, как «раздуть только« свой »макет». Завтра протестирую, на сегодня готово.

user9567456 06.11.2018 20:25

@EduardUnruh, вы не разместили свой onCreateViewHolder (включая XML с расширенным макетом) или свой класс ViewHolder, поэтому я не буду гадать, как это сделать.

Pawel 06.11.2018 21:07

Но на самом деле было бы достаточно быстрого примера того, как раздуть разные макеты, чтобы другие тоже могли их использовать, а не только я ^^

user9567456 07.11.2018 16:07

@EduardUnruh добавил пример кода, использовал упрощенный макет, потому что я не был уверен, почему у вас было 8 макетов только для отображения 1 текстового представления.

Pawel 07.11.2018 20:30

Другие вопросы по теме