Android: (Newb Question) Programatically creating views based on xml - android

Sorry for the Newb-ness.
I want to create a list of view elements in a LinearLayout (vertical). I created an xml layout that is a TableLayout called "category_list.xml"
<TableLayout>
<TableRow>
<ImageView />
<TextView />
<CheckBox />
</TableRow>
</TableLayout>
I want to iterate an array, on each iteration create a new TableLayout view and add it to the LinearLayout. The peice I'm missing is creating a new TableLayout based on the above xml.
Something like
TableLayout t = new TableLayout( R.layout.category_list );
Can someone point me in the right direction? Is it better to generate the TableLayout programatically?

Or by using the static View.inflate function
TableLAyout t = (TableLayout) View.inflate(this, R.layout.category_list, null);
Anyway, be carefull with inflating and deleting too many views in your app, as short lived objects leak memory. Consider using an ListView with and Adapter instead.

You want to use a LayoutInflater to "inflate" the xml files. You can get LayoutInflater in an activity by using getLayoutInflater(). Here's how it works (assuming the id of your LinearLayout is "parent"):
LinearLayout parent = (LinearLayout) findViewById(R.id.parent);
LayoutInflater inflater = getLayoutInflater();
TableLayout t = (TableLayout) inflater.inflate(R.layout.category_list, parent);

Related

How can I create Views in xml which I can use for any layout?

When creating an ImageView for example, I know I can create it within a Layout:
Example a LinearLayout:
<LinearLayout...>
<ImageView
android:id="#id/hello_world_id"/>
</LinearLayout>
But can I define an View outside a layout, and then add it to any other layout?
I want to have a RelativeLayout which adds/removes views programmatically and dynamically, so that the RelativeLayout starts off with no views inside it, then I add some, remove some etc. Would there be any way to do this? Or is it better just to have these views already inside some other Layout, and then I add the Layout (whatever it is--containing my view(s)) to my RelativeLayout?
What you are searching for is LayoutInflator
Create a xml file - buttons.xml
<LinearLayout...>
<ImageView
android:id="#id/hello_world_id"/>
In your activity access it by
final LayoutInflater inflater
= (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.buttons,
null);// this is a layout in your master activity
lLayout = (LinearLayout)findViewById(R.id.layout1);
lLayout.addView(itemView);
Hope this helps.

Android: Adding a linearLayout in a LinearLayout from a separate xml file

I got a relative layout which contains another relative layout which I used to replace the "title", a linearLayout which I will use later as a "control panel", and a horizontalScrollView, where the horizontalScrollView contains a LinearLayout(let's name this linear layout - "hsc".
I also have another xml layout file named "entries" that contains an imageView.
My question is, how do i attach "entries" inside "hsc"? Or how to I populate "hsc" with multiple "entries"?
My main layout's structure looks something like this:
<RelativeLayout>
<relativeLayout1>
<linearLayout>
<horizontalScrollView1>
<hsc>
Thanks!
Try to use LayoutInflater. First get the hsc in code somehow like this
LinearLayout layout = (LinearLayout) findViewById(R.id.hsc_id);
Then you make new entrie
LayoutInflater inflater = (LayoutInflater)context.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
View entrie = inflater.inflate(R.layout.entries,
null, false);
and put one into another
layout.addView(entrie);
you can add multiple views by repeating child view creation process.
If your are going to populate the view, you may want to use a ListView (FragmentList or ListActivity).
In which case you use the tag
<RelativeLayout>
<relativeLayout1>
<linearLayout>
<horizontalScrollView1>
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
And then load the list with an Adapter.
http://www.vogella.com/articles/AndroidListView/
Your question seem to imply that you some-how need to traverse the xml tree, you don't, you just use android:id to find the resource from the code side.
create a linear layout dynamically and add some view in that.....
LinearLayout layoutContainer=new LinearLayout(your_activity.this); //create a linear layout dynamically
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.RIGHT;
layoutContainer.setLayoutParams(lp);//apply attributes to your linear layout
View viewOther = LayoutInflater.from(your_activity.this)
.inflate(R.layout.layout_to_add, layoutContainer);//add some view to your linear_layout.
hope it helps....!

The best way to inflate view programmatically

I found a simple SwipeSample that I changed to allow me to create new xml layouts and inflate the main layout to display them. What I wanted to do was also be able to programmatically add layouts for the swipe process.
I have the main.xml layout and a red.xml and yellow.xml which are a simple linearlayout with a textview set to a solid color.
The code below works but I don't think that it's correct or the best way to do what I'm trying to get.
If anyone can suggest a better way that would be greatly appreciated.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Create a layout with a solid blue background programmatically
TextView tv1 = new TextView(this);
tv1.setText("Blue");
tv1.setBackgroundColor(Color.BLUE);
tv1.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
ll.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
ll.addView(tv1);
//Create a layout with a solid green background programmatically
TextView tv2 = new TextView(this);
tv2.setText("Green");
tv2.setBackgroundColor(Color.GREEN);
tv2.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
LinearLayout ll2 = new LinearLayout(this);
ll2.setOrientation(LinearLayout.VERTICAL);
ll2.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
ll2.addView(tv2);
//inflate the flipper view and add the yellow and red xml layouts and also the 2 programmatically created layouts
fSpace = (ViewFlipper)findViewById(R.id.flipper);
inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.yellow, fSpace);
inflater.inflate(R.layout.red, fSpace);
fSpace.addView(ll);
fSpace.addView(ll2);
}
If you have a complex layout that you want to create programmatically, it might be easiest to have the layout premade in xml and then just inflate it and add it at runtime.
Create view in xml
Here is a sample premade xml layout that is in the layout folder. Yours could be anything, a single view or a whole complex layout.
layout/my_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayout1"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/TextView1"
android:text="This is a TV"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/TextView2"
android:text="How are you today?"/>
</LinearLayout>
Make a container for your view
Have some place it put your view in your activity layout. You could have something like this.
<FrameLayout
android:id="#+id/flContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</FrameLayout>
Inflate the view
Use get a reference to the container, inflate your view from xml, and then add it to the container.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FrameLayout container = (FrameLayout) findViewById(R.id.flContainer);
View inflatedLayout= getLayoutInflater().inflate(R.layout.my_view, null, false);
container.addView(inflatedLayout);
}
Doing it like this keeps your code a lot cleaner.
See also:
How to inflate one view with a layout
Add a View to a wrapper multiple times with inflate
The way you inflate R.layout.yellow and R.layout.red is indeed the right way to do so. You may be able to simplify your code by moving a lot of it over to xml. I assume tv1 is just a sample? if not, it could go into main.xml. You may even find a way to create yellow and red with a single inflation... depending on what you're doing.
Programmatically creating views is just, for the most part, slightly tedious.

android nested listview

is it possible/advisable to have a nested listview?
i.e. a listView that's contained within a row of another listview?
an example would be where my main list is displaying blog posts, and then in each row, you'd have another list view for the comments for each post (that would be collapsible)
I had the same problem today, so this is what I did to solve it:
I have a ListView, with a CustomAdapter, and on the getView of the customAdapter, I have something like this:
LinearLayout list = (LinearLayout) myView.findViewById(R.id.list_musics);
list.removeAllViews();
for (Music music : albums.get(position).musics) {
View line = li.inflate(R.layout.inside_row, null);
/* nested list's stuff */
list.addView(line);
}
So, resuming, It's not possible to nest to ListViews, but you can create a list inside a row using LinearLayout and populating it with code.
Is what you're looking for the ExpandableListView? Of course, that's limited to only two levels of listings (but that sounds like it would work for your needs).
This sound like what you're looking for? If you're not, or if this doesn't work, I would suggest having two list views: one of, say, blog posts, and the second of comments, and an action on a blog post item takes you to the second view, populated with the relevant comments.
you can do it like this :
inside the parent listview row xml layout add the following table layout
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/table_show"
android:background="#beb4b4">
</TableLayout>
then you have to make a layout for the child list with name reply_row.xml
<?xml version="1.0" encoding="utf-8"?>
<TableRow android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/tv_reply_row"
android:textColor="#000"/>
</TableRow>
in your parent listview adapter getview method add the following code :
TableLayout replyContainer = (TableLayout)
// vi is your parent listview inflated view
vi.findViewById(R.id.table_show);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//child listview contents list
String [] replys = {"a","b","c","d"};
for (int i=0;i<replys.length;i++)
{
final View comments = inflater.inflate(R.layout.reply_row, null);
TextView reply_row = (TextView) comments.findViewById(R.id.tv_reply_row) ;
reply_row.setText(replys[i]);
//for changing your tablelayout parameters
TableLayout.LayoutParams tableRowParams=new TableLayout.LayoutParams
(TableLayout.LayoutParams.FILL_PARENT,TableLayout.LayoutParams.WRAP_CONTENT);
int leftMargin=3;
int topMargin=2;
int rightMargin=3;
int bottomMargin=2;
tableRowParams.setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
comments.setLayoutParams(tableRowParams);
TableRow tr = (TableRow) comments;
replyContainer.addView(tr);
}
You'd better use one ListView, not nested. Nesting ListView is an inefficient way. Your ListView may not scroll smoothly and take up more memory.
You could organize your data structure to show nested data in one ListView. Or you can use this project PreOrderTreeAdapter.
It is convenient to show nested data in ListView or RecyclerView. It can be used to make ListView or RecyclerView collapsible, just change the way you provide your data than notify the adapter.

Setting number of columns programmatically in TableLayout

I have an XML layout which contains a TableLayout with an unknown number of TableRows...
The number of Rows will be established durin runtime, what I do know though is that I want two columns...
So I have a couple of questions regarding this :
- is there a way to set the whole TableLayout to have 2 columns ?
- is there a way programmatically to give an id to the (during runtime) created TableRows which will be placed within the TableLayout, so I can reference them later on from other parts of the software ?
You can build your table rows via XML parts and LayoutInflater. Say you had this as your table_cell.xml:
<TextView android:id="#+id/text"
android:text="woot" />
And this as your table_row.xml (unless you're doing something fancy with your TableRow, you may not need to put it in it's own XML file, and instead just create it programmatically. The result will be the same):
<TableRow />
Assuming your TableLayout reference was called "table", you could do something like this:
TableLayout table = (TableLayout)findViewById(R.id.table);
LayoutInflater inflater = getLayoutInflater();
for(int i = 0; i < 5; i++) {
TableRow row = (TableRow)inflater.inflate(R.layout.table_row, table, false);
View v = (View)inflater.inflate(R.layout.table_cell, row, false);
row.addView(v);
v = (View)inflater.inflate(R.layout.table_cell, row, false);
row.addView(v);
// you can store your reference to `row` here for later use
table.addView(row);
}
With this technique, you can still set up your layout in XML, making it easier to read/organize/edit, and you still have programmatic control over how many columns and rows are in the table. You can also store references to each table row for later use.

Categories

Resources