The best way to inflate view programmatically - android

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.

Related

Adding a widget in scrollView programmatically

I am having trouble adding a view in the scrollview. The structure of my xml is
// xml_layout.xml
<ScrollView>
<LinearLayout
android:id="#+id/container"
>
<LinearLayout>
<ListView
...
/>
</LinearLayout>
******Here I am trying to add an item *********
</LinearLayout>
</ScrollView>
I am trying to add a textview at the bottom programmatically as follows.
TextView v = new TextView(getActivity());
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
v.setText("TEST View");
v.setLayoutParams(params);
LinearLayout container = (LinearLayout) LayoutInflater.from(getActivity()).inflate(R.layout.xml_layout, null).findViewById(R.id.container);
container.addView(v, 1);
The goal I am trying to achieve is making a tablelayout that contains two columns with the title and listview in the second column. Before I do this, I tried to display a simple textview so that I know I can add a widget. I have tried many different ways but did not work. Is there something wrong with my code??
you must first verify that your LinearLayout 'container' is 'vertical ' orientation, and...
LinearLayout container = (LinearLayout) findViewById(R.id.container);
container.addView(v);

Problems Adding TextView Programmatically Without Erasing Views in XML - Android

I'm trying to add a TextView programmatically, and it has proved immensely difficult. I have found code that works here (added to onCreate):
LinearLayout thisLayout = new LinearLayout(this);
setContentView(thisLayout);
TextView dynamicTextView = new TextView(this);
dynamicTextView.setText("Dynamically Added TextView");
thisLayout.addView(dynamicTextView);
The problem is that this erases all of the views I had created in the XML. There is a popular question with a highly upvoted answer HERE. Based on that, I created this:
LinearLayout myLayout = findViewById(R.layout.activity_main);
TextView tv = new TextView(this);
tv.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT));
tv.setText("Trying Again");
myLayout.addView(tv);
But there is an error on this line:
LinearLayout myLayout = findViewById(R.layout.activity_main);
I try to cast it like this, which silences the error, but immediately crashes:
LinearLayout myLayout = (LinearLayout) findViewById(R.layout.activity_main);
I'm curious what I'm doing incorrectly. I realize that there are many similar questions out there, but none of them seem to work and many point to the answer I connected here. The problem I'm having is that the answer just doesn't work at all. Also, I'm in the process of familiarizing myself with the Android environment so if there's anything I'm doing that seems "off", please point it out.
Here's my XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="lowri.morepractice.app.MainActivity">
<EditText android:id="#+id/edit_message"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="#string/edit_message" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/button_send"
android:onClick="sendMessage"/>
</LinearLayout>
For anyone else who comes here, I also had to change the layout params to this:
tv.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
You can't request the layout by id. It doesn't point to the LinearLayout.
To actually get the LinearLayout you have to add an id to it
<LinearLayout
android:id="#+id/edit_linearlayout"
....
and request that like:
LinearLayout myLayout = (LinearLayout) findViewById(R.id.edit_linearlayout);
To add the the TextView you have to set the LayoutParams like in the question you posted. Doesn't have to be FILL_PARENT of course:
TextView tv = new TextView(this);
tv.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT));
tv.setText("Trying Again");
myLayout.addView(tv);
The error is because you are looking for an XML file in your resources.
Try this,
In your code:
LinearLayout myLayout = (LinearLayout) findViewById(R.id.layout_main);
In your XML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/layout_main"
android:layout_width="match_parent"
You are using the xml and the LinearLayout wrong.
1- call this to set your xml as content view
setContentView(R.layout.activity_main);
2- give an id to your linear layout
android:id="#+id/myLinearLayout"
3- find your linear layout like this
LinearLayout myLayout = (LinearLayout) findViewById(R.id.myLinearLayout);
4- then add your view
TextView tv = new TextView(this);
tv.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT));
tv.setText("Trying Again");
myLayout.addView(tv);
I didn't try but this should work.
The mistakes you're doing are
1- SetContentView method overrides all the views in the content view. so it'll remove everything when you call
LinearLayout thisLayout = new LinearLayout(this);
setContentView(thisLayout);
2- You need to use id of an item while trying to find it. Not the name of the layout file like you did here
// findViewById gets the id of the view that you want to find
LinearLayout myLayout = (LinearLayout) findViewById(R.layout.activity_main);

addView does not work (RelativeLayout)

This is my MainActivity XML file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/testingView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:context=".TestingActivity" >
This is the .java file:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.testing_activity);
RelativeLayout viewOne = (RelativeLayout) findViewById(R.id.testingView);
RelativeLayout viewTwo = new RelativeLayout(this);
viewTwo.setId(5233);
viewTwo.setBackgroundColor(0xFF0000);
Then, I tried to add this code (and a lot of other and the same, in differents ways, with differents and fixed sizes, but none of them worked):
viewTwo.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
At the end:
viewOne.addView(viewTwo);
Tried to add this too, but didn't work:
viewTwo.bringToFront();
I just see the white background with the Hello World! text.
Any solution?
viewTwo.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT));
Try this. Since the viewTwo don't have any child you won't see any thing. Try setting a different backgroundColor for viewTwo.
viewTwo.setBackgroundColor(Color.RED);
RelativeView is container to hold view inside it, of course it is also View, and you can add nested views as well.
How ever when you right some thing like this:
viewTwo.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
You are telling your view to be with the width of it's children. Since you did not added any child to that view the with will be 0.
use RelativeLayout instead of LinearLayout
viewTwo.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT))
Try This-
viewTwo.setBackgroundColor(getResources().getColor(Color.RED));
Updated-
Create a template for your dynamica view like relative layout-
createa xml in your res/layout folder- relative_view_template.xml and copy below code.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ff0000"
/>
and in your class use this code -
RelativeLayout relativeLayout = (RelativeLayout)((Activity) context).getLayoutInflater().inflate(R.layout.relative_view_template, null);
this is working for me,please try this.

Is both Static and Dynamic Layout Possible?

I have an XML layout having a single TextView
Now I want to add 50 buttons which I want to add dynamically in my java file !.
Is it possible to add attributes to an XML file via java code ??
Or can an activity have 2 layouts at a time ??
for eg,
public class Options extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.options);
Button but=new Button(this);
but.setText("Wassup");
// How do I add this button to the layout ?
}
}
Is it possible to add attributes to an XML file via java code ??
No, but you can add properties to Views and Layouts as you are doing with setText(). resource files themselves cannot be changed after compiled.
Or can an activity have 2 layouts at a time ??
The simple answer is no but you can inflate another layout and add it to the current layout.
Example of what you can do to add a Button
Inflate your root layout and add the Buttons to it with addView(). Something like
Layoutinflater inflater = (LayoutInflater) getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout ll = (LinearLayout) inflater.inflate(R.layout.layout_file);
Button but=new Button(this);
but.setText("Wassup");
// How do I add this button to the layout ?
ll.addView(but);
LayoutInflater
Or if you want to add it to a layout in the current file you can just use findViewById() and use addView() on that to add your Buttons to.
Considering you have an xml layout as below:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#id/mainlayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</TextView>
</LinearLayout>
In your java code after setContentView(R.layout.options); you can do the following:
LinearLayout linearLayout=(LinearLayout)findViewById(R.id.mainlayout);
Button button=new Button(this);
linearLayout.addView(button);
Now you can add as many buttons you like into the linear layout as seen above.
Yes it is possible. After setContentView(R.layout.options); get your buttons container with findViewById(). You will have a reference to a LinearLayout, RelativeLayout or something else. After that use Layout inflater and programmatically you can add other layouts or components.
Hope it helps!
just use layout.addView() where layout is a ViewGroup that you get by calling findViewById(R.id.layoutId)

Programmatically change a xml-created view

Is there a way to get the parameters from a XML view, modify some stuff on it and then use it as content view ?
Let's say I have a normal LinearLayout and I want to make that work:
LinearLayout layout = (LinearLayout) findViewById(R.layout.main);
setContentView(layout);
Instead of :
setContentView(R.layout.main);
Yes.
To be more specific, we need more specific info from you.
Edit
You can, for example, do the following.
Say you have in your xml specification a TextView:
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/mytv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22sp"
android:textStyle="bold"/>
</RelativeLayout>
Now you want to center horizontal the TextView programmatically:
setContentView(R.id.main);
TextView myTV = (TextView) findViewById(R.id.mytv);
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) myTV.getLayoutParams();
lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
myTV.setLayoutParams(lp);
You just set the contentview at the start, and don't need to set it again when you change the variables.
You can do anyything you want to the layouts even after setContentView. When you do operations like add items to a layout or set a background, the views in the screen are redrawn.
onCreate method is where you can modify layouts as it it about to begin drawing on to a screen.

Categories

Resources