Android kotlin / java - ReclerView странное поведение при скрытии деталей в держателе / ​​xml - PullRequest
0 голосов
/ 06 ноября 2018

Я не знал, какой может быть правильный заголовок для этой проблемы.

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

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

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

enter image description here

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

enter image description here

Надеюсь, проблема понятна.

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

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

EDIT:

Весь адаптер:

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>

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

Не называйте это ошибкой, если вы не понимаете, как работает шаблон ViewHolder.

Вы должны были использовать несколько itemViewType s вместо того, чтобы переключать видимость друг на друга (обратите внимание, что весь этот код входит в ваш 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>
0 голосов
/ 06 ноября 2018

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...