I want to get a a childView whose name is "name" inside a ViewGroup. I knew that the nameView is the second item inside the GroupView, so I used following code:
TextView nameView = (TextView)((ViewGroup)view).getChildAt(2); //2 is magic number
However, it is possible that ,in the future, I might add some other Views before the nameView and above code will became invalid. So, I am wondering how could get the ChildView by name, something like:
TextView nameView = (TextView)((ViewGroup)view).getChildByID(R.id.name);
EDIT: thanks to kcoppock. I realize getChildByName("name") does not make sense. So i will purse something like getChildByID.
You method are looking for is View.findViewById(id). Per your example:
TextView nameView = (TextView) view.findViewByID(R.id.name);
(It is not necessary to cast to ViewGroup)
Barry
If you just need to find a particular child of a ViewGroup by its ID, just first get a reference to the ViewGroup:
ViewGroup vg = (ViewGroup)findViewById(R.id.myGroupLayout);
Then call findViewById() on that ViewGroup:
View v = (TextView)vg.findViewById(R.id.name);
Related
I have inflated one layout in my Activity now in that Activity I have some common fields for multiple times, so I have created one more layout with those common fields and included in my layout.And I got inflated all those fields.But now My problem is that While I am inserting data in those fields only first included fields gets inserted with data not the second, third, and so on... So how to get data inserted in such fields with common ids..
LayoutInflater inflater = LayoutInflater.from(getContext());
View w4FragmentRowView = inflater.inflate(R.layout.weekly_report4_row_item, null);
etWhere = (EditText)w4FragmentRowView.findViewById(R.id.et_weekly_reports_where_w4_tab);
etHowSubStd = (EditText)w4FragmentRowView.findViewById(R.id.et_weekly_reports_how_sub_std_w4_tab);
Now I have to insert data multiple times in same activity with these edit Text fields.
Say you have two views and they have common ids and you inflate them
Like shown below
now for common ids when you are doing find view by id make sure
the point to right parent
//look at item and item2 as while finding view
LinearLayout item = (LinearLayout) mLayoutInflater.inflate(
R.layout.layout1, null);
TextView skunitNameTextView = (TextView) item.findViewById(R.id.textView);
LinearLayout item2 = (LinearLayout) mLayoutInflater.inflate(
R.layout.layout1, null);
TextView skunitNameTextView2 = (TextView) item2.findViewById(R.id.textView);
i think this should solve your problem
Take example you have a layout file with name "reuse.xml" where you have only one view TextView with id "txv".
Now in your Activity you are inserting this layout file multiple times like:-
TextView tv1 = (TextView) mLayoutInflater.inflate(
R.layout.reuse, null);
tv1.setId(R.id.txv_activity_1);
TextView tv2 = (TextView) mLayoutInflater.inflate(
R.layout.reuse, null);
tv2.setId(R.id.txv_activity_2);
TextView tv3 = (TextView) mLayoutInflater.inflate(
R.layout.reuse, null);
tv3.setId(R.id.txv_activity_3);
Now you are using the same layout file but they gave different id so you can easily update any of file which one you want.
But if you are using the same layout more than 3-4 times it is recommended to use it as ListView or RecyclerView item, which also provide you better performance in case of large layout and easy to maintain.
My intent is to inflate numerous instances of the same view on a LinearLayout, and then modify their views accordingly. However, whenever I inflate a view multiple times, I always end up with the same reference to the first inflated view.
Simplified example:
View v = getActivity().getLayoutInflater().inflate(R.layout.inflatable_layout,rootLinearLayout,true);
TextView t = (TextView) v.findViewById(R.id.text1);
t.setText("Foo");
View v2 = getActivity().getLayoutInflater().inflate(R.layout.inflatable_layout,rootLinearLayout,true);
TextView t2 = (TextView) v2.findViewById(R.id.text1);
t2.setText("Bar");
By doing this, I end up with two inflated views. However, the first view's TextView contains "Bar", and the second one unaltered.
Is there a way to be able to maintain reference to the views I inflate individually?
To solve your problem, just change:
View v = inflater.inflate(R.layout.inflatable_layout,rootLinearLayout,true);
to
View v = inflater.inflate(R.layout.inflatable_layout,rootLinearLayout,false);
rootLinearLayout.addView(v1);
Note that you now have to add the view manualy to your layout.
(Do the same for v2)
This way you should receive two different references.
Please try this:
View v = getActivity().getLayoutInflater().inflate(R.layout.inflatable_layout,null); // Note the null replacing the "ViewGroup"
TextView t = (TextView) v.findViewById(R.id.text1);
t.setText("Foo");
View v2 = getActivity().getLayoutInflater().inflate(R.layout.inflatable_layout,null); // Note the null replacing the "ViewGroup"
TextView t2 = (TextView) v2.findViewById(R.id.text1);
t2.setText("Bar");
// Manually append each layout to your linear layout.
I think this should work, as no root is defined
I have a ListView that I add a headerView as below. When the user clicks a button, I attempt to update a TextView that is inside the ListView's header View
if(mHeaderView == null){
mHeaderView = (LinearLayout) activity.getLayoutInflater().inflate(R.layout.header_report, listViewReports, false);
}
TextView textViewName = (TextView) mHeaderView.findViewById(R.id.report_header_name);
textViewName.setText(student.getFullName();
The TextView only updates if the TextView changes size - for example if the student.getFullName() returns a longer name causing the textView to wrap to another line.
I have tried invalidating textViewName and mHeaderView. Also I have tried having textViewName as a class variable. Neither have worked.
What would be the proper way to achieve this?
Store reference to the header text that was originally used when creating the Header. Then just call the setText when needed.
I have an activity in which I need to add LinearLayout dynamically, by code (because it depends on the user input).
So, here is what I have done:
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout lyt = (LinearLayout) inflater.inflate(R.layout.row_edit, mLytRows);
TextView tvName = (TextView) lyt.findViewById(R.id.name_textview);
tvName.setText(user.getName());
where R.layout.row_edit is a LinearLayout in which there are some Views, including a TextView, whereas mLytRows is a referenced LinearLayout (defined in the XML of the UI), in which I want to add the row_edit layout.
Based on the user input, I repeat this code several times and here is the problem:
when I try to reference the TextView, I aways get the TextView of the first LinearLayout I have added.
Why? How can I solve it, please?
Take a closer look at the documentation.
If you specify the second argument in inflate(), the method returns the parent, not the inflated View.
Hence, lyt is always your parent and findViewById always returns the first element it finds with the R.id.name_textview ID.
You might want to do
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout lyt = (LinearLayout) inflater.inflate(R.layout.row_edit, null);
TextView tvName = (TextView) lyt.findViewById(R.id.name_textview);
tvName.setText(user.getName());
mLytRows.addView(lyt);
And in ViewGroup you can see there are several addView methods to place the view where you want.
In your res/layout/my_image_layout.xml
<LinearLayout
android:id="#+id/buttons"
...>
<ImageView ...
</ImageView>
</LinearLayout>
To grab that Layout by its #+id value inside your app/src/java/MyClass.java code, do this:
String myLinearLayoutName = "buttons";
LinearLayout myLinearLayoutID2 = (LinearLayout) activity.findViewById(activity.getResources()
.getIdentifier(myLinearLayoutName, "id", activity.getPackageName()));
/*Bottom code changes that LinearLayout's background to a different image. "bomb" (R.mipmap.bomb) is the name of an image I have in my drawable folder. */
myLinearLayoutID2.setBackgroundResource(R.mipmap.bomb);
I have a LinearLayout with many nested LinearLayouts and TextViewss
My main activity inflates the main LinearLayout,
Then I load data from a server and based on the data received, I add multiple Layouts in a place holder (LinearLayout)
This is simple a news page where I load Images associated with the news and place it inside an initially empty LinearLayout.
Each Image has the following info: Title(TextView), Date(TextView), Image(ImageView) so what I actually do is the following:
*Please notice that this is only the essential coded in the question I elemenated all the try -> catch ... if/else ....etc
public void addImages(JSONArray images){
ViewGroup vg = (ViewGroup) findViewById(R.id.imagesPlaceHolder);
// loop on images
for(int i =0;i<images.length;i++){
View v = getLayoutInflater().inflate(R.layout.image_preview,vg);
// then
I think that here is the problem
ImageView imv = (ImageView) v.findViewById(R.id.imagePreview);
TextView dt = (TextView) v.findViewById(R.id.dateHolder);
TextView ttl = (TextView) v.findViewById(R.id.title);
// then
dt.setText("blablabla");
ttl.setText("another blablabla");
// I think the problem is here too, since it's referring to a single image
imv.setTag( images.getJSONObject(i).getString("image_path").toString() );
// then Image Loader From Server or Cache to the Image View
}
}
The code above works good for a single image
But for multiple images the Image Loader doesn't work I guess it's because all ImageViews (Inflated multiple times) have the same ID
When you provide a ViewGroup to be used as the parent, the View returned by inflate() is this parent (vg in your case) and not the newly created View. Therefore, v points toward the ViewGroup vg and not toward the newly created View and as all of your children have the same id, the same subviews (imv, dt, ttl) are returned each time.
Two solutions. The first one is to change their id right after you are finished with them, before the next iteration. Therefore, on the next creation at the beginning of the next iteration, the newly created Views will have a different IDs from the older Views because they will still use the old constant defined in R.
The other solution would be to add the parameter false to the call to inflate() so that the newly created view will not be attached to the ViewGroup and will then be returned by the inflate() function instead of the ViewGroup. The rest of your code will then works as attended with the exception that you will have to attach them to the ViewGroup at the end of the iteration.
Notice that you still need to provide a ViewGroup because it will be used to determine the value of the LayoutParams.
I had the same problem, and based on the answer from #SylvainL, here'a a working solution:
// myContext is, e.g. the Activity.
// my_item_layout has a TextView with id='text'
// content is the parent view (e.g. your LinearLayoutView)
// false means don't add direct to the root
View inflated = LayoutInflater.from(myContext).inflate(R.layout.my_item_layout, content, false);
// Now, before we attach the view, find the TextView inside the layout.
TextView tv = (TextView) inflated.findViewById(R.id.text);
tv.setText(str);
// now add to the LinearLayoutView.
content.addView(inflated);
Is there a reason why the ImageView in the layout XML needs to have an ID? Could you erase the android:id attributes from the image_preview.xml layout and then simply iterate through the children of the inflated LinearLayout? For example:
ViewGroup v = (ViewGroup)getLayoutInflater().inflate(R.layout.image_preview,vg);
ImageView imv = (ImageView) v.getChildAt(0);
TextView dt = (TextView) v.getChildAt(1);
TextView ttl = (TextView) v.getChildAt(2);
I inflate XML-Layout with dynnamic and get text of id
private val onAddView = View.OnClickListener {
val parent = viewForm.findViewById<LinearLayout>(R.id.layout_parent)
LayoutInflater.from(activity).inflate(R.layout.layout_child, parent) // layout_child has id "tv_attribute"
}
private val onSave = View.OnClickListener {
val parent = viewForm.findViewById<LinearLayout>(R.id.layout_parent)
for (i in 0 until parent.childCount) {
val getText = parent.getChildAt(i).findViewById<TextView>(R.id.tv_attribute).text
}
}