如何在不在 ListView 可见部分的适配器 class 中获取视图? - 科特林
How get view inside adapter class that is not in visible part of ListView? - Kotlin
我有 listView
铃声
每次音乐开始或停止时,我都需要将 play_arrow
图像更改为 stop
图像。
当我在一张图片上单击播放时,它变成了 stop
图片,然后我在其他音乐项目图片上单击播放,所以上一张应该变成 play_arrow
而刚刚点击的一张应该变成 stop
。
问题在于按位置获取视图。在前 12 个音乐视图中,一切都很好。如果我尝试使用 previousListened > 12
获得这样的视图 parent.getChildAt(previousListened)
它 returns null.
编辑: 添加适配器 class
class SoundListAdapter constructor(
private var context: Context,
private val layout: Int,
private var arrayList: ArrayList<Sound>,
private val activity: FragmentActivity,
private val mediaPlayer: MediaPlayer
) : BaseAdapter() {
private var selectedPosition = -1
private var currentListened = -1
private var previousListened = -1
private var isPlaying = false
private var TAG = "SoundListAdapter"
private val mSendSoundUri: SendSoundUri = activity as SendSoundUri
interface SendSoundUri {
fun sendSoundUri(input: String?)
}
override fun getCount(): Int {
return arrayList.size
}
override fun getItem(i: Int): Any {
return ""
}
override fun getItemId(i: Int): Long {
return i.toLong()
}
private inner class ViewHolder {
internal var radioButton: RadioButton? = null
internal var txtName: TextView? = null
internal var ivPlay: ImageView? = null
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
var convertView = convertView
val viewHolder: ViewHolder
if (convertView == null) {
viewHolder = ViewHolder()
val layoutInflater = context.getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
convertView = layoutInflater.inflate(layout, null)
viewHolder.txtName = convertView!!.findViewById(R.id.sound_name)
viewHolder.radioButton = convertView.findViewById(R.id.sound_radiobutton)
viewHolder.ivPlay = convertView.findViewById(R.id.ivPlay) as ImageView
convertView.tag = viewHolder
} else {
viewHolder = convertView.tag as ViewHolder
}
//check the radio button if both position and selectedPosition matches
viewHolder.radioButton?.isChecked = (position === selectedPosition)
// TODO add color to checked circle
//Set the position tag to both radio button and label
viewHolder.radioButton?.tag = position
viewHolder.ivPlay?.tag = position
viewHolder.txtName?.tag = position
viewHolder.radioButton?.setOnClickListener { v -> itemCheckChanged(v) }
viewHolder.txtName?.setOnClickListener { v -> itemCheckChanged(v) }
val music = arrayList[position]
viewHolder.txtName!!.text = music.title
// play music
viewHolder.ivPlay!!.setOnClickListener {
previousListened = currentListened
currentListened = it.tag as Int
// TODO add black square when playing
Log.d(TAG, "max items: ${parent.childCount}")
Log.d(TAG, "previousListened: $previousListened")
if (previousListened != -1 && previousListened == currentListened && mediaPlayer.isPlaying) {
mediaPlayer.stop()
} else {
mediaPlayer.reset()
mediaPlayer.setDataSource(context, Uri.parse(music.uri))
mediaPlayer.prepare()
mediaPlayer.start()
}
}
return convertView
}
private fun getSelectedSound(): Sound? {
Log.d(TAG, "sending selectedPosition: $selectedPosition")
if (selectedPosition == -1)
return null
return arrayList[selectedPosition]
}
private fun itemCheckChanged(v: View) {
selectedPosition = v.tag as Int
mSendSoundUri.sendSoundUri(getSelectedSound()?.uri)
Log.d(TAG, "selectedPosition changed to: $selectedPosition")
notifyDataSetChanged()
}
}
是否可以在适配器 class 的可见部分之外获取 ListView
的项目视图?
是否可以获取 Adapter 中可见部分之外的 ListView 的项目视图 class?
不,你不能。 ViewHolder 只存在于可见的项目中。
但是,对于您的情况,您只需要在 getView
函数中设置 ImageView
图像。
if (currentListened == position) {
// set here your Stop image
viewHolder.ivPlay.setImageResource(R.drawable.stop);
} else {
// set here your Play image
viewHolder.ivPlay.setImageResource(R.drawable.play);
}
然后,调用notifyDataSetChanged
viewHolder.ivPlay!!.setOnClickListener {
...
...
notifyDataSetChanged();
}
notifyDataSetChange
将更新所有可见项目。
另一方面,您不需要将 position
保存在 tag
变量中。您始终知道点击了哪个项目,因为您的 onClick
事件是在 getView
函数中设置的。
我有 listView
铃声
每次音乐开始或停止时,我都需要将 play_arrow
图像更改为 stop
图像。
当我在一张图片上单击播放时,它变成了 stop
图片,然后我在其他音乐项目图片上单击播放,所以上一张应该变成 play_arrow
而刚刚点击的一张应该变成 stop
。
问题在于按位置获取视图。在前 12 个音乐视图中,一切都很好。如果我尝试使用 previousListened > 12
获得这样的视图 parent.getChildAt(previousListened)
它 returns null.
编辑: 添加适配器 class
class SoundListAdapter constructor(
private var context: Context,
private val layout: Int,
private var arrayList: ArrayList<Sound>,
private val activity: FragmentActivity,
private val mediaPlayer: MediaPlayer
) : BaseAdapter() {
private var selectedPosition = -1
private var currentListened = -1
private var previousListened = -1
private var isPlaying = false
private var TAG = "SoundListAdapter"
private val mSendSoundUri: SendSoundUri = activity as SendSoundUri
interface SendSoundUri {
fun sendSoundUri(input: String?)
}
override fun getCount(): Int {
return arrayList.size
}
override fun getItem(i: Int): Any {
return ""
}
override fun getItemId(i: Int): Long {
return i.toLong()
}
private inner class ViewHolder {
internal var radioButton: RadioButton? = null
internal var txtName: TextView? = null
internal var ivPlay: ImageView? = null
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
var convertView = convertView
val viewHolder: ViewHolder
if (convertView == null) {
viewHolder = ViewHolder()
val layoutInflater = context.getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
convertView = layoutInflater.inflate(layout, null)
viewHolder.txtName = convertView!!.findViewById(R.id.sound_name)
viewHolder.radioButton = convertView.findViewById(R.id.sound_radiobutton)
viewHolder.ivPlay = convertView.findViewById(R.id.ivPlay) as ImageView
convertView.tag = viewHolder
} else {
viewHolder = convertView.tag as ViewHolder
}
//check the radio button if both position and selectedPosition matches
viewHolder.radioButton?.isChecked = (position === selectedPosition)
// TODO add color to checked circle
//Set the position tag to both radio button and label
viewHolder.radioButton?.tag = position
viewHolder.ivPlay?.tag = position
viewHolder.txtName?.tag = position
viewHolder.radioButton?.setOnClickListener { v -> itemCheckChanged(v) }
viewHolder.txtName?.setOnClickListener { v -> itemCheckChanged(v) }
val music = arrayList[position]
viewHolder.txtName!!.text = music.title
// play music
viewHolder.ivPlay!!.setOnClickListener {
previousListened = currentListened
currentListened = it.tag as Int
// TODO add black square when playing
Log.d(TAG, "max items: ${parent.childCount}")
Log.d(TAG, "previousListened: $previousListened")
if (previousListened != -1 && previousListened == currentListened && mediaPlayer.isPlaying) {
mediaPlayer.stop()
} else {
mediaPlayer.reset()
mediaPlayer.setDataSource(context, Uri.parse(music.uri))
mediaPlayer.prepare()
mediaPlayer.start()
}
}
return convertView
}
private fun getSelectedSound(): Sound? {
Log.d(TAG, "sending selectedPosition: $selectedPosition")
if (selectedPosition == -1)
return null
return arrayList[selectedPosition]
}
private fun itemCheckChanged(v: View) {
selectedPosition = v.tag as Int
mSendSoundUri.sendSoundUri(getSelectedSound()?.uri)
Log.d(TAG, "selectedPosition changed to: $selectedPosition")
notifyDataSetChanged()
}
}
是否可以在适配器 class 的可见部分之外获取 ListView
的项目视图?
是否可以获取 Adapter 中可见部分之外的 ListView 的项目视图 class?
不,你不能。 ViewHolder 只存在于可见的项目中。
但是,对于您的情况,您只需要在 getView
函数中设置 ImageView
图像。
if (currentListened == position) {
// set here your Stop image
viewHolder.ivPlay.setImageResource(R.drawable.stop);
} else {
// set here your Play image
viewHolder.ivPlay.setImageResource(R.drawable.play);
}
然后,调用notifyDataSetChanged
viewHolder.ivPlay!!.setOnClickListener {
...
...
notifyDataSetChanged();
}
notifyDataSetChange
将更新所有可见项目。
另一方面,您不需要将 position
保存在 tag
变量中。您始终知道点击了哪个项目,因为您的 onClick
事件是在 getView
函数中设置的。