使用绑定中断 RecyclerView 项目布局
Use of binding breaks RecyclerView item layout
我正在使用 Kotlin 构建一个 Android 应用程序,并决定替换对 findViewById 的调用并使用绑定。一切正常,但具体来说,当我为 RecyclerView 更改适配器时,它会破坏项目布局。
带有 findViewById 的原始代码:
class WeightListAdapter(val weights: List<WeightWithPictures>, val onWeightItemClickListener: OnWeightItemClickListener) : RecyclerView.Adapter<WeightListAdapter.WeightHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeightListAdapter.WeightHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item_weight, parent, false)
return WeightHolder(view)
}
override fun onBindViewHolder(holder: WeightListAdapter.WeightHolder, position: Int) {
val weightWithPictures = weights[position]
holder.bind(weightWithPictures)
}
override fun getItemCount() = weights.size
inner class WeightHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
private lateinit var weight: Weight
private val weightValueView: TextView = this.itemView.findViewById(R.id.weightValue)
private val weightDateView: TextView = this.itemView.findViewById(R.id.weightDate)
private val weightImageView: ImageView = this.itemView.findViewById(R.id.weightImage) as ImageView
这是布局:
但是每当我使用绑定时:
class WeightListAdapter(val weights: List<WeightWithPictures>, val onWeightItemClickListener: OnWeightItemClickListener) : RecyclerView.Adapter<WeightListAdapter.WeightHolder>() {
private var _binding: ListItemWeightBinding? = null
private val binding get() = _binding!!
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeightListAdapter.WeightHolder {
_binding = ListItemWeightBinding.inflate(LayoutInflater.from(parent.context))
val view = binding.root
return WeightHolder(view)
}
override fun onBindViewHolder(holder: WeightListAdapter.WeightHolder, position: Int) {
val weightWithPictures = weights[position]
holder.bind(weightWithPictures)
}
override fun getItemCount() = weights.size
inner class WeightHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
private lateinit var weight: Weight
private val weightValueView: TextView = binding.weightValue
private val weightDateView: TextView = binding.weightDate
private val weightImageView: ImageView = binding.weightImage
布局中断:
关于我在这里做错了什么有什么想法吗?这是一个错误吗?
P.S - 现在,我只是添加注释以忽略项目视图的 documented here 绑定,但我真的很想了解问题所在。
您的绑定需要在其父级的上下文中膨胀,以便其根视图的布局参数生效:
binding = ListItemWeightBinding.inflate(LayoutInflater.from(parent.context), parent, false)
我认为如果您尝试长期使用它,您正在为适配器创建 binding
属性 也会给您带来问题。每个 ViewHolder 都持有一个具有不同绑定实例的不同视图。它现在可以工作,因为您在设置每个实例后立即将它用于 ViewHolder 实例化。但是,如果这就是您的全部意图,您应该只将绑定传递给 ViewHolder 的构造函数并省略适配器的 属性.
顺便说一下,这是我用于 ViewHolder 的那种模式。更少的代码。请注意,它不一定是 inner
class.
class WeightHolder(binding: ListItemWeightBinding) : RecyclerView.ViewHolder(binding.root), View.OnClickListener {
fun bind(item: WeightWithPictures) {
with (binding) {
// set data for views here
}
}
}
我同意@Tenfour04 的观点,使用相同的绑定实例是错误的,但我相信您的问题的根本原因在于绑定逻辑。通过绑定,数据将绑定到视图,但不会立即。因此,您的视图会膨胀,但由于绑定发生在稍后阶段,计划在不久的将来发生,因此 item_view
宽度缩小了。
所以请尝试以下操作,
// oncreate view logic
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeightListAdapter.WeightHolder {
val binding = ListItemWeightBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return WeightHolder(binding)
}
// onBindViewHolder logic remains the same
// this remains same as suggested by @Tenfour04 but a change in the bind function
class WeightHolder(binding: ListItemWeightBinding) : RecyclerView.ViewHolder(binding.root), View.OnClickListener {
fun bind(item: WeightWithPictures) {
with (binding) {
// set data for views using databindig
customVariable = item
executePendingBindings() // this is important
}
}
}
// define the customvariable in your `item_list_view.xml`
<variable
name="customVariable"
type="packagename.WeightWithPictures" />
executePendingBindings()
是我们强制绑定立即发生而不是稍后安排的方式
编辑:
此答案来自 Databinding
而非 ViewBinding
我正在使用 Kotlin 构建一个 Android 应用程序,并决定替换对 findViewById 的调用并使用绑定。一切正常,但具体来说,当我为 RecyclerView 更改适配器时,它会破坏项目布局。
带有 findViewById 的原始代码:
class WeightListAdapter(val weights: List<WeightWithPictures>, val onWeightItemClickListener: OnWeightItemClickListener) : RecyclerView.Adapter<WeightListAdapter.WeightHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeightListAdapter.WeightHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item_weight, parent, false)
return WeightHolder(view)
}
override fun onBindViewHolder(holder: WeightListAdapter.WeightHolder, position: Int) {
val weightWithPictures = weights[position]
holder.bind(weightWithPictures)
}
override fun getItemCount() = weights.size
inner class WeightHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
private lateinit var weight: Weight
private val weightValueView: TextView = this.itemView.findViewById(R.id.weightValue)
private val weightDateView: TextView = this.itemView.findViewById(R.id.weightDate)
private val weightImageView: ImageView = this.itemView.findViewById(R.id.weightImage) as ImageView
这是布局:
但是每当我使用绑定时:
class WeightListAdapter(val weights: List<WeightWithPictures>, val onWeightItemClickListener: OnWeightItemClickListener) : RecyclerView.Adapter<WeightListAdapter.WeightHolder>() {
private var _binding: ListItemWeightBinding? = null
private val binding get() = _binding!!
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeightListAdapter.WeightHolder {
_binding = ListItemWeightBinding.inflate(LayoutInflater.from(parent.context))
val view = binding.root
return WeightHolder(view)
}
override fun onBindViewHolder(holder: WeightListAdapter.WeightHolder, position: Int) {
val weightWithPictures = weights[position]
holder.bind(weightWithPictures)
}
override fun getItemCount() = weights.size
inner class WeightHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
private lateinit var weight: Weight
private val weightValueView: TextView = binding.weightValue
private val weightDateView: TextView = binding.weightDate
private val weightImageView: ImageView = binding.weightImage
布局中断:
关于我在这里做错了什么有什么想法吗?这是一个错误吗?
P.S - 现在,我只是添加注释以忽略项目视图的 documented here 绑定,但我真的很想了解问题所在。
您的绑定需要在其父级的上下文中膨胀,以便其根视图的布局参数生效:
binding = ListItemWeightBinding.inflate(LayoutInflater.from(parent.context), parent, false)
我认为如果您尝试长期使用它,您正在为适配器创建 binding
属性 也会给您带来问题。每个 ViewHolder 都持有一个具有不同绑定实例的不同视图。它现在可以工作,因为您在设置每个实例后立即将它用于 ViewHolder 实例化。但是,如果这就是您的全部意图,您应该只将绑定传递给 ViewHolder 的构造函数并省略适配器的 属性.
顺便说一下,这是我用于 ViewHolder 的那种模式。更少的代码。请注意,它不一定是 inner
class.
class WeightHolder(binding: ListItemWeightBinding) : RecyclerView.ViewHolder(binding.root), View.OnClickListener {
fun bind(item: WeightWithPictures) {
with (binding) {
// set data for views here
}
}
}
我同意@Tenfour04 的观点,使用相同的绑定实例是错误的,但我相信您的问题的根本原因在于绑定逻辑。通过绑定,数据将绑定到视图,但不会立即。因此,您的视图会膨胀,但由于绑定发生在稍后阶段,计划在不久的将来发生,因此 item_view
宽度缩小了。
所以请尝试以下操作,
// oncreate view logic
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeightListAdapter.WeightHolder {
val binding = ListItemWeightBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return WeightHolder(binding)
}
// onBindViewHolder logic remains the same
// this remains same as suggested by @Tenfour04 but a change in the bind function
class WeightHolder(binding: ListItemWeightBinding) : RecyclerView.ViewHolder(binding.root), View.OnClickListener {
fun bind(item: WeightWithPictures) {
with (binding) {
// set data for views using databindig
customVariable = item
executePendingBindings() // this is important
}
}
}
// define the customvariable in your `item_list_view.xml`
<variable
name="customVariable"
type="packagename.WeightWithPictures" />
executePendingBindings()
是我们强制绑定立即发生而不是稍后安排的方式
编辑:
此答案来自 Databinding
而非 ViewBinding