简体   繁体   中英

(Kotlin) Position of RecyclerView returns -1 when trying to click on an item

I'm new to Android development (and Kotlin). I'm trying to implement a RecyclerView (which works fine) and when I click on a specific row it opens a new activity (Intent). However, whenever I've press/click on one of the rows, I'm only able to get the value "-1" returned.

I've tried a number of different approaches (you should see the number of tabs in my browser). This seems like it should be a fairly straightforward occurrence for something as common as a RecyclerView, but for whatever reason I'm unable to get it working.

Here is my RecyclerView Adapter file:

class PNHLePlayerAdapter (val players : ArrayList<PNHLePlayer>, val context: Context) : RecyclerView.Adapter<ViewHolder>() {

var onItemClick: ((Int)->Unit) = {}

// Gets the number of items in the list
override fun getItemCount(): Int {
    return players.size
}

// Inflates the item views
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {

    val itemView = LayoutInflater.from(context).inflate(
        R.layout.pnhle_list_item,
        parent,
        false
    )

    val viewHolder = ViewHolder(itemView)

    itemView.setOnClickListener {
        onItemClick(viewHolder.adapterPosition)
    }

    return ViewHolder(itemView)
}

// Binds each item in the ArrayList to a view
override fun onBindViewHolder(holder: ViewHolder, position: Int) {

    holder.tvPlayerName?.text = players[position].Name
    holder.tvPlayerRank?.text = position.toString()
    holder.tvPNHLe?.text = players[position].PNHLe.toString()
    holder.tvTeam?.text = players[position].Team
    holder.ivLeague?.setImageResource(leagueImageID)

}


}

class ViewHolder (view: View) : RecyclerView.ViewHolder(view)  {

val linLayout = view.hor1LinearLayout
val ivTeam = view.teamImageView
val tvPlayerName = view.playerNameTextView
val tvPlayerRank = view.rankNumTextView
val tvPNHLe = view.pnhleTextView
val tvTeam = view.teamTextView
val ivLeague = view.leagueImageView
}

As you can see, there is a class property "onItemClick" which uses a lambda as the click callback. I setOnClickListener in the onCreateViewHolder method after the view is inflated.

Next, in my Activity I add the list to my Adapter and set the call back. However, every time I 'Toast' the position it is displayed as '-1'.

val adapter = PNHLePlayerAdapter(list, this)
    adapter.onItemClick = { position ->
        Toast.makeText(this, position.toString(),Toast.LENGTH_SHORT).show()
        var intent = Intent(this, PlayerCardActivity::class.java)
        //startActivity(intent)   
    }
    rv_player_list.adapter = adapter

Perhaps I'm not thinking about this properly, but shouldn't the position represent the row number of the item out of the RecyclerView??? Ideally, I need to use the position so that I can obtain the correct item from the 'list' (ArrayList) so that I can pass information to my next Activity using the Intent

I found the issue.

Change this line in onCreateViewHolder :

return ViewHolder(itemView)

to this one:

return viewHolder

I would reorganize the adapter like this:

class PNHLePlayerAdapter : androidx.recyclerview.widget.RecyclerView.Adapter<Adapter.ViewHolder>() {

interface AdapterListener {
    fun onItemSelected(position: Int?)
}

var players: List<Player> = listOf()
    set(value) {
        field = value
        this.notifyDataSetChanged()
    }
var listener: AdapterListener? = null

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val view = LayoutInflater.from(parent.context)
        .inflate(R.layout.item_car_selector, parent, false)
    return ViewHolder(view)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.bind(position)
}

override fun getItemCount(): Int {
    return brands.size
}

inner class ViewHolder(view: View): androidx.recyclerview.widget.RecyclerView.ViewHolder(view) {
    private var position: Int? = null
    private val baseView: LinearLayout? = view.findViewById(R.id.baseView) as LinearLayout?
    ...

    init {
        baseView?.setOnClickListener {
            listener?.onManufacturerSelected(position)
        }
    }

    fun bind(position: Int) {
        this.position = position

        ...
    }
  }
}

And from your activity/fragment set the listener as adapter.listener = this , and implement the onItemSelected(position: Int?)

override fun onItemSelected(position: Int?) {
    ...
}

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