after every 5th item, i want a button view to load.
override fun getItemViewType(position: Int): Int {
if (position % 5 == 0 && position != 0) {
return R.layout.button10th
} else {
return R.layout.checkitout
}
}
when i run it, this is taking away my 5th item. how can i achieve this without taking any of my array items? do i need to fix my getItemCount?
override fun getItemCount(): Int {
return lists.size
}
i want it look like below. 1. John 2. Mike 3. Chris 4. Jane 5. Sue 6. CLickable BUTTON
After some time working with multiple view RecyclerViews, here is my best way to do it (that prevents bugs and has decent implementation):
Create two viewHolder classes for your two item types, each having a bind() function inside:
Since we have multiple view types, thus multiple viewHolders, we need to create a plain java object that holds the common information. I called mine Cell(). Call it whatever suits your needs. We'll get to that.
So now you have your two viewHolder classes:
NameViewHolder()andButtonViewHolder().Now lets create our Cell class and objects:
Let me explain: So I created a global Cell() object that has an identifier function inside that gives me a class hash. This function will serve us later to get our view type. In my RecyclerView I don't use Int or other things to identify my view types, but the hash of my object class itself. The hash is a unique string for every class. So if my adapter, in its list of items, stumbles upon a object that is CellName(), the recyclerView gets its hash using my identifier() function and realises that the view type for this is Name, not a Button (from your example above). The other classes extend the global Cell() class and have their custom individual logic. Give them whatever parameters you like or need.
Now inside our adapter we will add our list of Cells as a parameter like this:
Make sure you implement the RecyclerView.Adapter exactly like above, otherwise the multiple view will not work.
Now the getItemViewType override method that chooses your viewTypes will look like this:
As you can see, we use the identifier() function I previously talked about, here, to let the adapter know what view type to choose based on the Cell() class hash.
Now the onCreateViewHolder where your views get inflated:
Now, when the adapter finds a Name view type, it inflates the NameViewHolder with the desired layout, and same for the Button with ButtonViewHolder. Next, onBindViewHoder:
Basically for each type of cell class, you access the bind functions from your viewHolder classes.
That's about it with the recyclerView adapter. This is the whole file so far(next we will move on to creating your list of cells):
Make sure you scroll the above text snipped as it's very large to fit. Also, the
is a Kotlin Extension Function that makes layout inflation faster. Use as is.
Next, your cell list creation:
Use this function in any activity/fragment where you have that adapter.
That's it. Feel free to customise your cells and view types as much as you want. Remember that for each new view type you need in your recyclerView, you have to create a cell class and a view holder class for it. This is my full tutorial on multiple view types. And to answer your explicit question of how to do this:
... you don't. You don't to this logic anymore inside the recyclerView. The adapter must only receive a list of Cells and nothing more. This just prevents a full load of bugs and makes your code cleaner and easier to read. You just create your cells in the createCells() function like:
and you won't have to worry about item numbers and positions anymore. Just use the createCells() function to do your entire logic but return a single full list and the adapter knows what to do.
And if you're wondering what to do with the bind() function inside your bindViewHolder, you can do whatever you would do in that code block normally, inside your adapter, like setting texts in textViews and buttons, setting images with Glide or by resource linking, create your button functionality. I'll actually explain how to do your button functionality and bind():
Remember how we already set our desired information in our cell objects.
Here you have access to that object, so let's create a button and add a callback for it. In order to do so, you have to update your bind function with a callback variable.
The invoke function tells your callback that the button has been pressed. Now in order to make the callback work, we need to declare the callback variable as public in your adapter. So inside your adapter add this:
And also don't forget to add the var as parameter to your bind call here in the adapter:
So instead of:
we will have:
Basically this type of callback variable is a Kotlin shortcut for an interface that would do the same thing, you know, in Java, when you create an interface to handle your adapter clicks.
But we are not done yet, make sure your adapter callback variable is not private, and in your ACTIVITY, do this to access it:
where
myAdapter = MyAdapter(cellList)Hope I helped.