I want to create an activity that looks similar to this:
I will use a recyclerview to show all the questions. But each question has a variable number of clickable tags. The number of tags will vary and their width will also vary. Hence, I am using a FlowLayout in which I shall place the clickable tags. Typically I would have to use addview multiple times by looping on the number of tags. Is it possible to do this in the OnCreateViewHolder? How do I pass the information on the number of times the addview method is to be called to the onCreateViewHolder?
Typically, on an OnCreateViewHolder method override, you just inflate a layout from resources and then construct a ViewHolder instance passing in that layout and whatever parameter it needs (in your case, the tags). The constructor of the ViewHolder class can then create any additional view(s), set their values and add it to the passed in layout.
Related
I'm getting my data via an API that supplies me with an array of rows for my RecyclerView. Inside each of these rows there is an array of elements which I want to add dynamically to each of my RecyclerView rows. Each element corresponds to a view. So for example I might get a title, then an image, then text. Or I might get just an image. Or a title and text. These are just some of the elements, there are more and maybe hundreds of different possible combinations. For this reason it's not viable to create and inflate different row types as you would normally do if you need just a few different types of rows.
I tried to inflate and attach my views to the row on the onBindViewHolder method, but this caused the elements to be added again and again everytime that method was called.
I have searched around and have found no similar questions to what I am after, and I was wondering if there was a nice clean and elegant way of achieving what I need.
I managed to achieve what I was looking for using the following method I had already tried:
I tried to inflate and attach my views to the row on the onBindViewHolder method, but this caused the elements to be added again and again everytime that method was called.
To prevent the views to being continuously added everytime a view was recycled, I overrided the onViewRecycled method, and removed all the views from the linear layout inside the row.
So far, I haven't had any problems with this method, but it's probably not the most efficient.
I have decided to upgrade my code to use RecyclerView now instead of the list I am using now.
As I understand the following is how it normally goes:
onCreateViewHolder - this inflates a view, and does the findviewbyid and returns it as a ViewHolder object for the view
onBindViewHolder - this assigns the view holder values to the position view (which is being recycled).
This is all fine and dandy... If the views in the list contain the same fields...
My views however in my list are different, before I programmatically added views depending on the adapter List (in the getView method).
Is there a "good practice" way to handle this, I can't think of a good way to get around this.
getViewItemType does not work as the views are unique and that they are not predefined.
This is what you need to use when you different types of Views inside a ListView or RecyclerView :-
getItemViewType() and getViewTypeCount()
First you need to use getViewTypeCount() and return the number of unique views you need inside your List. Then override getItemViewType() and return the View type you want to inflate inside the List row.
Hope it will help.
If you still have any issue and need a working example, let me know, i'll update my answer.
I understand the idea and usage of Viewholder pattern, but still I have one question:
Assume we have one TextView in the viewholder, and 10 items to display ("item0, item1....").
If I call findViewById once, as I understand I have one object of that TextView.
So at first call to getView I inflate the view, find the reference and set text "item0".
At second call I get same TextView and set text "item1" to the same TextView.
Why item 0 text doesn't change?
Is there any cloning in the background?
Is there any cloning in the background?
Android preallocate a number of views that are enough to fill the screen of the device where you are running the app ( a pool of views ), identical from the content perspective but differently from the reference perspective
Assuming that you implement your ViewHolder inside an adapter class and you use the holder in the getView() method, the only thing that is for sure, is that the TextView in your case , describe a slot of the parent structure (e.g. ListView). Once you have defined the slot in an xml, that is inflated from your adapter, there is no cloning or something like that.
According to Google Documentation the holder idea is described as :
Your code might call findViewById() frequently during the scrolling of
ListView, which can slow down performance. Even when the Adapter
returns an inflated view for recycling, you still need to look up the
elements and update them. A way around repeated use of findViewById()
is to use the "view holder" design pattern.
A ViewHolder object stores each of the component views inside the tag
field of the Layout, so you can immediately access them without the
need to look them up repeatedly. First, you need to create a class to
hold your exact set of views.
There is not cloning , only reusability of the view
I have a ListView that contain several TextViews. Once a TextView is pressed I get the onClick called with the view. What is the best practice to get the other text views on that row? IDs of the text views are similar along the rows so I need to keep on the context of the given view. I would guess I need to get the Parent of the given view and then grab the rest of the text views from it.
Thanks.
Yeah, you would need to get the parent of the current textview, then get all the children contained within that parent.
Depending on what you need to do with the textviews you could either call FindViewById on the parent view to get each TextView by ID. Or you can iterate through the children as suggested in this question/answer:
Android - get children inside a View?
I know people mention that calling FindViewByID is a taxing process, so consider storing the references to the textview's in some sort of object so you can quickly get the references to the other textview's within the row without having to look them up all the time.
ViewHolder's work pretty well, as they store the references to the textview's within an object (which you only need to fill once during creation) but it requires setting up your own customized adapter.
In my custom view I need to use the getParent method and set the visibility on some of it's child views depending on my custom view's state. The problem is that I want to instantiate the child views just once. Where is the best place to do this?
I'm not exactly sure what you want to do. But if all of this is occurring in the same Activity screen why don't you just assign ids (e.g. android:id="#+id/someId" to your elements in the layout.xml file.
This way you can reference any element programatically in your code by calling:
View someView = findViewById(R.id.someId);
I am unclear why you would need to call getParent. If you are trying to manipulate views in a different activity then I think you will need to use a Handler.