recyclerview 项目的不同角半径
Different corner radius of recyclerview items
我正在 Android 使用 Kotlin 创建一个聊天应用程序。
我正在使用 recyclerview
并且项目具有八分之一的背景,具体取决于它们是您的还是其他人的以及它们是否在时间组中 first/last/middle/alone。
在 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>
为什么?问题出在哪里?
问题是 drawable 是根据你第一次设置的文本调整的,你不应该为每个项目设置相同的 drawable,因为你的文本大小不固定
获取每个资源的背景并不低效。我相信你的第一种方法不会滞后。要检查效率低下,请检查一段代码执行所需的时间,还可以通过滚动至少 100 个项目来检查内存并查看它的行为方式。如果您遇到任何问题,请告诉我。
为什么不使用多个 itemView 类型?这样,每个 ViewHolder 将加载一次可绘制对象,并且在滚动时将适当地重复使用它。为简单起见,您可以将可绘制资源 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
中完全删除您的背景更改代码。
我正在 Android 使用 Kotlin 创建一个聊天应用程序。
我正在使用 recyclerview
并且项目具有八分之一的背景,具体取决于它们是您的还是其他人的以及它们是否在时间组中 first/last/middle/alone。
在 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>
为什么?问题出在哪里?
问题是 drawable 是根据你第一次设置的文本调整的,你不应该为每个项目设置相同的 drawable,因为你的文本大小不固定
获取每个资源的背景并不低效。我相信你的第一种方法不会滞后。要检查效率低下,请检查一段代码执行所需的时间,还可以通过滚动至少 100 个项目来检查内存并查看它的行为方式。如果您遇到任何问题,请告诉我。
为什么不使用多个 itemView 类型?这样,每个 ViewHolder 将加载一次可绘制对象,并且在滚动时将适当地重复使用它。为简单起见,您可以将可绘制资源 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
中完全删除您的背景更改代码。