XML dynamic creation - android

I want to create a XML layout dynamically but I had a question on doing so.
Say I have something like this (Looking at the layout from the "Outline" perspective):
-ScrollView
---Linear Layout(Vertical) (LL1)
-------Linear Layout(Horizontal) (LL2)
-----------Image View (IV1)
-----------Linear Layout(Vertical) (LL3)
---------------TextView
---------------TextView
So my question here is would I start with the most inner Layout (LL3) and add the 2 TextViews and then branch upwards (to LL2 then LL1 then ScrollView) with adding to the other views & layouts?

I believe you can do this several ways. I've not tried creating an entire hierarchy like this dynamically, but I've added buttons, radio-buttons, text-views and other Views this way several times. In those cases, I've just added new ones to the ones that already exist using AddView().
I think the easiest way is to just create it "top down", i.e. create the ScrollView first and add any settings, then add the other views to it downwards. I would typically do something like this:
// Call other methods to create the views first:
ScrollView myScrollView = createMainScrollView();
LinearLayout myHorizontalLayout = createLinearLayoutForAbc();
LinearLayout myOtherLayout = createLinearLayoutForXyz();
TextView myFirstTxt = (...)
(..etc..)
Now populate them in the right way:
myScrollView.addView(myHorizontalLayout);
myHorizontalLayout.addView(myOtherLayout);
(..etc..)
Note:
I do believe this should work, but I can not guarantee it; if the reference to an inner view is no longer correct after having been added to an outer view (Eg. myHorizontalLayout is no longer a valid ref to the actual view under myScrollView), you might not be able to add children to that inner view. Not sure about this, though.
(If so, you might try to fetch a new, correct reference using findViewByName() after adding each view, but I don't think that would be an optimal solution).
I would try the first way first - at least make a proof of concept, to see that you can add view in a hierarchy at least three levels deep. That should give you your answer. If it does not work, I suppose I would try adding them in the opposite order, as you suggest in your question, just to see if that works (maybe just switch the order in my second code block?).
Sorry for the imprecise answer, hope it is of some help anyway.

Related

How to convert a group of TextView to EditText in android without ViewSwitcher?

ViewSwitcher can be used only for two childs in it. But for a group of textviews to be converted to Edittexts what can be the ways?
It's easy enough to replace views for other views but converting - I don't think so.
To replace views, you can simply do something like the following:
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.edit_texts_layout, null);
viewSwitcher.removeAllViews();
viewSwitcher.addView(view.findViewById(R.id.first_edit_text));
viewSwitcher.addView(view.findViewById(R.id.second_edit_text));
So what's going on here?
1) You create a layout called edit_texts_layout which contains two EditText's with the ID's: first_edit_text and second_edit_text.
2) You then inflate this in your Activity or Fragment.
3) You then remove all of the existing views in your ViewSwitcher since, as you rightfully said, there can only ever be two views in a ViewSwitcher.
4) You then add the two EditText's inside that ViewSwitcher by view.findViewById()
Also...
It would be wise to have another layout called text_views_layout and do the exact same thing so that you can switch the EditText's with the TextView's.
But why have the EditText's inside a layout and not create them programmatically?
Good question. Views should live in layouts and live separately from code when possible. It makes life easy where you can work with a view in a layout since you have XML autocomplete and the preview screen so you know exactly what the view looks like - saving you from any nasty surprises later on.
Are there any other alternatives to this?
There's always more than one way to skin a cat and this situation is no different. You could possibly create TWO ViewSwitcher's and with different child views. What you'd have to do then is toggle the visibility to View.GONE and View.VISIBLE alternatively. The caveat? It'll be troublesome to maintain both in memory and to perform any operations on the child views as you'd have to remember which one is visible and which one isn't. With my original answer, you won't have to worry.

define a recurrent set of views to use multiple time in the same layout

I'm working on an android project where I have a set of views (2 TextViews and some checkboxes in a checkbox group) to replicate many time in the same activity.
Is it possible to define the layout only for one set and instantiate it many time?
Also, the views are grouped in a Relative layout, is it possible to position the without the id attributes (to avoid id duplication)?
I would use a ListView for this. Even if you got like 5 items it workd fine. If you got many more items it still works perfect. Take a look at this example.
You can do this by defining the fields you want to reuse in their own xml. you can then use the 'include' tag for where you want them to display.
http://developer.android.com/training/improving-layouts/reusing-layouts.html
You do need to define the id's to position them in the relative layout. What is your concern about replicating the id's.
The other thing worth mentioning is how to use findById() when using 'include'. You can put a id on the include tag (which is effectively the relative layout viewgroup). Find that group first (Cast to viewgroup) and then do a findbyId on that group for what ever view you are after.

Orientation change: children of LinearLayout can't have #+id/something

Cross posting from Android Google group
I ran into this issue earlier today:
https://code.google.com/p/android/issues/detail?id=55106
The problem is:
LinearLayout has children
every child is inflated from the same XML layout file
a child has nested element with some ID.
The ID is used to call findViewById(ID) to set some value
Everything is displayed properly on startup, but after orientation change every child of LinearLayout displays the value of the last data item
As soon as ID is removed from the child XML layout file, everything starts working properly
The bug has the sample project attached that demonstrates the problem.
Just wanted to ask if somebody has experienced the same issue and knows a workaround?
Thank you in advance.
EDIT:
The situation with LinearLayout is pretty flaky. I finally made the project work - see the second attached project at
https://code.google.com/p/android/issues/detail?id=55106
If you go to item_main.xml and change android:textIsSelectable from false to true, the bug shows up.
Keep android:textIsSelectable="true", but remove android:id="#+id/text" - the bug disappears again
The main reason I was experimenting with this LinearLayout is because I wanted to follow thy layout animation sample.
http://developer.android.com/training/animation/layout.html
But it seems the situation is so unstable with LinearLayout and orientation change that I need to go back to the working ListView+Adapter approach and figure out how to do similar layout animations when adding items to the adapter and revalidating the list.
Another workaround is removing all views from your LinearLayout in onSaveInstanceState method.
#Override
protected void onSaveInstanceState(Bundle outState) {
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.yourLinearLayoutId);
linearLayout.removeAllViews();
super.onSaveInstanceState(outState);
}
Do you have any particular reason why you are inflating 50 children layouts and then inserting them into a ScrollView instead of using an AdapterView?
It seems to me like you should probably be using ListView with some sort of Adapter that will handle the row inflating and data binding for you, which will result in not only improved efficiency and performance but will let you avoid this "bug" which you are encountering.
Any time you are inflating Views within a loop it should be a strong hint that you ought to re-consider your approach and start using an AdapterView of some sort (ListView, Gallery etc...)
When you add a number of TextViews and re-use the same id for them (android:id="#+id/text") my best guess would be that you're stumbling on unexpected behavior (at best) once you invoke the findViewByID method. To do what you apparently want to do (use a list of TextViews you could be doing something like what was proposed here, i.e. create an array of TextViews, instance them and keep them for internal reference.
What you found isn't actually a bug, it's behaving like it should: all the TextViews have the same id, so all will change at the same time.
I looked up the actual reference in the documentation (emphasis mine):
An ID need not be unique throughout the entire tree, but it should be
unique within the part of the tree you are searching (which may often
be the entire tree, so it's best to be completely unique when
possible).

How to list all dynamically created views in an activity?

I'd like to see all the dynamically created Buttons, TextViews, etc before (or even after) setContentView() shows them on the screen. I have a loose understanding that this relates to the Context and the Activity, but concretely I don't know where these dynamic views exist / how they are put together at runtime.
And if they are shown at runtime is there a way to list all of them?
LinearLayout layout = new LinearLayout(this);
layout.addView(button1);
layout.addView(button2);
layout.addView(button3);
setContentView(layout);
The buttons SHOULD exist somewhere (I am so sure they exist in the Context!!) but there is no way (that I have found) of locating these dynamically created views.
Please and thanks.
In general, if you are going to need to display these kinds of things on the screen, then you should keep a reference to them somewhere. This is a common pattern, if you dynamically create a button, you need to stuff them in a List (for example). You shouldn't need to get all the views if you program like this, and even if you easily could (typically in GUIs, you can, either by reflection, or something equally tacky mechanism) it wouldn't be organized in any kind of logical structure that would relate the things in the layout to the logical layout dictated by the application. So instead, when you dynamically create views, stuff them somewhere like a list so you can iterate through it later.

android repeater-like functionality

is there any type of 'repeater' type functionality in android? I have a relative layout (inside a row in a listview) and inside that I'd like to have a series of TextViews be displayed one after the other (as if they are child rows in the listview row). The issue is that the number of those "child rows" will vary. is there any way to do this, or should i just create the TextView objects in code, and programatically add them to a linear or table layout?
The closest thing (besides ListView/ListAdapter, naturally) that I can think of offhand is ViewSwitcher and ViewSwitcher.ViewFactory, but there's really nothing magical there: it's an interface that you can call to get a view.
Since it's only one line to get a view and add it to your current hierarchy anyways, though (View.inflate(context, R.layout.somelayout, myContainerViewGroup)) it feels silly to go with something heavier, but if you feel better wrapping that up in a Factory of some sort, check the AOSP source for ViewSwitcher.
One option is TextViews support Multi-line text. So you could create the text with a StringBuilder using "\n" for new lines, and not have to worry about multiple text views.

Categories

Resources