Различный угловой радиус элементов recyclerview

Я создаю приложение для чата на Android с Kotlin.

Я использую recyclerview, и предметы имеют один из 8 фонов в зависимости от того, являются ли они вашими или чужими, и являются ли они первым / последним / средним / единственным во временной группе.

В recyclerview adapter есть обычный метод onBindViewHolder () с установкой этих фонов.

Когда код такой:

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    val message = ...
    ...

    textTV.background = ContextCompat.getDrawable(
        context,
        when {
            msg.isLastInTimeGroup() && !msg.sentByMe -> R.drawable.chat_message_in_last_bg
            msg.isFirstInTimeGroup() && !msg.sentByMe -> R.drawable.chat_message_in_first_bg
            msg.isMiddleInTimeGroup() && !msg.sentByMe -> R.drawable.chat_message_in_middle_bg
            msg.isLastInTimeGroup() && msg.sentByMe -> R.drawable.chat_message_out_last_bg
            msg.isFirstInTimeGroup() && msg.sentByMe -> R.drawable.chat_message_out_first_bg
            msg.isMiddleInTimeGroup() && msg.sentByMe -> R.drawable.chat_message_out_middle_bg
            else -> if (msg.sentByMe) R.drawable.chat_message_out_bg else R.drawable.chat_message_in_bg
        }
    )
}

... он работает и выглядит как первое изображение ниже. Однако неэффективно использовать getDrawable () для каждого элемента. Итак, я извлек из функции чертежи следующим образом:

private val inFirstBg: Drawable? = ContextCompat.getDrawable(ctx, R.drawable.chatMessageInFirstBg)
private val inMiddleBg: Drawable? = ContextCompat.getDrawable(ctx, R.drawable.chatMessageInMiddleBg)
private val inLastBg: Drawable? = ContextCompat.getDrawable(ctx, R.drawable.chatMessageInLastBg)
private val inAloneBg: Drawable? = ContextCompat.getDrawable(ctx, R.drawable.chatMessageInBg)
private val outFirstBg: Drawable? = ContextCompat.getDrawable(ctx, R.drawable.chatMessageOutFirstBg)
private val outMiddleBg: Drawable? = ContextCompat.getDrawable(ctx, R.drawable.chatMessageOutMiddleBg)
private val outLastBg: Drawable? = ContextCompat.getDrawable(ctx, R.drawable.chatMessageOutLastBg)
private val outAloneBg: Drawable? = ContextCompat.getDrawable(ctx, R.drawable.chatMessageOutBg)

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    val message = ...
    ...

    textTV.background = when {
        msg.isLastInTimeGroup() && !msg.sentByMe -> inLastBg
        msg.isFirstInTimeGroup() && !msg.sentByMe -> inFirstBg
        msg.isMiddleInTimeGroup() && !msg.sentByMe -> inMiddleBg
        msg.isLastInTimeGroup() && msg.sentByMe -> outLastBg
        msg.isFirstInTimeGroup() && msg.sentByMe -> outFirstBg
        msg.isMiddleInTimeGroup() && msg.sentByMe -> outMiddleBg
        else -> if (msg.sentByMe) outAloneBg else inAloneBg
    }
} 

... и он начинает выполнять задачи рисования, как на втором рисунке ниже.

Некоторые углы вообще не закруглены, текст выходит за пределы фона и т. д.

Фоновые ресурсы выглядят типично (out_middle):

<shape xmlns:android = "http://schemas.android.com/apk/res/android"
    android:shape = "rectangle">
    <solid android:color = "@color/blue" />
    <corners android:radius = "24dp"
        android:topRightRadius = "4dp"
        android:bottomRightRadius = "4dp"/>
</shape>

Почему? В чем проблема?

Различный угловой радиус элементов recyclerviewРазличный угловой радиус элементов recyclerview

0
0
1 867
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Проблема в том, что рисование настраивается в соответствии с текстом, который вы впервые установили, вы не должны устанавливать одно и то же рисование для каждого элемента, так как ваш размер текста не фиксирован.

Получение предыстории для каждого ресурса не является неэффективным. Я уверен, что ваш первый метод не задержится. Чтобы проверить неэффективность, проверьте время, которое требуется для выполнения фрагмента кода, а также проверьте память, прокрутив минимум 100 элементов, и посмотрите, как он себя ведет. Сообщите мне, если у вас возникнут проблемы.

Почему бы не использовать несколько типов itemView? Таким образом, drawable будет загружаться один раз для каждого ViewHolder и будет повторно использоваться соответствующим образом при прокрутке. Для простоты вы можете использовать свой идентификатор ресурса с возможностью рисования как itemViewType, попробуйте следующее:

override fun getItemViewType(position: Int): Int {
    val msg = ... // retrieve msg for [position] from dataset
    return when {
        msg.isLastInTimeGroup() && !msg.sentByMe -> R.drawable.chat_message_in_last_bg
        msg.isFirstInTimeGroup() && !msg.sentByMe -> R.drawable.chat_message_in_first_bg
        msg.isMiddleInTimeGroup() && !msg.sentByMe -> R.drawable.chat_message_in_middle_bg
        msg.isLastInTimeGroup() && msg.sentByMe -> R.drawable.chat_message_out_last_bg
        msg.isFirstInTimeGroup() && msg.sentByMe -> R.drawable.chat_message_out_first_bg
        msg.isMiddleInTimeGroup() && msg.sentByMe -> R.drawable.chat_message_out_middle_bg
        else -> if (msg.sentByMe) R.drawable.chat_message_out_bg else R.drawable.chat_message_in_bg
    }
}

Затем используйте это значение в onCreateViewHolder:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    val holder = ... // your viewholder creation
    holder.textTV.background = ContextCompat.getDrawable(context, viewType)
}

И полностью удалите код изменения фона из onBindViewHolder.

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