'How to make item selectable in recycler view and use it?
I have followed android developer documents to create the recycler view. But now I would like to make the item selectable.
Currently have created itemAdapter.kt
class ItemAdapter(
private val context: Context,
private val dataset: List<Mode>,
private val itemClickListener: MainActivity
) : RecyclerView.Adapter<ItemAdapter.ItemViewHolder>() {
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder.
class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
val textView: TextView = view.findViewById(R.id.item_title)
}
/**
* Create new views (invoked by the layout manager)
*/
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
// create a new view
val adapterLayout = LayoutInflater.from(parent.context)
.inflate(R.layout.list_item, parent, false)
return ItemViewHolder(adapterLayout)
}
/**
* Replace the contents of a view (invoked by the layout manager)
*/
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val item = dataset[position]
holder.textView.text = context.resources.getString(item.stringResourceId)
holder.itemView.setOnClickListener {
itemClickListener.onItemClick(item) //here we are sending the mode object using interface
}
}
/**
* Return the size of your dataset (invoked by the layout manager)
*/
override fun getItemCount() = dataset.size
interface ItemClickListener {
fun onItemClick(mode: Mode)
}
}
Then there is data file called Modes.kt
class Modes {
fun loadModes(): List<Mode> {
return listOf(
Mode(R.string.height),
Mode(R.string.hleveldistance),
)
}
}
Then there is model file called Model.kt
data class Mode(val stringResourceId: Int)
How do I get the selected item for my function in the mainactivity.
class MainActivity : AppCompatActivity() {
//private var etCommand: EditText? = null
private var tvPalaute: TextView? = null
private val modes = Modes().loadModes()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Initialize modes
val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
recyclerView.adapter = ItemAdapter(this, modes, this)
// Use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
recyclerView.setHasFixedSize(true)
//val etCommand: EditText = findViewById(R.id.et_command)
val etSubmit: Button = findViewById(R.id.btn_submit)
val etMeasure: Button = findViewById(R.id.btn_measure)
tvPalaute = findViewById(R.id.tvPalaute)
etSubmit.setOnClickListener {
Toast.makeText(this, "Haetaan laite", Toast.LENGTH_SHORT).show()
openActivityForResult()
}
etMeasure.setOnClickListener {
Toast.makeText(this, "Aloitetaan mittaus", Toast.LENGTH_SHORT).show()
openMeasureActivityForResult()
}
}
fun onItemClick(mode: Mode) {
//openMeasureActivityForResult(mode) // update method to receive mode as an argument
Log.d(mode.code, "mode code")
Toast.makeText(this, "Mode is $mode", Toast.LENGTH_SHORT).show()
}
private fun openMeasureActivityForResult(mode: Mode) {
val measureAction = "com.app.app.m"
val intent = Intent()
intent.action = measureAction
//val selectedMode = mode?.Id
//var mode = modes[selectedMode!!]
intent.putExtra("Mode", mode?.code)
Log.d(intent.toString(), "intent")
intent.putExtra("AppName", "Example App")
//if (!String.toString().isNullOrEmpty(Device))
//{
// intent.putExtra("Device", Device);
//}
measureLauncher.launch(intent)
}
This is my current state of the code. What should the openmeasureactivity function get as it parameter? And is the code looking allright since itemadapter is not in use now. And does the selected item look correct?
Solution 1:[1]
You can user interface
to pass objects
to the activity
.
Create an interface
ItemClickListener
with a method named onItemClick
with a parameter
of type, whatever you want to receive in your activity
. For here use Mode
interface ItemClickListener {
fun onItemClick(mode: Mode)
}
In your activity
or fragment
implement this interface
, and override the onItemClick
method to perform any operations on the selected Mode
object.
class MainActivity : ItemClickListener {
override fun onItemClick(mode: Mode) {
openMeasureActivityForResult(mode) // update method to receive mode as an argument
}
private fun openMeasureActivityForResult(mode: Mode) { //use mode here
val measureAction = "com.app.app.m"
val intent = Intent()
intent.action = measureAction
//var mode = modes[SelectedMode] <-- here the selected value
//intent.putExtra("Mode", mode.Code); <-- also here
intent.putExtra("AppName", "Example App")
//if (!String.toString().isNullOrEmpty(Device))
//{
// intent.putExtra("Device", Device);
//}
measureLauncher.launch(intent)
}
}
Change ItemAdapter
to accept ItemClickListener
in its constructor
class ItemAdapter(
private val context: Context,
private val dataset: List<Mode>,
private val itemClickListener: ItemClickListener
) : RecyclerView.Adapter<ItemAdapter.ItemViewHolder>() {
}
Inside onBindViewHolder()
set a click listener to the holder
s itemView
and pass mode
object using the itemClickListener
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val item = dataset[position]
holder.textView.text = context.resources.getString(item.stringResourceId)
holder.itemView.setOnClickListener {
itemClickListener.onItemClick(item) //here we are sending the mode object using interface
}
}
In activity
or fragment
, when you create adapter
just pass the instance of ItemClickListener
's interface, we can pass it using this
as we've already implemented it above.
val adapter = ItemAdapter(
context,
modeList,
this
)
Solution 2:[2]
I had the same problem, I made an interface for the on click, then in your fragment you override this fun with whatever you want to do.
// Here I add --> val itemClickListener: ItemClickListener
class MovieAdapter(
private val movies: List<Mode>,
val itemClickListener: ItemClickListener) : RecyclerView.Adapter<MovieAdapter.ViewHolder>() {
private lateinit var context: Context
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val binding = ItemMovieBinding.bind(itemView)
fun bind(mode: Mode) {
// Here we set the setOnClickListener
itemView.setOnClickListener {itemClickListener.onClick(mode)}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
context = parent.context
// R.layout.item_mode --> change to yor layout
return ViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.item_mode, parent, false)
)
}
/**
* Returns the size of the list
*/
override fun getItemCount(): Int = movies.size
/**
* Called by RecyclerView to display the data at the specified position.
*/
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(movies[position])
}
}
// The interface we can use in the fragment
interface ItemClickListener{
fun onClick(mode: Mode)
}
then you can use the interface in your fragment:
override fun onClick(mode: Mode) {
// here you can use the object
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Praveen |
Solution 2 |