I have a RecyclerView and am trying to pass the location from my adapter back to the mainactivity without success so far .
I think the code in the adapter is passing the data back is working, but unfortunately I can’t work out how to set the initialisation in the onCreate in the MainActivity to work? I’m not certain how to call this using “lazy” (ie “private val itemAdapter by lazy” in the mainactivity”)?
I am getting frustrated solving this so any help appreciated.
MainActivity.kt
class MainActivity : AppCompatActivity(), ItemAdapter.OnItemClickListener {
private val itemAdapter by lazy {
ItemAdapter { position: Int, item: Item ->
Toast.makeText(this@MainActivity, "Pos ${position}", Toast.LENGTH_LONG).show()
item_list.smoothScrollToPosition(position)
} }
private val possibleItems = listOf(
Item("Plane 1", R.drawable.ic_airplane),
Item("Car 2", R.drawable.ic_car),
Item("Meals 3", R.drawable.ic_food),
Item("Fuel 4", R.drawable.ic_gas),
Item("Home 5 ", R.drawable.ic_home)
)
fun onImageClick(imageData: String?) {
// handle image data
}
override fun onCreate(savedInstanceState: Bundle?) {
var position: Int
val thisitem: Item
var thisunit: Unit
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// var itemAdapter = ItemAdapter(possibleItems)
// var thisitemAdapter = ItemAdapter((position, thisitem) -> thisunit)
// Toast.makeText(this@MainActivity, "Pos ${position}", Toast.LENGTH_LONG).show()
// item_list.smoothScrollToPosition(position) //CAN'T GET THIS TO COMPILE
item_list.initialize(itemAdapter)
itemAdapter.setOnItemClickListener(this) // Added this
ItemSnapHelper().attachToRecyclerView(item_list)
item_list.setViewsToChangeColor(listOf(R.id.list_item_background, R.id.list_item_text))
item_list.scrollToPosition(Int.MAX_VALUE/2)
itemAdapter.setItems(possibleItems)
}
override
public fun getAdapterPosition(position : Int ){
Toast.makeText(this,"this is toast message" position,Toast.LENGTH_SHORT).show()
}
private fun getLargeListOfItems(): List<Item> {
val items = mutableListOf<Item>()
(0..40).map { items.add(possibleItems.random()) }
return items
}
}
data class Item(
val title: String,
@DrawableRes val icon: Int
)
ItemAdapter.kt
class ItemAdapter(val itemClick: (position:Int,item:Item) -> Unit) : RecyclerView.Adapter<ItemViewHolder>() {
private var items: List<Item> = listOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder =
ItemViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false))
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val pos = position % items.size
holder.bind(items[pos]) // bind the actual item
Log.d("xx position= ", pos.toString())
}
override fun getItemCount(): Int = Int.MAX_VALUE
fun setItems(newItems: List<Item>) {
items = newItems
notifyDataSetChanged()
}
lateinit var listener: OnItemClickListener
public interface OnItemClickListener {
fun getAdapterPosition(position : Int )
}
public fun setOnItemClickListener(listener: OnItemClickListener) {
this.listener= listener
}
}
class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
fun bind(item: Item) {
view.list_item_text.text = "${item.title}"
view.list_item_icon.setImageResource(item.icon)
}
}
CodePudding user response:
you have a listener so you can write like this
class MainActivity : AppCompatActivity(), ItemAdapter.OnItemClickListener {
private lateinit var itemAdapter: ItemAdapter
private val possibleItems = listOf(
Item("Plane 1", R.drawable.ic_airplane),
Item("Car 2", R.drawable.ic_car),
Item("Meals 3", R.drawable.ic_food),
Item("Fuel 4", R.drawable.ic_gas),
Item("Home 5 ", R.drawable.ic_home)
)
fun onImageClick(imageData: String?) {
// handle image data
}
override fun onCreate(savedInstanceState: Bundle?) {
var position: Int
val thisitem: Item
var thisunit: Unit
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
itemAdapter = ItemAdapter()
itemAdapter.listener = this
item_list.initialize(itemAdapter)
ItemSnapHelper().attachToRecyclerView(item_list)
item_list.setViewsToChangeColor(listOf(R.id.list_item_background, R.id.list_item_text))
item_list.scrollToPosition(Int.MAX_VALUE/2)
itemAdapter.setItems(possibleItems)
}
override
public fun getAdapterPosition(position : Int ){
Toast.makeText(this,"this is toast message" position,Toast.LENGTH_SHORT).show()
}
private fun getLargeListOfItems(): List<Item> {
val items = mutableListOf<Item>()
(0..40).map { items.add(possibleItems.random()) }
return items
}
}
ItemAdapter.kt
class ItemAdapter : RecyclerView.Adapter<ItemViewHolder>() {
private var items: List<ClipData.Item> = listOf()
var listener: OnItemClickListener? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder = ItemViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false))
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
holder.bind(items[position], position)
}
override fun getItemCount(): Int = Int.MAX_VALUE
fun setItems(newItems: List<ClipData.Item>) {
items = newItems
notifyDataSetChanged()
}
}
class ItemViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
fun bind(item: ClipData.Item, position: Int) {
view.list_item_text.text = "${item.title}"
view.list_item_icon.setImageResource(item.icon)
view.list_item_text.setOnClickListener {
listener?.getAdapterPosition(position)
}
}
}
interface OnItemClickListener {
fun getAdapterPosition(position: Int)
}
CodePudding user response:
Instead of creating an interface you can also pass a lambda function as a callback to the Adapter.
Basic structure will be like this:
class MainActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
val itemAdapter = ItemAdapter { position ->
// do whatever you wish with this position
}
recyclerView.adapter = itemAdapter
...
}
}
class ItemAdapter(private val onClick: (Int) -> Unit) {
...
inner class ItemViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
fun bind(item: ClipData.Item, position: Int) {
...
view.setOnClickListener {
onClick(position)
}
}
}
}
If you don't want to create ItemViewHolder
as an inner class, you can accept the onClick
lambda in its constructor and pass it there from onCreateViewHolder
.