Home > Blockchain >  Returning the location from the adapter back to the mainactivity in Kotlin?
Returning the location from the adapter back to the mainactivity in Kotlin?

Time:11-13

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.

  • Related