Reputation: 465
I am attempting to make a function : In recyclerView when you click the user image ,navigate to the userActivity, and when you click the "gift" icon ,navigate to otherActivity .
As follow is my Adapter.kt :
package Users.UserReceiveGiftItem
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.gearsrun.www.R
import com.squareup.picasso.Picasso
import kotlinx.android.synthetic.main.user_receive_gift_item.view.*
class UserReceiveGiftAdapter(val userList : List<UserReceiveGiftItem>) : RecyclerView.Adapter<UserReceiveGiftAdapter.UserHolder>(){
private lateinit var mListener :onItemClickListener
interface onItemClickListener{
fun onItemClick(view:View,position: Int)
}
fun setOnItemClickListener(listener: onItemClickListener){
mListener = listener
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): UserHolder {
val layoutInflater = LayoutInflater.from(parent.context)
return UserHolder(layoutInflater.inflate(R.layout.user_receive_gift_item,parent,false),mListener)
}
override fun onBindViewHolder(holder: UserReceiveGiftAdapter.UserHolder, position: Int) {
holder.render(userList[position])
}
override fun getItemCount(): Int = userList.size
class UserHolder(val view : View,listener:onItemClickListener) : RecyclerView.ViewHolder(view){
fun render(userList: UserReceiveGiftItem){
Picasso.get().load(userList.user_img).into(view.user_img)
view.user_name.text = userList.user_name
view.time.text = userList.time
view.userId.text = userList.userId
view.giftImg.setImageResource(userList.giftImg)
}
init {
view.setOnClickListener {
listener.onItemClick(it,absoluteAdapterPosition)
}
}
}
}
And I use in the Activity :
package com.gearsrun.www.UI.Receive
import Users.UserReceiveGiftItem.UserReceiveGiftAdapter
import Users.UserReceiveGiftItem.UserReceiveGiftItem
import android.content.Intent
import android.graphics.drawable.ColorDrawable
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.ImageView
import android.widget.Toast
import androidx.appcompat.app.ActionBar
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.gearsrun.www.R
import com.gearsrun.www.UI.Gift.AwaitingToUnwrapActivity
import com.gearsrun.www.UI.Sunflower.SunflowerAvailableActivity
import com.gearsrun.www.UI.User.UserDetailActivity
import kotlinx.android.synthetic.main.activity_who_receive_gift.*
import kotlinx.android.synthetic.main.user_receive_gift_item.view.*
class ReceiveActivity : AppCompatActivity() {
val userList : List<UserReceiveGiftItem> = listOf(
UserReceiveGiftItem(
"https://i.pinimg.com/564x/63/85/68/63856877880614e0dab080071513156f.jpg",
"Sharry",
"10 mins ago",
"517ddY",
R.drawable.donut
),
)
lateinit var gift_unwrap : ImageView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_receive)
changeColor(R.color.font_green)
initRecycler()
gift_unwrap = findViewById(R.id.gift_unwrap)
gift_unwrap.setOnClickListener {
}
}
private fun changeColor(resourseColor: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.statusBarColor = ContextCompat.getColor(applicationContext, resourseColor)
}
val bar: ActionBar? = supportActionBar
if (bar != null) {
bar.setBackgroundDrawable(ColorDrawable(resources.getColor(resourseColor)))
}
}
fun initRecycler(){
rvUser.layoutManager = LinearLayoutManager(this)
val adapter = UserReceiveGiftAdapter(userList)
rvUser.adapter = adapter
adapter.setOnItemClickListener(object:UserReceiveGiftAdapter.onItemClickListener{
override fun onItemClick(view: View, position: Int) {
view.user_img.setOnClickListener {
val intent = Intent(this@ReceiveActivity,UserDetailActivity::class.java)
startActivity(intent)
}
view.giftImg.setOnClickListener {
val intent =Intent(this@ReceiveActivity,SunflowerAvailableActivity::class.java)
startActivity(intent)
}
}
})
}
}
It is a bit rare that it is able to navigate successfully ,however ,it dosen't react for the first click ..Could you please take a look my code ?Thank you guys in advance !!
Upvotes: 0
Views: 168
Reputation: 2341
What I think after looking your code is, that you are setting adapter to your recyclerview first and then you are injecting a click listener to adapter.
What happens here is that some items from recycler view are loaded and they wouldn't have the click listener at that time,
for example if you scroll down, the newly appeared items on the screen will have proper click listeners, now if you scroll up, the previous one's will also have listener attached.
What to do to get rid of this problem:
Change your initRecycler() method as below:
fun initRecycler(){
rvUser.layoutManager = LinearLayoutManager(this)
val adapter = UserReceiveGiftAdapter(userList)
adapter.setOnItemClickListener(object:UserReceiveGiftAdapter.onItemClickListener{
override fun onItemClick(view: View, position: Int) {
view.user_img.setOnClickListener {
val intent = Intent(this@ReceiveActivity,UserDetailActivity::class.java)
startActivity(intent)
}
view.giftImg.setOnClickListener {
val intent =Intent(this@ReceiveActivity,SunflowerAvailableActivity::class.java)
startActivity(intent)
}
}
})
//set adapter after setting click listener to your adapter.
rvUser.adapter = adapter
}
Upvotes: 1
Reputation: 93551
You are using the click listener of the list item to add more click listeners to its children. So the first time you click it, the children don't have listeners yet and won't do anything. It is also error prone that a parent and its children both have click listeners, because it's undefined what will happen if you change the click listener as you are clicking it.
Instead, you should define your interface in the adapter to handle both types of clicks. In the ViewHolder, set click listeners only on the relevant children to be clicked.
Also, I think you're misusing lateinit
. I would make the property nullable. And it is redundant to have a setter function for a property's value.
If you make the ViewHolder class inner
, then you don't have to pass instances of the listener to the view holder instances, which will cause problems if you ever change the Adapter's listener.
Finally, personally I think the listener should return the list item, not the specific view and position in the list. Those are implementation details that the outer class doesn't need to know about.
class UserReceiveGiftAdapter(val userList : List<UserReceiveGiftItem>) : RecyclerView.Adapter<UserReceiveGiftAdapter.UserHolder>(){
var onItemClickListener: OnItemClickListener? = null
interface OnItemClickListener{
fun onUserClick(item: UserReceiveGiftItem)
fun onGiftClick(item: UserReceiveGiftItem)
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): UserHolder {
val layoutInflater = LayoutInflater.from(parent.context)
return UserHolder(layoutInflater.inflate(R.layout.user_receive_gift_item,parent,false))
}
override fun onBindViewHolder(holder: UserReceiveGiftAdapter.UserHolder, position: Int) {
holder.render(userList[position])
}
override fun getItemCount(): Int = userList.size
inner class UserHolder(val view : View) : RecyclerView.ViewHolder(view){
fun render(userList: UserReceiveGiftItem){
Picasso.get().load(userList.user_img).into(view.user_img)
view.user_name.text = userList.user_name
view.time.text = userList.time
view.userId.text = userList.userId
view.giftImg.setImageResource(userList.giftImg)
}
init {
view.user_img.setOnClickListener {
onItemClickListener?.onUserClick(userList[absoluteAdapterPosition])
}
view.giftImg.setOnClickListener {
onItemClickListener?.onGiftClick(userList[absoluteAdapterPosition])
}
}
}
}
In Activity or Fragment:
adapter.onItemClickListener = object: UserReceiveGiftAdapter.OnItemClickListener {
override fun onUserClick(item: UserReceiveGiftItem) {
val intent = Intent(this@ReceiveActivity, UserDetailActivity::class.java)
startActivity(intent)
}
override fun onGiftClick(item: UserReceiveGiftItem) {
val intent = Intent(this@ReceiveActivity, SunflowerAvailableActivity::class.java)
startActivity(intent)
}
}
Upvotes: 1