简体   繁体   中英

How get view inside adapter class that is not in visible part of ListView? - Kotlin

I have listView with ringtones

列表显示

I need change play_arrow image to stop image every time when music started or stoped. When I click play on one image it become stop image and then I click play on other music item image so previous should become play_arrow and just clicked one should become stop . The problem is on getting views by position. Everything works great on first 12 music views. And if I try to get view like this parent.getChildAt(previousListened) with previousListened > 12 it returns null.

EDIT: add adapter 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()
    }
}

Is it possible to get item view of ListView that is outside of visible part in Adapter class?

Is it possible to get item view of ListView that is outside of visible part in Adapter class?

No, you can't. ViewHolder exists only for visible items.

However, in your case, you only need to set your ImageView image inside your getView function.

    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);
    }

Then, call notifyDataSetChanged

    viewHolder.ivPlay!!.setOnClickListener {
        ...
        ...
        notifyDataSetChanged();
    }

notifyDataSetChange will update all visible items.

On the other hand, you don't need to save position in tag variable. You always know which item is clicked because your onClick events are set in getView function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM