android - RecyclerView Multiple ViewHolders ItemDetailsLookup
问题描述
我的 recyclerview (用于聊天视图)正确加载视图,但是当我点击视图时,它会引发强制转换异常:
ViewHolderReceived cannot be cast to ViewHolderSent
视图持有者:
class ViewHolderReceived(val view: View) : RecyclerView.ViewHolder(view) {
fun getItemDetails(): ItemDetailsLookup.ItemDetails<Long> =
object : ItemDetailsLookup.ItemDetails<Long>() {
override fun getPosition(): Int = adapterPosition
override fun getSelectionKey(): Long? = itemId
override fun inSelectionHotspot(e: MotionEvent): Boolean {
return true
}
}
fun bind(isSelected: Boolean = false) {
itemView.isSelected = isSelected
}
}
//#########################################################################
class ViewHolderSent(val view: View) : RecyclerView.ViewHolder(view) {
fun getItemDetails(): ItemDetailsLookup.ItemDetails<Long> =
object : ItemDetailsLookup.ItemDetails<Long>() {
override fun getPosition(): Int = adapterPosition
override fun getSelectionKey(): Long? = itemId
override fun inSelectionHotspot(e: MotionEvent): Boolean {
return true
}
}
fun bind(isSelected: Boolean = false) {
itemView.isSelected = isSelected
}
}
ItemDetails查找:
class MyItemDetailsLookup(private val recyclerView: RecyclerView) :
ItemDetailsLookup<Long>() {
override fun getItemDetails(event: MotionEvent): ItemDetails<Long>? {
val view = recyclerView.findChildViewUnder(event.x, event.y)
if (view != null) {
return if(recyclerView.getChildAdapterPosition(view) == 0){
(recyclerView.getChildViewHolder(view) as MyAdapter.ViewHolderReceived)
.getItemDetails()} else {
(recyclerView.getChildViewHolder(view) as MyAdapter.ViewHolderSent)
.getItemDetails()} // error here
}
return null
}
}
无论点击哪个视图,它都会引发相同的错误(对于 ViewHolderReceived 或 ViewHolderSent),但会以正确的顺序正确绑定它们。
注意:如果我在点击任何已发送的视图后点击收到的视图,它只会引发错误,反之亦然
找到解决方案:问题出在 recyclerView.getChildAdapterPosition(我傻了,半睡半醒)。
解决方案
如果您将共享方法提取到超类或接口,这可以很容易地解决,那么无论如何您都可以执行安全转换。例如:
abstract class SelectableViewHolder(val view: View) : RecyclerView.ViewHolder(view){
fun getItemDetails(): ItemDetailsLookup.ItemDetails<Long> =
object : ItemDetailsLookup.ItemDetails<Long>() {
override fun getPosition(): Int = adapterPosition
override fun getSelectionKey(): Long? = itemId
override fun inSelectionHotspot(e: MotionEvent): Boolean {
return true
}
}
open fun bind(isSelected: Boolean = false) {
itemView.isSelected = isSelected
}
}
class ViewHolderReceived(view: View) : SelectableViewHolder(view) {
override fun bind(isSelected: Boolean = false) {
super.bind(isSelected)
// anything else specific for received viewholder
}
}
class ViewHolderSent(view: View) : SelectableViewHolder(view) {
override fun bind(isSelected: Boolean = false) {
super.bind(isSelected)
// anything else specific for sent viewholder
}
}
然后查找很容易:
class MyItemDetailsLookup(private val recyclerView: RecyclerView) : ItemDetailsLookup<Long>() {
override fun getItemDetails(event: MotionEvent): ItemDetails<Long>? {
return recyclerView.findChildViewUnder(event.x, event.y)?.let {
(recyclerView.getChildViewHolder(it) as SelectableViewHolder).getItemDetails()
}
}
}
推荐阅读
- javascript - 如何编写一个函数来遍历打字稿中的列表?
- python - 有效地将具有嵌入式数组的字典列表转换为 DataFrame
- julia - 在 Julia 中将类型 Array{Union{Missing, Float64},1} 转换为 Array{Float64,1}
- python - TensorFlow 2.0 将不包含 TensorFlow Contrib 模块
- mysql - 如何使用 laravel 在博客文章的刀片模板中显示博客文章的多个标签?
- reactjs - ReactJS - 道具未传递给组件
- reactjs - 无法将 SVG 导入 Next.js
- solace - 来自 VB 6.0 的安慰连接
- javascript - 使用自定义超链接包裹 Instagram 嵌入
- intern - 如何指定实习生为 http://localhost:9000 服务的根目录?