I need to display data from firebase database using a recyclerView. everything works fine, I can see the cards and all but there wont be and data on the card.
here is my adapter class:
class MyAdapter(c: Context, t: ArrayList<Thoughts>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
var context : Context
var theThoughts : ArrayList<Thoughts>
init{
context = c
theThoughts = t
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(LayoutInflater.from(context).inflate(R.layout.card_view01, parent, false))
}//end onCreateViewHolder
override fun getItemCount(): Int {
return theThoughts.size
}//end getItemCount
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
//holder.theTopicAdapter.text[position]
//holder.theThoughtAdapter.text[position]
//it works fine withOUT these two lines up
}//end onBindViewHolder
class MyViewHolder(itemView:View):RecyclerView.ViewHolder(itemView) {
var theTopicAdapter: TextView
var theThoughtAdapter: TextView
init{
//super.itemView
theTopicAdapter = itemView.textViewCard01
theThoughtAdapter = itemView.textViewCard02
}
fun MyViewHolder(itemView: View){
super.itemView
theTopicAdapter = itemView.textViewCard01
theThoughtAdapter = itemView.textViewCard02
}//end MyViewHolder function
}//end MyViewHolder class
}//end MyAdapter class
this is the code where I get the data and display it:
databaseReference.addValueEventListener(object: ValueEventListener {
override fun onDataChange(p0: DataSnapshot) {
if (p0.exists()){
for (thought in p0.children){
//var theTopicGetter = thought.child("theTopic").value.toString()
val t: Thoughts = thought.getValue(Thoughts::class.java)!!
list.add(t)
}//end for loop
}//end if
adapter = MyAdapter(this#SeePreviousThoughts, list)
recyclerView.adapter = adapter
}//end onDataChange
override fun onCancelled(p0: DatabaseError) {
Toast.makeText(this#SeePreviousThoughts, "error, please try again.", Toast.LENGTH_SHORT).show()
}
})//end the listener
this is the class thoughs:
class Thoughts() {
lateinit var theID: String
lateinit var theCode: String
lateinit var theTopic: String
lateinit var theThought: String
constructor(theID: String, theCode: String, theTopic: String, theThought: String) : this() {
this.theID = theID
this.theCode = theCode
this.theTopic = theTopic
this.theThought = theThought
}
}
I should get the data from the database and it should be displayed on each card, but the cards are simply empty.
this is a screenshot of the empty recyclerView
the words topic and thoughts are default from the xml file.
I guess that my problem is that the function MyViewHolder in class MyViewHolder is never used... a screenshot of the code that isn't being used
Problem was in override fun onBindViewHolder(holder: MyViewHolder, position: Int) method. This adapter works:
class MyAdapter(val context: Context, val theThoughts: ArrayList<Thoughts>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(LayoutInflater.from(context).inflate(R.layout.card_view01, parent, false))
}//end onCreateViewHolder
override fun getItemCount(): Int {
return theThoughts.size
}//end getItemCount
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.theTopicAdapter.text = theThoughts[position].theTopic
holder.theThoughtAdapter.text = theThoughts[position].theThought
}//end onBindViewHolder
class MyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
lateinit var theTopicAdapter: TextView
lateinit var theThoughtAdapter: TextView
fun MyViewHolder(itemView: View){
super.itemView
theTopicAdapter = itemView.textViewCard01
theThoughtAdapter = itemView.textViewCard02
}//end MyViewHolder function
}//end MyViewHolder class
}//end MyAdapter class
Related
Override function onBindViewHolder is not overwriting when I add ViewHolder class inside it.
When I put viewHolder class outside it. it is not working.
Below in my code -
class data_custom_adapter(private val context: Context, private val datalist : ArrayList<Display_data>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.display_data_card, parent, false)
return CustomAdapter.ViewHolder(v)
}
//Issue occur here -- it is not overriding when I add ViewHolder class
override fun onBindViewHolder(holder: data_custom_adapter.ViewHolder, position: Int) {
holder.bindItems(context,datalist[position])
}
override fun getItemCount(): Int {
return datalist.size
}
//the class is holding the list view
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val datalist_data = itemView.findViewById(R.id.displayxmldata) as TextView
fun bindItems(context: Context, datashow : Display_data) {
datalist_data.text = datashow.appdata
}
}
}
Guys, please help to find out issue in this.
The ViewHolder must match the class that you indicate in the first line. so in
class data_custom_adapter(private val context: Context, private val datalist : ArrayList<Display_data>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
there's CustomAdapter.ViewHolder. Change this to your data_custom_adapter.ViewHolder and it should work. so like
class data_custom_adapter(private val context: Context, private val datalist : ArrayList<Display_data>) : RecyclerView.Adapter<data_custom_adapter.ViewHolder>() {
this needs to be also changed in the onCreateViewHolder function
I hope this will work.
class data_custom_adapter(
private val context: Context,
private val datalist : ArrayList<Display_data>) : RecyclerView.Adapter<data_custom_adapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.display_data_card, parent, false)
return data_custom_adapter.ViewHolder(v)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindItems(context,datalist[position])
}
override fun getItemCount(): Int {
return datalist.size
}
//the class is holding the list view
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val datalist_data = itemView.findViewById(R.id.displayxmldata) as TextView
fun bindItems(context: Context, datashow : Display_data) {
datalist_data.text = datashow.appdata
}
}
}
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 simple RecyclerViewAdapter class:
class TariffsCardAdapter(context: Context, tariffCardItems: List<ItemsItem?>?) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var context: Context? = null
private var tariffCardItems: ArrayList<ItemsItem?>? = null
init {
this.context=context
this.tariffCardItems=tariffCardItems as ArrayList<ItemsItem?>
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_tariff_card_items, parent, false)
return TariffsCardAdapterViewHolder(view)
}
override fun getItemCount(): Int {
return tariffCardItems!!.size
}//getItemCount ends
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val viewHolder = holder as TariffsCardAdapterViewHolder
Log.e("posX","pos:::".plus(position))
}
private inner class TariffsCardAdapterViewHolder : RecyclerView.ViewHolder {
var text: TextView? = null
constructor(row: View) : super(row) {
text= row.findViewById(R.id.text) as TextView
}
}
}
Now lets suppose that my tariffCardItems: List<ItemsItem?> will have only 5 items in the list that I want to show.
The problem is that when the adapter gets instantiated that is for the first time the onBindViewHolder method is called twice.
So that the Log values prints as:
pos:::0
pos:::1
pos:::0
pos:::1
Which means that my recycler view position will be 1 in the end.
And the very first view will be created with list item at index 1 which is wrong and should be `0.
In other words, the very first child of the recycler view is created by 1 position value which is wrong.
What am I doing wrong?
It's simply because you are calling adapter 2 in code an recyclerview's bindviewholder should use to bind data not to call viewholder.
class TariffsCardAdapter(context: Context, tariffCardItems: List<ItemsItem?>?) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var context: Context? = null
private var tariffCardItems: ArrayList<ItemsItem?>? = null
init {
this.context=context
this.tariffCardItems=tariffCardItems as ArrayList<ItemsItem?>
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_tariff_card_items, parent, false)
return TariffsCardAdapterViewHolder(view)
}
override fun getItemCount(): Int {
return tariffCardItems!!.size
}//getItemCount ends
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
//bind data
}
private inner class TariffsCardAdapterViewHolder : RecyclerView.ViewHolder {
var text: TextView? = null
constructor(row: View) : super(row) {
text= row.findViewById(R.id.text) as TextView
}
}
}
For example your adapter should be like this
class CustomAdapter(val userList: ArrayList<User>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
//this method is returning the view for each item in the list
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.list_layout, parent, false)
return ViewHolder(v)
}
//this method is binding the data on the list
override fun onBindViewHolder(holder: CustomAdapter.ViewHolder, position: Int) {
holder.bindItems(userList[position])
}
//this method is giving the size of the list
override fun getItemCount(): Int {
return userList.size
}
//the class is hodling the list view
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bindItems(user: User) {
val textViewName = itemView.findViewById(R.id.textViewUsername) as TextView
val textViewAddress = itemView.findViewById(R.id.textViewAddress) as TextView
textViewName.text = user.name
textViewAddress.text = user.address
}
}
}
This method from your code is calling twice
val viewHolder = holder as TariffsCardAdapterViewHolder
Log.e("posX","pos:::".plus(position))
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);
}
});