I have the same View inflated (from XML) multiple times. When I call findViewById(R.id.my_layout).setVisibility(View.GONE) I want to apply it on all such views.
How do I do that?
There isn't a version of findViewById() that returns all matches; it just returns the first one. You have a few options:
Give them different ids so that you can find them all.
When you inflate them, store the reference in an ArrayList, like this:
ArrayList<View> mViews = new ArrayList<View>();
Then when you inflate:
LayoutInflater inflater = getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mViews.add(inflater.inflate(R.layout.your_layout, root));
Then when you want to hide them:
for (View v : mViews) { v.setVisibility(View.GONE); }
Depending on what you're doing with these Views, the parent layout may have a way of accessing them. E.g., if you're putting them in a ListView or some such. If you know the parent element you can iterate through the children:
ViewGroup parent = getParentSomehow();
for (int i = 0; i < parent.getChildCount(); ++i) {
View v = parent.getChildAt(i);
if (v.getId() == R.id.my_layout) {
v.setVisibility(View.GONE);
}
}
If the above options don't work for you, please elaborate on why you're doing this.
Modify on the View that holds the inflated layout.
E.g:
If you have
View v = inflater.inflate(.... );
you change the visibility onto this view. v.setVisibility(View.GONE);
Related
I am trying to set the visibility of some views as gone after layout inflation but it doesn't work. If I try to access the tag of the view , I can clearly see that I am accessing the right view. This code doesn't result to any errors, so I am trying to understand why it's not working.
I am passing in as parameters the resource ids for the views (hideView) and the layout(layout):
public void hideViews(String title, ArrayList<Integer> hideView, int layout){
final LayoutInflater factory = getLayoutInflater();
final View originalView = factory.inflate(layout, null);
for (int i = 0; i < hideView.size(); i++) {
View view = originalView.findViewById(hideView.get(i));
if (title.equals("Admin") || title.equals("Manager")){
view.setVisibility(View.VISIBLE);
}else{
view.setVisibility(View.GONE);
}
}
}
originalView is not attached to your layout.
Either provide the parent view where you want to inflate this layout
Or add originalView as a child of other attached view after inflating.
Let's assume that this is your parent view
ViewGroup parentView = (ViewGroup)findViewById(R.id.parentView);
Solution 1
Replace this:
final View originalView = factory.inflate(layout, null);
With:
final View originalView = factory.inflate(layout, parentView);
Solution 2
Add this:
parentView.add(originalView)
I am trying to add multiple relative layouts to a Linear layout. I am using the following lines of code.
LayoutInflater inflator = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout item = (LinearLayout)findViewById(R.id.reviews);
for(int i=0 ; i<2 ; i++){
View child = inflator.inflate(R.layout.review_item, null);
child.setId(i);
child.setTag(i);
item.addView(child);
}
But I can only see one child view. Can anyone tell me where I am going wrong.
Declare the LinearLayout item outside of the for loop.
The way you're doing it the variables value will be overwritten each time you run through the for loop. So your method should look like this:
public void somemethod(){
LayoutInflater inflator = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout item = (LinearLayout)findViewById(R.id.reviews);
for(int i=0 ; i<2 ; i++)
{
View child = inflator.inflate(R.layout.review_item, null);
child.setId(i);
child.setTag(i);
item.addView(child);
}
}
You need to take the first two lines outside of the for loop. You're inflating the LinearLayout twice, which overrides the first layout you inflate, rather than adding to it. By putting those two lines before the for loop starts, you'll add both child views to a single LinearLayout.
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
I just wrote an answer for someone confused by findViewById and I realised that I have a gap in my understanding. This question is for knowledge and curiosity only.
Consider this:
button = (Button)findViewById(R.id.button);
findViewById returns an instance of View, which is then cast to the target class. All good so far.
To setup the view, findViewById constructs an AttributeSet from the parameters in the associated XML declaration which it passes to the constructor of View.
We then cast the View instance to Button.
How does the AttributeSet get passed in turn to the Button constructor?
[EDIT]
So I was the confused one :). The whole point is that when the layout is inflated, the view hierarchy already contains an instance of the view descendant class. findViewById simply returns a reference to it. Obvious when you think about it - doh..
findViewById does nothing. It just looks through view hierarchy and returns reference to a view with requested viewId. View is already created and exists. If you do not call findViewById for some view nothing changes.
Views are inflated by LayoutInflator. When you call setContentView xml layout is parsed and view hierarchy is created.
attributes passed to Button's constructor by LayoutInflater. check LayoutInflator source code.
I don't think findViewById() constructs or instantiates a View. It will search in View hierarchy of already inflated layout, for a View with matching id.This method works differently for a View and for a ViewGroup.
from Android Source code:
View.findViewById() returns the same View object if this view has the given id or null, it calls:
protected View findViewTraversal(int id) {
if (id == mID) {
return this;
}
return null;
}
ViewGroup.findViewById() iterates through child views and calls same method on these Views, it calls:
protected View findViewTraversal(int id) {
if (id == mID) {
return this;
}
final View[] where = mChildren;
final int len = mChildrenCount;
for (int i = 0; i < len; i++) {
View v = where[i];
if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
v = v.findViewById(id);
if (v != null) {
return v;
}
}
}
return null;
}
Say I have a LinearLayout with some elements in it as an .xml file.
In Java, I need to somehow "clone" it a few times into an array, edit some of its children, and then loop through the array, adding each LinearLayout to my main view.
What do you think would be the correct way to "clone" this layout from an xml file into an array element in java?
Thanks!
LayoutInflater vi = (LayoutInflater) myContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.yourLayoutId, null);
you can do some thing like this to inflate the view, and then modify the element iside the view using the findViewById method. Hope this will help
Something like this:
....
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout layout = null;
for(....) {
layout = (LinearLayout) inflater.inflate(R.layout.YOUR_LAYOUT_ID, null);
someList.add(layout);
}
.....
Try getting the layout in a variable:
for (int c=0; c < count; c++)
{
LinearLayout layout = (LinearLayout) findViewById(R.id.yourmainlayout);
// do something with layout
// assign layout to a variable or add it on another layout
}