Recyclerview项目的不同角落半径

时间:2018-05-25 16:27:10

标签: android kotlin recycler-adapter rounded-corners

我正在使用Kotlin在Android中创建聊天应用。

我正在使用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()效率都很低。所以我从这个函数中取出了drawable:

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>

为什么呢?问题在哪里?

enter image description here enter image description here

2 个答案:

答案 0 :(得分:0)

问题在于可绘制是根据您第一次设置的文本进行调整的,您不应该为每个项目设置相同的绘图,因为文本大小不固定

获取每个资源的背景并不是低效的。我相信你的第一种方法不会滞后。要检查低效率,请检查执行代码所需的时间,同时通过滚动至少100个项目来检查内存,并查看其行为方式。如果您遇到任何问题,请告诉我。

答案 1 :(得分:0)

为什么不使用多个itemView类型?这样,每个ViewHolder将加载一次drawable,滚动时它将被适当地重用。为简单起见,您可以将可绘制资源ID用作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删除后台更改代码。