The following piece of code is inflating the same view for 20 times. Since inflating is costly. I want to inflate it only one, and use the same view for 20 items, i just want to change the visible data in the UI.
LinearLayout ll = new LinearLayout(context);
for (int i = 0; i < 20; ++i) {
View itemView = inflater.inflate(getLayoutId(), parent, false);
itemView.setText(data.getName(i);
ll.add(itemView);
}
I want something like this.
LinearLayout ll = new LinearLayout(context);
View itemView = inflater.inflate(getLayoutId(), parent, false);
for (int i = 0; i < 20; ++i) {
itemView.setText(data.getName(i);
ll.add(itemView);
}
But am not able to use the itemView obj this way.
Can anyone tell me how to use the view many times once it inflated.
You cannot do that. If you think its costly then find another way to create your layout.
But consider gridViews for example. They create a ton of views and show them and that works great.
You cannot add the same object of a view 2 times to a layout. Every object has its own state which in your case in a way says that you will share the state between all your 20 views which doesn't make sense to do, meaning changing the text on one textView will change it on all the rest...
Just inflate 20 seperate views and fill them appropriately.
Also consider using ListView or GridView if you actually have the exact same view it can offer some nice features like view recycling.
You should use ViewHolder patern:
http://developer.android.com/training/improving-layouts/smooth-scrolling.html#ViewHolder
it should do all things You want
Related
full view of all the items of recyclerview should be added to a single view.Is it possible in recyclerview. Right now I've done something like this,
for(int i=0; i<=adapter.getItemCount(); i++){
View view = layoutManager.findViewByPosition(i);
}
But it is returning null for every iteration of "i".please suggest answer for this.
Try this.
YourViewHolder holder = recyclerview.findViewHolderForAdapterPosition(position);
View view = holder.itemView;
//now you have the rootView for each row
I am having a RecyclerView with a Custom Adapter which extends RecyclerView.Adapter
I am Creating LinearLayout with Textview at Runtime and inflating it in each row of RecyclerView
For Example, 1st Row of RecyclerView will have 2 or 3 Textview created at runtime, 2nd Row will have 2 or 3 Textviews created at runtime, 3rd Row will have some Textviews...and so on...
Its working almost Prefect if I check my Log... But when I scroll it down, it just places some textview in wrong places, means I get previous Textviews again when I scroll down in wrong places
#Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
//Movie movie = mItems.get(i);
hm2 = new HashMap<String, ArrayList<PD_Data>>();
sub_rows2 = new ArrayList<PD_Data>();
hm2=categories.get(i);
String key=hm2.keySet().toArray()[0].toString();
sub_rows2=hm2.get(key);
Log.i(LOG_TKT,key);
viewHolder.textview_category.setText(key);
LayoutInflater inflater;
View new_sub_row;
for(int x=0;x<sub_rows2.size();x++){
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
new_sub_row = inflater.inflate(R.layout.recyclerview_pd, null);
TextView heading2 = (TextView)new_sub_row.findViewById(R.id.heading2);
heading2.setText(sub_rows2.get(x).sub_heading);
Log.i(LOG_TKT,sub_rows2.get(x).sub_heading);
TextView detail2 = (TextView)new_sub_row.findViewById(R.id.detail2);
detail2.setText(sub_rows2.get(x).value);
Log.i(LOG_TKT, sub_rows2.get(x).value);
viewHolder.linearlayout_recyclerview_pd.addView(new_sub_row);
}
//viewHolder.imgThumbnail.setImageResource(movie.getThumbnail());
hm2 = new HashMap<String, ArrayList<PD_Data>>();
sub_rows2 = new ArrayList<PD_Data>();
}
What am I doing wrong ?
It is obvious from your question that you aren't familier with how to use RecyclerViews. You need to read up on the subject. Here is a good start.
Basically, onBindViewHolder() is only responsible for binding your data to your viewHolders which hold your item layouts provided by you through onCreateViewHolder(). The reason for that is that RecyclerView recycles your views so it doesn't have to create new views every time you scroll.
In your case, it appears that you would need to use some technique that will tell the RecyclerView to use different viewHolders for different items. See how you can do it here.
I have given answer for better practice of binding data with ViewHolder in another question. You can check it here RecyclerView causes issue when recycling I hope this will help you. This will solve you problem well.
EDIT
Have you solved your problem yet? If not , consider my advice. You know the problem right? suppose you create a ViewHOlder for item 0 and add some text in it. While scrolling suppose this ViewHolder recycled for item number 10, then according to your code it will add new text rows along with some text rows you added for item number 0. You can solve it like
LayoutInflater inflater;
View new_sub_row;
//check here if the linear layout already has previusely added child, if yes remove them
if(viewHolder.linearlayout_recyclerview_pd.getChildCount()>0){
viewHolder.linearlayout_recyclerview_pd.removeAllViews();
}
for(int x=0;x<sub_rows2.size();x++){
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
new_sub_row = inflater.inflate(R.layout.recyclerview_pd, null);
TextView heading2 = (TextView)new_sub_row.findViewById(R.id.heading2);
heading2.setText(sub_rows2.get(x).sub_heading);
Log.i(LOG_TKT,sub_rows2.get(x).sub_heading);
TextView detail2 = (TextView)new_sub_row.findViewById(R.id.detail2);
detail2.setText(sub_rows2.get(x).value);
Log.i(LOG_TKT, sub_rows2.get(x).value);
viewHolder.linearlayout_recyclerview_pd.addView(new_sub_row);
}
first question on SO, forgive me if I forget to include something.
In my activity, I have a function that loads a new activity that has a tabbed ViewPager with two fragments. From what I understand (or rather, from what I can tell) the activity does not load until both tabs have completed their onCreateViews() functions. Currently, this is taking between 500ms-2000ms which makes the application feel rather clunky. I believe this gives me two options:
Have the activity load and display the first tab once the first tab has finished it's onCreateView()
Preferably, speed up the loading of the second tab/fragment. What I'm doing is very slow and I'm looking for a better way to do it.
Here is an excerpt from my code for the second fragment (tab):
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root_view = inflater.inflate(R.layout.stats_layout, container, false);
for (Map.Entry<String, int[]> entry : stats.entrySet()) {
String key = entry.getKey();
int[] value = entry.getValue();
if (value[2] == 1) {
LinearLayout ll_singles = (LinearLayout) root_view.findViewById(R.id.ll_singles_stats);
RelativeLayout rl_detail = (RelativeLayout) inflater.inflate(R.layout.rl_detail, ll_singles, false);
( (TextView) rl_detail.findViewById(R.id.tv_made) ).setText(Integer.toString(value[0]));
( (TextView) rl_detail.findViewById(R.id.tv_total) ).setText(Integer.toString(value[0] + value[1]));
( (TextView) rl_detail.findViewById(R.id.tv_percent) ).setText(MessageFormat.format("{0,number,0.00%}", (float) value[0] / (value[0] + value[1])));
ll_singles.addView(rl_detail);
}
}
Without getting too specific on my entire layout (unless someone asks), I inflate a single RelativeLayout (rl_detail) many (50+) times and add it to four different LinearLayouts (in this excerpt, ll_singles).
I know findViewById() is an expensive action and I have to think there is a way to avoid the findViewById() that I do every time I inflate the exact same view when I change the text for the TextView.
I have explored asynctasks (haven't been able to find an example that inflates views in the background -- it sounds like it isn't possible) and have considered using a ViewHolder, but that seems exclusive to ListViews.
Any ideas?
I am currently populating an Adapter on startup with views inflated from XML using
private void addView(Context context) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.deal_tile, this, null);
mViews.add(view);
}
However, I've found that storing the views in a list inside the AdapterView creates problems with controls within those views, so I want to change over to use the recycling functions in Adapter#getView(int position, View recycle, ViewGroup container).
For this reason I want to use a custom view class so I can do a sanity check (if(recycle!=null && recycle instanceof CustomView)) before I repopulate it in the adapter. However, I can't find out how you inflate a custom view class from XML. I can find out how you add an inflated view to a custom view, I can find out how you insert a custom view into an XML layout, etc, and obviously I am quite happily inflating these things directly using LayoutInflater, but I can't find an equivalent for generating the custom view itself. I want to reuse the XML I already have; consequently I don't want to program in the elements (and how they look) directly.
I used this to create my own slide gallery, i think it would help.
LinearLayout internalWrapper = new LinearLayout(getContext());
internalWrapper.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
internalWrapper.setOrientation(LinearLayout.HORIZONTAL);
addView(internalWrapper);
this.mItems = items;
LinearLayout generalLayout = new LinearLayout(this.getContext());
generalLayout = (LinearLayout) View.inflate(this.getContext(), R.layout.galleryrow, null);
// inside linear layout
LinearLayout generalLinear = (LinearLayout) generalLayout.findViewById(R.id.rowgenerallin);
// set height & width to the LINEAR
generalLinear.setLayoutParams(new LayoutParams(reference_width, reference_height));
ImageView ivl = (ImageView) generalLayout.findViewById(R.id.arrow_left);
ImageView ivr = (ImageView) generalLayout.findViewById(R.id.arrow_right);
internalWrapper.addView(generalLayout);
In my case, R.layout.gallery_row contains the two images I want to manage, nested by a LinearLayous (rowgenerllin), the internal wrapper is an empty LinearLayout declared in the main layout of your activity.
Double check the LayoutParams code or you will get a big NULL :)
Cheers!
I need to get an dynamically added view position in LinearLayout with vertical orientation.
For example i have 4 TextViews added dynamically on LinearLayout, then i need to change position of text colour at 3rd position will be in different color.How can i achieve it by getting position of added views.
You can do it just like that
ViewGroup parent;
int position;
for(int i = 0; i < parent.getChildCount(); ++i) {
int currentViewId = parent.getChildAt(i).getId();
if(currentViewId == wantendViewId) {
position = i;
}
}
That's (in my opinion) the simplest way
If you always know the number of TextViews in your LinearLayout, you can just use the function getChildAt( int position ). This returns a View which you can then cast to a TextView to be able to perform the desired operations.
If you do not know the number of elements you could set the id of each TextView (in order to be able to identify a particular one) and then run through them like this:
for( View view : myLinearLayout )
if( view instanceof TextView && view.getId().equals( idToSearchFor ) )
//Do what needs to be done.
I see following options:
Declare some id's in resources in form of <item type="id">first</item> and assign them to
views in adding to layout, after that use normal findViewById() mechanism
Assign some tags to views you're adding to a layout via setTag method and after that use findViewWithTag mechanism
Remeber position of your views and use them vie getChildAt method
I got simple option.
suppose you add
View v;//any view
linearlayout.addview(v);//add in layout
While u want to modify view.
simpaly remove old view.
linearlayout.removeView(v);
add new update view object
v-updated new view
linearlayout.addview(v);