Viewholders and setOnClickListeners - android

I have a RecyclerView with a list of items. The individual list item is an ImageView with a TextView. They have different behaviours when clicked. The individual list item is rendered with the aid of a ViewHolder.
Where should I put the .setOnClickListener() call for the ImageView and TextView? In the ViewHolder? Or inside the RecyclerView's onBindViewHolder method when the view is binded?

From the official doc of ViewHold:
A ViewHolder describes an item view and metadata about its place
within the RecyclerView.
So you should avoid do anything else in the viewhold, instead use onBindViewHolder in the RecyclerView
If you take a look at the example made by Google of RecyclerView on GitHub you will see google does not set listeners in the ViewHolder

Call it inside of the onBindViewHolder method while you're binding your ImageView and TextView. If you set it on the ViewHolder itself, then the onClick() will be triggered for the entire list item in the RecyclerView .

Related

Recycler View to change View Holders

I use a RecyclerView to display a list of items. The RecyclerView shows a single item at the time. By clicking a button I would like to change ViewHolders for all the items, including the one displayed. The data stays the same, only the list item layout changes.
I supposed I need to clear the cache pool, but it did not help. There are still views in the recycler pool.
recyclerView.recycledViewPool.clear()
RecyclerView keeps using the cached views.
Moreover, how to re-create the view with a new ViewHolder of the item displayed?
add type in your model class
var viewType : ViewType
make an enum of viewType
ViewType { VIEW_ONE, VIEW_TWO }
override ItemViewType function in your RecyclerViewAdapter. Make separate Layout files for each view type and create/inflate in onCreateViewHolder of RecyclerViewAdapter.
When button is being pressed. Change the ViewType in your model class and call notifyDatasetChanged()

unique item view in Listview

I have a ListView. Each view item in that Listview has a progress bar that will be updated by some threads. As The listview reuse the views (Has no unique view), the threads update unexpected views when new item has been added and when the listview has been scrolled.
I would like to know how can I create some unique views that each thread will update only the given view in the listview?
Listview doesn't re-use the views by default like recyclerview does, because listview relies on implementers using the ViewHolder pattern to achieve the re-use. Simply don't use the viewholder pattern and each list item will receive its own view. Just be careful not to do this in a list with too many concurrent items. Viewholder became a defacto standard for a reason.
I had just to take a look at that class. Put the view that will be updated in the header list. When done, put it back to the adapter.

On View click inside a RecyclerView row change the state of other rows inside the same RecyclerView

I have an ImageViewinside every row of my RecyclerView. I set an setOnClickListener inside method onBindViewHolder() of my Adapter so each time this ImageViewis clicked something happens.
But the problem is that I need to change the state of other rows inside the same RecyclerView. But they are not the current row at method onBindViewHolder().
Is there any way to from method onBindViewHolder()change the state of ImageViewin another row that is not the current one, if I know the position/index of the other row I want to change?
What you can try is for example creating a CustomView for example MyRelativeLayoutas a wrapper of the item in RecyvlerView, that extends the view you need to change, once the user clicks the view this MyRelativeLayoutyou can have a method for example isClicked(boolean) so you put it isclicked(true) and then myAdapter.notifiyDataSetChanged().And then you can decide what to do to you imageView, for example if MyRelativeLayout isClicked() == true then change its drawable to whatever yo need or something like that.
hope this helps!

RecyclerView inside RecyclerView not smoothly

There are some topics about RecyclerView inside RecyclerView but I see most of them do not fit my case. My case is I have a RecyclerView (verticle linear layout management) displays a list of CardView, each Cardview contains a inner RecyclerView (horizontal linear layout management). The problem is all about performance when scrolling, it is not smooth at all. I notice if I comment the setAdapter for the Inner Recyclerview, the scrooling become smooth, but I make the CardView not updated the new list. The code is something similar to this:
onBindViewHolder...{
holder.innerRecycler.setAdapter(new InnerAdapter((data));
// comment that line make the outer recyclerview smoothly but the CardView data not updated thanks to the view recycling.
}
I know a scrollable view inside a scrollable view is not a good idea but I dont see any other choices. Anyone face to this kind of layout before?. Thanks.
UPDATE (add more code).
// init outer recyclerview
mOuterRecyclerView = (RecyclerView) findViewById(...);
mOuterRecyclerView.setLayoutManagement(new LinearLayoutManagement(this));
mOuterRecyclerView.setHasFixedSize(true);
mOuterRecyclerView.setAdapter(new OuterAdapter(dataList));
// The adapter class for the outer one
onBindViewHolder(...){
final dataItem = mItems.get(position);
holder.innerRecycler.setAdapter(new InnerAdapter(dataItem.getList()));
}
// the holder for the outer
class MyHolder extends ViewHolder{
RecyclerView innerRecycler;
public MyHolder(View view){
super(..);
innerRecycler = findViewById(...);
}
}
// the adapter for the inner
onBindViewHolder(...){
final dataItem = mItems.get(pos);
// async loading
holder.tvTitle.setText(dataItem.getTitle);
}
The layout is pretty simple so I dont post the fully code here. :)
#Paul i had the same requirement and the below trick worked.
Put the parent recyclerview inside NestedScrollView and in your onCreate method,
set.
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setNestedScrollingEnabled(false);
This prevents scroll of parent recyclerview and scroll becomes absolutely smooth.
There is no issue in such an approach as long as they scroll along different axes.You could enable RecyclerView.startNestedScroll(int) and also handle situations like overscroll.This delay would be because you are reinitiating an adpater everytime. You could try something different like maintaining a map of adpaters and calling RecyclerView.swapAdapter(args...) in bindVH.
Another good step could also be using a common pool for recycled views using RecyclerView.setRecycledViewPool(args...) .
I have created and used a list of 100+ plus items with a nested (different axis) recycler and have not faced issues .
If you would provide more code( where you have written async loading) I could help you more.But I suggest you go through the API and the design patterns and that should solve your issue.
Since there are some user ask me how to archive, I'm going to post what I do.
The sugession that #Droidekas seems a good point but I dont follow that.
What I did is:
Each horizontal recycler view is a item of a vertical recycler view
When I need to set the data for the particular vertical item (onBindViewHolder), I use the horizontal recycler adapter setNotifyDataSetChanged instead of setting a completely new adapter or swapping it. This way, I got the vertical recyler run very smoothly.
The vertical recyler adapter structure could be:
Vertical Item view holder -> Vertical Item[Name, List<Horizontal item>,...]
Vertical Item view holder -> Vertical Item[Name, List<Horizontal item>,...]
In OnBindViewHolder
holder.setData(VerticalItem)
In the Holder, I have a setData method looks like:
setData(VerticalItem item){
mItems = item.getHorizontalItems();
mHorizontalAdapter.notifyDataSetChanged();
}
Hope it helps. :D

how to get focus on the items of a listview toching the screen and moving the finger upper and down withoud untouch it - Android

I have a listview with two columns where the user can compare the productName and proudctQty against the stock. There are loads of products in that list and the user may get confuse checking all of them. So, the idea is to highlight the products and their price by using focus.
Does anyone know if would be possible to implement it in listview like on the virtual keyboard (it isnot onLongTouch or click)?
Could anyone give a hint about how to do it?
Many thanks
ok like in case of wheelpicker iPhone we can highlight the product just follow these steps
implement the list's onscrollchangedlistener .
put the list in a relative layout with another view at the centerinparent and fillparent
on this view you will display the highlighted item.
as the list is scrolled update the content over that view inside the overrided onscroll method.
You need to use a View Holder Pattern. You can find more information on Google.
Simply create a class called AdapterViewHolder, declare properties, the Views on each row.
For example:
public class AdapterViewHolder
{
ImageView myImageView;
TextView myTextView;
...
}
In constructor pass your values to set to the views, initialize your views and set your values like:
public AdapterViewHolder(String param, Drawable imageDrawable){
// set values to views
}
In the adapter in getView method:
if convertView == null
//then create your layout and holder class, set your holder to your layout by view.setTag method, prepare your view and return it
else
//get your layout tag by view.getTag(), cast it to AdapterViewHolder and update your views and values of them as you like and then return updated view.
For more info search for ViewHolder Pattern in android listviews.

Categories

Resources