RecyclerAdapter is creating multiple view back to back - android

I am using recyclerview to display images in cardview. When I load images from the url. It loads well from first time but when It loads for second time it is not displayed properly.
How to fix it? Here is the code
override fun getItemCount(): Int {
dataList = FlickrDBOperation.dataArray
if (dataList!!.isEmpty())
return 0
Log.e("count",dataList!!.size.toString())
return dataList!!.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
var itemView: View = LayoutInflater.from(parent.context).inflate(R.layout.imagelist_row,parent,false)
var viewHolder: FlickrAdapter.Holder = FlickrAdapter.Holder(itemView)
return viewHolder
}
override fun onBindViewHolder(holder: Holder, position: Int) {
holder.image_name.text = dataList!!.get(position).name
Picasso.with(context).load(dataList!!.get(position).preUrl).into(holder.row_image)
}
class Holder(itemView: View?) : RecyclerView.ViewHolder(itemView) {
val row_image: ImageView
val image_name: TextView
init {
row_image = itemView!!.findViewById<ImageView>(R.id.row_image)
image_name = itemView!!.findViewById<TextView>(R.id.image_name)
}
}

Related

View all button to button of recycler view

Initially load 3 items from list after click on view all button load remaining all data to same page in kotlin.
To show 3 items I added limit to show data in adapter class in getItemCount mathod. So now I am able to see only 3 items from list. But not able to do like ad all data on same page on click view all button.
Here is how I have solved the issue.
class MyAdapter(private val maxItems: Int = 3) : RecyclerView.Adapter<MyViewHolder>() {
private val items = mutableListOf<String>()
fun setData(data: List<String>) {
items.clear()
items.addAll(data)
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_layout, parent, false)
return MyViewHolder(view)
}
override fun getItemCount(): Int {
return min(items.size, maxItems)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.bind(items[position])
}
fun updateMaxItems(max: Int) {
maxItems = max
notifyDataSetChanged()
}
}
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val textView = itemView.findViewById<TextView>(R.id.item_text)
fun bind(text: String) {
textView.text = text
}
}
In your Activity/Fragment where you set up the RecyclerView, create a button "View All" and set its onClickListener
val viewAllButton = findViewById<Button>(R.id.viewAllButton)
viewAllButton.setOnClickListener {
//update the adapter's maxItems to show all items
adapter.maxItems = Int.MAX_VALUE
adapter.notifyDataSetChanged()
}

Recycler view pagination in kotlin android development

Want to show images from internal storage in android studio using recycler view, did that but now want to use pagination, can it be done using pagination?
class TestingAdapter(var URI_String: ArrayList<String>, var activity: Activity) :
RecyclerView.Adapter<TestingAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view: View = LayoutInflater.from(parent.context).inflate(R.layout.view, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
Glide.with(activity).load(URI_String[position]).into(holder.imageView)
}
override fun getItemCount(): Int {
return URI_String.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var imageView: ImageView
init {
imageView = itemView.findViewById(R.id.imageView2)
}
}
}

How to get the current loaded rows/items of a RecyclerView

I have a list of items in my RecyclerView and I need to get the currently loaded items (i.e. not the recycled or off screen items) at a time.
This is may adapter
class MyAdapter(list: List<String>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
private var items: List<String> = list
class MyViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
val myText = view.findViewById<TextView>(R.id.my_text);
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val listItem: View = LayoutInflater.from(parent.context)
.inflate(R.layout.list_item, parent, false)
return MyViewHolder(listItem)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.myText.text = items[position]
}
override fun getItemCount() = items.size
}
And RecyclerView:
recyclerView.apply {
layoutManager = LinearLayoutManager(this#MainActivity)
hasFixedSize()
adapter = MyAdapter(listOf("a", "b", "c")) // List is bigger than that
}
How can I do that?
I'd a case that I needed to ensure how many RecyclerView items are currently loaded in order to control a performance issue; so that created this for someone else was looking for an answer.
You need to track the list of loaded & recycled items:
The items are loaded in onBindViewHolder() callback
The items are recycled in onViewRecycled() callback
So, we can create a local list that tracks the current loaded item positions, add new positions in onBindViewHolder() and remove recycled ones in onViewRecycled()
In the below code the currentLoadedPositions tracks the loaded positions, and you can create a method that returns it:
class MyAdapter(list: List<String>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
private var items: List<String> = list
// Tracking the currently loaded items in the RecyclerView
private val currentLoadedPositions: ArrayList<Int> = ArrayList()
fun getLoadedPositions(): ArrayList<Int> {
return currentLoadedPositions
}
class MyViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
val myText = view.findViewById<TextView>(R.id.my_text)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val listItem: View = LayoutInflater.from(parent.context)
.inflate(R.layout.list_item, parent, false)
return MyViewHolder(listItem)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val item = items[position]
holder.myText.text = item
currentLoadedPositions.add(position)
Log.d("LOG_TAG", "onViewRecycled: $currentLoadedPositions")
}
override fun getItemCount() = items.size
override fun onViewRecycled(holder: MyViewHolder) {
currentLoadedPositions.remove(Integer.valueOf(holder.adapterPosition));
Log.d("LOG_TAG", "onViewRecycled: $currentLoadedPositions")
}
}

Strange animation when removing item from RecyclerView

I have a recyclerView populated by the val microphones: MutableList<Microphone>. There's a button in the row layout to remove that item from the list, which I've managed to get functioning, but the animation is going wrong. It looks like when the recyclerView updates, it removes the last item in the list, then the correct item, and then the whole list below the removed item animates to the correct state.
Here's the relevant bits of the recyclerView adapter:
class RecyclerViewAdapter(
val microphones: MutableList<Microphone>
): RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val cellForRow = LayoutInflater.from(parent.context).inflate(R.layout.favorites_row, parent, false)
return ViewHolder(cellForRow)
}
override fun getItemCount(): Int {
return microphones.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val microphone = microphones[position]
holder.bind(microphone)
holder.favoritesButton.setOnClickListener {
microphones.remove(microphone)
notifyItemRemoved(position)
}
}
class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
val modelText = view.findViewById<TextView>(R.id.model_textView)
val brandText = view.findViewById<TextView>(R.id.brand_textView)
val favoritesButton = view.findViewById<ImageButton>(R.id.btnFavorite)
fun bind(
microphone: Microphone,
) {
modelText.text = microphone.model
brandText.text = microphone.brand
}
}
}
Here's a screen recording of the issue:
https://imgur.com/a/pJt3KwH

How to I access button inside a recycler view?

This is my RecyclerView Adaper
class RecyclerAdapter(private val recyclerList: List): RecyclerView.Adapter(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): mainRecyclerViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.quiz_item_recycler_view,
parent, false)
return mainRecyclerViewHolder(itemView)
}
override fun getItemCount() = recyclerList.size
override fun onBindViewHolder(holder: mainRecyclerViewHolder, position: Int) {
val currentItem = recyclerList[position]
holder.imageView.setImageResource(currentItem.imageResource)
holder.textView.text = currentItem.recyclerCardText
}
class mainRecyclerViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
val imageView: ImageView = itemView.rec_image
val textView: TextView = itemView.text_view_1
}
}
And this is my data class
data class RecyclerItemMain(val imageResource: Int, val recyclerCardText: String, val button: Button)
Like this:
override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
holder.yourButton.setOnClickListener { v ->
// Here your start your other activity or navigate to another fragment
}
}
Remember that if you intent to send the user to diferent activities depending on the button, you have to create a when expression what will send the user to an activity depending on another value in the recyclerItem, for example the text of the item, in your case currentItem.recyclerCardText
Here is your full adapter, re-organized:
class RecyclerAdapter(recyclerList: List<CategorySectionIcon>) :
RecyclerView.Adapter<YourAdapter.CustomViewHolder>() {
private var recyclerList: List<CategorySectionIcon>? = recyclerList
inner class CustomViewHolder(
//Get a reference to the Views in our layout//
val myView: View
) : RecyclerView.ViewHolder(myView) {
var textView: TextView = myView.findViewById(R.id.your_text)
var imageView: ImageView = myView.findViewById(R.id.your_image)
var yourButton: Button = myView.findViewById(R.id.iv_category_imagen_icon)
}
override//Construct a RecyclerView.ViewHolder//
fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val itemView =
layoutInflater.inflate(R.layout.quiz_item_recycler_view, parent, false)
return CustomViewHolder(itemView)
}
override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
holder.textView.text = recyclerList!![position].recyclerCardText
holder.imageView.setImageResource(recyclerList!![position].image)
holder.yourButton.setOnClickListener { v ->
// Here your start your other activity or navigate to another fragment
}
}
//Calculate the item count for the RecylerView//
override fun getItemCount(): Int {
return recyclerList!!.size
}
}

Categories

Resources