I am using a RecyclerView and I want to add a click listener to it. How can I achieve this? Here's my Adapter class for reference.
class ItemAdapter(var context:Context, var list:ArrayList<Items>): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
var v:View=LayoutInflater.from(context).inflate(R.layout.item_row,parent,false)
return ItemHolder(v)
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as ItemHolder).bind(list[position].name,list[position].price,list[position].picture,list[position].id)
}
class ItemHolder(itemView: View): RecyclerView.ViewHolder(itemView){
fun bind(n:String,p:Double,u:String,item_id:Int)
{
itemView.item_name.text=n
itemView.item_price.text=p.toString()+" "+"USD"
var web:String=("http://192.168.0.101/web%20Sales/images/"+u)
web=web.replace(" ","%20")
//Picasso.with(itemView.context).load(web).into(itemView.item_photo)
Glide.with(itemView.context).load(web).into(itemView.item_photo).toString()
itemView.item_add_photo.setOnClickListener{
UserInfo.itemId=item_id
var obj= QtyFragment()
var manager=(itemView.context as Activity).fragmentManager
obj.show(manager, "Qty")
}
itemView.det_btn.onItem
}
}
}
If you want to set Click Listener to an item in RecyclerView, you can do that from your ItemHolder class -
class ItemHolder(itemView: View): RecyclerView.ViewHolder(itemView){
var currentItem: Items? = null
var currentPosition: Int = 0
init{
itemView.item_add_photo.setOnClickListener {
currentItem?.let {
val message: String = "My item is: " + currentItem!!.name
val intent = Intent(context, YourActivity::class.java)
context.startActivity(intent)
}
}
}
fun bind(n:String,p:Double,u:String,item_id:Int)......
}
In the Adapter:
class ItemHolder(itemView: View): RecyclerView.ViewHolder(itemView){
...
init {
itemView.setOnClickListener{
onItemClick?.invoke(list[adapterPosition])
}
}
...
In the Activity or Fragment where you setup the Adapter:
adapter.onItemClick = { item ->
//do something
))
Try this way.on clicking on itemView...
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//enter code here
}
});
Related
I am new to Android & Kotlin. I want to click my row and intent it to other activity. That's why I tried to create an interface in my Adapter but it does not work. How can I create it?
My adapter code:
class NoteAdapter(private val titleTextArray: ArrayList<String>, private val imageArray: ArrayList<String>) : RecyclerView.Adapter<NoteAdapter.NoteHolder>() {
class NoteHolder (view: View) : RecyclerView.ViewHolder(view) {
var recyclerTitleText: TextView ?= null
var recyclerImageView: ImageView ?= null
init {
recyclerTitleText = view.findViewById(R.id.recyclerTitleText)
recyclerImageView = view.findViewById(R.id.recyclerImage)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NoteHolder {
val inflater = LayoutInflater.from(parent.context)
val view = inflater.inflate(R.layout.recycler_row, parent, false)
return NoteHolder(view)
}
override fun onBindViewHolder(holder: NoteHolder, position: Int) {
holder.recyclerTitleText?.text = titleTextArray[position]
Picasso.get().load(imageArray[position]).into(holder.recyclerImageView)
}
override fun getItemCount(): Int {
return titleTextArray.size
}
}
With Kotlin, you could to use a lambda (higher order function) to fetch the user clicks in the holder. For example, a base approach could be the next:
class YourAdapter(
private val listener: (String) -> Unit
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val yourDataList = emptyList<String>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.compound_checkbox_terms_layout, parent, false)
return YourViewHolder(view)
}
override fun getItemCount(): Int {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
private inner class YourViewHolder(view: View) : RecyclerView.ViewHolder(view) {
init {
if (adapterPosition != RecyclerView.NO_POSITION) {
val selectedData = yourDataList[adapterPosition]
listener.invoke(selectedData)
}
}
}
}
Pass the activity context to the adapter from Activity so it can launch intent
Activity Code :
mAdapter = new CustomAdapter(this, imageArray, ArrayList);
Adapter Code :
class NoteAdapter(private val titleTextArray: ArrayList, private val imageArray: ArrayList, private val context : Context) : RecyclerView.Adapter<NoteAdapter.NoteHolder>() {
class NoteHolder (view: View) : RecyclerView.ViewHolder(view) {
var recyclerTitleText: TextView?= null
var recyclerImageView : ImageView?= null
init {
recyclerTitleText = view.findViewById(R.id.recyclerTitleText)
recyclerImageView = view.findViewById(R.id.recyclerImage)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NoteHolder {
val inflater = LayoutInflater.from(parent.context)
val view = inflater.inflate(R.layout.recycler_row, parent, false)
return NoteHolder(view)
}
override fun onBindViewHolder(holder: NoteHolder, position: Int) {
holder.recyclerTitleText?.text = titleTextArray[position]
Picasso.get().load(imageArray[position]).into(holder.recyclerImageView)
holder.recyclerImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, NesneTani.class);
context.startActivity(intent);
}
});
}
override fun getItemCount(): Int {
return titleTextArray.size
}
}
Create an Interface to catch the click event. (position is optional)
interface OnItemClickListener {
fun onItemClick(position: Int)
}
add OnItemClickListener as a parameter in your Adapter class
class NoteAdapter(
private val titleTextArray: ArrayList<String>,
private val imageArray: ArrayList<String>,
private val listener: OnItemClickListener
) : RecyclerView.Adapter<NoteAdapter.NoteHolder>()
Then do below inside onBindViewHolder
override fun onBindViewHolder(holder: NoteHolder, position: Int) {
listener.onItemClick(position)
}
now inside your activity, implement the OnItemClickListener
class ActivityName implements OnItemClickListener{}
and while initiating adapter, do this
mAdapter = new CustomAdapter(this, imageArray, ArrayList);
Then inside the overridden method do what you want
override fun onItemClick(position: Int) {
//start the activity you want.
}
I have used Kotlin for implementing click listeners
How to properly use it, currently click is not detecting, I am not able to detect click using below code.
class AdptEvents (val items: MutableList<TestModel>, val context: Context) : RecyclerView.Adapter<ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, p1: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(context).inflate(R.layout.row_event, parent, false))
}
override fun getItemCount(): Int {
return items.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder?.tvAnimalType?.text = items.get(position).getName()
holder?.rootView.setOnClickListener{
clickEventRow(items,position)
true
}
holder?.rootView.setOnLongClickListener {
clickEventRow(items,position)
true
}
}
private fun clickEventRow( items: MutableList<TestModel>, position: Int ) {
Toast.makeText(context,items[position].getName(),Toast.LENGTH_LONG).show()
}
}
class ViewHolder (view: View) : RecyclerView.ViewHolder(view) {
// Holds the TextView that will add each animal to
val tvAnimalType = view.txtTitle!!
val rootView = view.eventListRootId!!
}
You dont need anything else
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder?.tvAnimalType?.text = items.get(position).getName()
holder?.rootView.setOnClickListener{
// code here
}
holder?.rootView.setOnLongClickListener {
//code here
}
}
Change your view holder. Also, if you need to get index, use adapterPosition variable.
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
// Holds the TextView that will add each animal to
val tvAnimalType = itemView.txtTitle!!
val rootView = itemView.eventListRootId!!
init {
itemView.setOnClickListener {
Toast.makeText(context, "OnClick", Toast.LENGTH_LONG).show()
}
// OnLongClick and etc.
}
}
If you need to handle root view click events apply it dirrectly
class ViewHolder (view: View) : RecyclerView.ViewHolder(view) {
// Holds the TextView that will add each animal to
val tvAnimalType = view.txtTitle!!
view.setOnClickListener {
Toast.makeText(view.context, "OnClick", Toast.LENGTH_LONG).show()
}
view.setOnLongClickListener {
Toast.makeText(view.context, "OnLongClick", Toast.LENGTH_LONG).show()
true
}
}
I am trying to store the values from retrofit into a database by pressing a AddtoCartButton but app is getting crashed when I press this button. I am able to retrieve the result from retrofit without any issues but onclicklistener is the issue.
Code:
inner class MoviesAdapter : RecyclerView.Adapter<MoviesAdapter.MovieViewHolder>() {
private val movies: MutableList<Movie> = mutableListOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {
return MovieViewHolder(layoutInflater.inflate(R.layout.item_movie_layout, parent, false))
}
override fun getItemCount(): Int {
return movies.size
}
override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {
holder.bindModel(movies[position])
}
fun setMovies(data: List<Movie>) {
movies.addAll(data)
notifyDataSetChanged()
}
inner class MovieViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val movieGenreTxt : TextView = itemView.findViewById(R.id.movieGenre)
val movieYearTxt : TextView = itemView.findViewById(R.id.movieYear)
val movieAvatarImage : ImageView = itemView.findViewById(R.id.movieAvatar)
val movieDescription: TextView =itemView.findViewById(R.id.movieDescription)
fun bindModel(movie: Movie) {
// movieTitleTxt.text = movie.name
movieGenreTxt.text = movie.menu
movieYearTxt.text = movie.price
Picasso.get().load(movie.picture).into(movieAvatarImage)
movieDescription.text=movie.description
var movieName:String= movie.name!!
var testvar=movie.name.toString()
}
}
}
fun addtocart(view: View)
{
Toast.makeText(context,"Success on Click", Toast.LENGTH_SHORT).show()
print testvar
}
Error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
Below code solves the purpose.
Code:
inner class MoviesAdapter : RecyclerView.Adapter<MoviesAdapter.MovieViewHolder>() {
private val movies: MutableList<Movie> = mutableListOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {
return MovieViewHolder(layoutInflater.inflate(R.layout.item_movie_layout, parent, false))
}
override fun getItemCount(): Int {
return movies.size
}
override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {
holder.bindModel(movies[position])
}
fun setMovies(data: List<Movie>) {
movies.addAll(data)
notifyDataSetChanged()
}
inner class MovieViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val movieGenreTxt : TextView = itemView.findViewById(R.id.movieGenre)
val movieYearTxt : TextView = itemView.findViewById(R.id.movieYear)
val movieAvatarImage : ImageView = itemView.findViewById(R.id.movieAvatar)
val movieDescription: TextView =itemView.findViewById(R.id.movieDescription)
fun bindModel(movie: Movie) {
// movieTitleTxt.text = movie.name
movieGenreTxt.text = movie.menu
movieYearTxt.text = movie.price
Picasso.get().load(movie.picture).into(movieAvatarImage)
movieDescription.text=movie.description
var movieName:String= movie.name!!
var testvar=movie.name.toString()
val addtocart = itemView.findViewById<Button>(R.id.idCart)
addtocart!!.setOnClickListener {
print $testvar
Toast.makeText(context,"Success on Click", Toast.LENGTH_SHORT).show()
startActivity(intent) }
}
}
}
I am trying to retrieve a testvar value from inner class Adapter to addtocart function but I am not getting the value. I am able to retrieve value inside Adapter class but not outside the class.
Code:
inner class MoviesAdapter : RecyclerView.Adapter<MoviesAdapter.MovieViewHolder>() {
private val movies: MutableList<Movie> = mutableListOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {
return MovieViewHolder(layoutInflater.inflate(R.layout.item_movie_layout, parent, false))
}
override fun getItemCount(): Int {
return movies.size
}
override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {
holder.bindModel(movies[position])
}
fun setMovies(data: List<Movie>) {
movies.addAll(data)
notifyDataSetChanged()
}
inner class MovieViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val movieGenreTxt : TextView = itemView.findViewById(R.id.movieGenre)
val movieYearTxt : TextView = itemView.findViewById(R.id.movieYear)
val movieAvatarImage : ImageView = itemView.findViewById(R.id.movieAvatar)
val movieDescription: TextView =itemView.findViewById(R.id.movieDescription)
fun bindModel(movie: Movie) {
// movieTitleTxt.text = movie.name
movieGenreTxt.text = movie.menu
movieYearTxt.text = movie.price
Picasso.get().load(movie.picture).into(movieAvatarImage)
movieDescription.text=movie.description
var movieName:String= movie.name!!
var testvar=movie.name.toString()
}
}
}
fun addtocart(view: View)
{
Toast.makeText(context,"Success on Click", Toast.LENGTH_SHORT).show()
print testvar
}
Think you are looking to put a button in the RecyclerView.
In that case setOnclicklistener within the
inner class MovieViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val addtocart = itemView.findViewById<Button>(R.id.viewprofile)
addtocart!!.setOnClickListener {
}}
My list is about questions and answer.
I've designed an item that has the question and answer and I'm planing to hide and show the answer, not the whole item (GONE/VISIBLE), when the user click on the question. So it will be more like expandable way.
Now this is my adapter:
class FaqExpandableAdapter internal constructor(private val context: Context, private var items: List<Faq>,private val callBack: AdapterCallBack?) : RecyclerView.Adapter<FaqExpandableAdapter.MyViewHolder>() {
private val inflater: LayoutInflater = LayoutInflater.from(context)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = inflater.inflate(R.layout.item_question_faq, parent, false)
return MyViewHolder(view)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.txtQuestionFaq.text = items[position].question?.toString() ?: "-"
holder.txtAnswerFaq.text = items[position].answer?.toString() ?: "-"
}
override fun getItemCount(): Int {
return items.size
}
fun update(items: List<Faq>) {
this.items = items
notifyDataSetChanged()
}
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
#BindView(R.id.txtQuestionFaq)
lateinit var txtQuestionFaq: AppCompatTextView
#BindView(R.id.txtAnswerFaq)
lateinit var txtAnswerFaq: AppCompatTextView
init {
ButterKnife.bind(this, itemView)
}
#OnClick(R.id.relativeRowFaq)
fun onItemClicked() {
callBack?.onItemClicked(adapterPosition)
}
}
interface AdapterCallBack {
fun onItemClicked(position: Int)
}
}
My last step is where to do the visibility action?
Kotlin : Write onClick method on your onBindViewHolder function.
holder.txtQuestionFaq.setOnClickListener {
holder.txtAnswerFaq.visibility = View.VISIBLE;
}
In onBindViewHolder() method, add below lines: (I use Java)
holder.txtQuestionFaq.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.txtAnswerFaq.setVisibility(View.VISIBLE);
}
});