选择在 android 中的 recyclerview 项目中不起作用
selection not working in reyclerview item in android
嘿,我在 reyclerview selection 工作。第一次加载 reyclerview 时,我想显示默认选择,然后在单击后显示所选项目选择。但它不起作用。默认选择有效,但在点击其他项目后它没有选择该项目。
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val selectionAdapter = SelectionAdapter()
selectionAdapter.submitList(createList())
binding.recyclerView.apply {
layoutManager =
LinearLayoutManager(this@MainActivity, LinearLayoutManager.HORIZONTAL, false)
adapter = selectionAdapter
}
}
private fun createList(): List<Data> {
return listOf(
Data("1"),
Data("2"),
Data("3", true),
Data("4"),
)
}
data class Data(
val value: String? = null,
val defaultValue: Boolean? = null
)
}
SelectionAdapter.kt
class SelectionAdapter :
ListAdapter<MainActivity.Data, SelectionAdapter.SelectionViewHolder>(COMPARATOR) {
var selectedItemPosition: Int = 0
set(value) {
val oldPosition = field
field = value
notifyItemChanged(oldPosition)
notifyItemChanged(value)
}
companion object {
private val COMPARATOR = object : DiffUtil.ItemCallback<MainActivity.Data>() {
override fun areItemsTheSame(
oldItem: MainActivity.Data,
newItem: MainActivity.Data
): Boolean {
return true
}
override fun areContentsTheSame(
oldItem: MainActivity.Data,
newItem: MainActivity.Data
): Boolean {
return true
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SelectionViewHolder {
return SelectionViewHolder(
SelectionItemLayoutBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
override fun onBindViewHolder(holder: SelectionViewHolder, position: Int) {
holder.binding.root.setOnClickListener {
selectedItemPosition = holder.adapterPosition
holder.binding.root.isSelected = selectedItemPosition == position
}
holder.bindItem(getItem(position))
}
inner class SelectionViewHolder(val binding: SelectionItemLayoutBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bindItem(item: MainActivity.Data) {
binding.textView.text = item.value
binding.root.isSelected = item.defaultValue == true
}
}
}
selection_item_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:padding="5dp"
android:background="@drawable/options_item_selector_background"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
mainactivity.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
options_item_default_background.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="1dp"
android:color="#D8DFED" />
<corners android:radius="1dp" />
</shape>
options_item_selector_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/options_item_selected_background" android:state_pressed="false" android:state_selected="true" />
<item android:drawable="@drawable/options_item_default_background" android:state_selected="false" />
</selector>
options_item_selected_background.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="1dp"
android:color="#213F66" />
<corners android:radius="1.5dp" />
</shape>
我正在发布我的视频link
您的适配器从不读取 selectedItemPosition
,那么它怎么能改变显示为选中的项目?
通过在每次绑定项目时使用列表项目中的 defaultValue
,它们将永远无法更改。
为简化这一点,让您的适配器将 selectedItemPosition
视为关于应该选择什么的唯一真实来源。 Activity 应该告诉它从哪个项目开始:
val selectionAdapter = SelectionAdapter()
val list = createList()
selectionAdapter.selectedItemPosition = list.indexOfFirst { it.defaultValue == true }
selectionAdapter.submitList(list)
您的适配器应专门使用 selectedItemPosition
作为其来源,以确定项目是否应显示为已选中。而点击监听器只需要改变选中的项目。让它手动改变项目的外观是没有意义的,因为这只能短暂地改变它的外观,直到下一次绑定视图持有者。
override fun onBindViewHolder(holder: SelectionViewHolder, position: Int) {
holder.binding.root.setOnClickListener {
selectedItemPosition = holder.adapterPosition
}
holder.bindItem(getItem(position), selectedItemPosition == position)
}
inner class SelectionViewHolder(val binding: SelectionItemLayoutBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bindItem(item: MainActivity.Data, isSelected: Boolean) = with(binding) {
textView.text = item.value
root.isSelected = isSelected
}
}
嘿,我在 reyclerview selection 工作。第一次加载 reyclerview 时,我想显示默认选择,然后在单击后显示所选项目选择。但它不起作用。默认选择有效,但在点击其他项目后它没有选择该项目。
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val selectionAdapter = SelectionAdapter()
selectionAdapter.submitList(createList())
binding.recyclerView.apply {
layoutManager =
LinearLayoutManager(this@MainActivity, LinearLayoutManager.HORIZONTAL, false)
adapter = selectionAdapter
}
}
private fun createList(): List<Data> {
return listOf(
Data("1"),
Data("2"),
Data("3", true),
Data("4"),
)
}
data class Data(
val value: String? = null,
val defaultValue: Boolean? = null
)
}
SelectionAdapter.kt
class SelectionAdapter :
ListAdapter<MainActivity.Data, SelectionAdapter.SelectionViewHolder>(COMPARATOR) {
var selectedItemPosition: Int = 0
set(value) {
val oldPosition = field
field = value
notifyItemChanged(oldPosition)
notifyItemChanged(value)
}
companion object {
private val COMPARATOR = object : DiffUtil.ItemCallback<MainActivity.Data>() {
override fun areItemsTheSame(
oldItem: MainActivity.Data,
newItem: MainActivity.Data
): Boolean {
return true
}
override fun areContentsTheSame(
oldItem: MainActivity.Data,
newItem: MainActivity.Data
): Boolean {
return true
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SelectionViewHolder {
return SelectionViewHolder(
SelectionItemLayoutBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
override fun onBindViewHolder(holder: SelectionViewHolder, position: Int) {
holder.binding.root.setOnClickListener {
selectedItemPosition = holder.adapterPosition
holder.binding.root.isSelected = selectedItemPosition == position
}
holder.bindItem(getItem(position))
}
inner class SelectionViewHolder(val binding: SelectionItemLayoutBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bindItem(item: MainActivity.Data) {
binding.textView.text = item.value
binding.root.isSelected = item.defaultValue == true
}
}
}
selection_item_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:padding="5dp"
android:background="@drawable/options_item_selector_background"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
mainactivity.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
options_item_default_background.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="1dp"
android:color="#D8DFED" />
<corners android:radius="1dp" />
</shape>
options_item_selector_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/options_item_selected_background" android:state_pressed="false" android:state_selected="true" />
<item android:drawable="@drawable/options_item_default_background" android:state_selected="false" />
</selector>
options_item_selected_background.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="1dp"
android:color="#213F66" />
<corners android:radius="1.5dp" />
</shape>
我正在发布我的视频link
您的适配器从不读取 selectedItemPosition
,那么它怎么能改变显示为选中的项目?
通过在每次绑定项目时使用列表项目中的 defaultValue
,它们将永远无法更改。
为简化这一点,让您的适配器将 selectedItemPosition
视为关于应该选择什么的唯一真实来源。 Activity 应该告诉它从哪个项目开始:
val selectionAdapter = SelectionAdapter()
val list = createList()
selectionAdapter.selectedItemPosition = list.indexOfFirst { it.defaultValue == true }
selectionAdapter.submitList(list)
您的适配器应专门使用 selectedItemPosition
作为其来源,以确定项目是否应显示为已选中。而点击监听器只需要改变选中的项目。让它手动改变项目的外观是没有意义的,因为这只能短暂地改变它的外观,直到下一次绑定视图持有者。
override fun onBindViewHolder(holder: SelectionViewHolder, position: Int) {
holder.binding.root.setOnClickListener {
selectedItemPosition = holder.adapterPosition
}
holder.bindItem(getItem(position), selectedItemPosition == position)
}
inner class SelectionViewHolder(val binding: SelectionItemLayoutBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bindItem(item: MainActivity.Data, isSelected: Boolean) = with(binding) {
textView.text = item.value
root.isSelected = isSelected
}
}