addView does not work (RelativeLayout) - android

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.

Related

Unable to set layout width, height and weight of inflated view in XML in Android

I am developing an Android app. In my app, I need to inflate list of views dynamically. I added them and working. The problem is with setting the width and height of layout. Now I will demonstrate my problem with a simple project. Actually, my project is much more complicated than this simple project.
I am inflating views to this layout.
<LinearLayout
android:orientation="horizontal"
android:id="#+id/cm_photos_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
I am looping through a list of bitmap and adding view dynamically as follow
for(Bitmap bmp : bitmaps)
{
View preview = layoutInflater.inflate(R.layout.item_cm_preview_image,null);
ImageView previewImageView = (ImageView)preview.findViewById(R.id.item_cm_preview_image);
previewImageView.setImageBitmap(bmp);
container.addView(preview);
}
Please note, in the above code, container is a LinearLayout added dynamically to the parent XML in the above.
container = new LinearLayout(this);
container.setOrientation(LinearLayout.HORIZONTAL);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
container.setLayoutParams(params);
parentLinearLayout.addView(container);
This is my item_cm_preview_image.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_weight="1"
android:layout_height="400dp"
android:layout_width="0dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:scaleType="centerCrop"
android:id="#+id/item_cm_preview_image"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
As you can see, I set the layout height to 400dp, width 0 and layout_weight to 1 in the XML. So all image height must be same and width must be equal because of layout_weight. But the result is not as expected. You can see screenshot below.
As you can see in the screenshot, both layout_weight and height are not working for all inflated views. But if I add extra ViewGroup dynamically and inflate the view to that layout, it is working. Below is my code
//This happening in for loop
LinearLayout wrapper = new LinearLayout(this);
wrapper.setLayoutParams(new LinearLayout.LayoutParams(0,500,1));
View preview = layoutInflater.inflate(R.layout.item_cm_preview_image,null);
ImageView previewImageView = (ImageView)preview.findViewById(R.id.item_cm_preview_image);
previewImageView.setImageBitmap(bmp);
wrapper.addView(preview);
container.addView(wrapper);
This is the result:
As you can see both layout_weight and height working when I use an extra dynamic linear layout. Why is setting layout weight and height in XML not working? Why second way is working? How can I set weight and height in XML layout file? Is it possible?
If you inflate layout using method
View preview = layoutInflater.inflate(R.layout.item_cm_preview_image,null);
it skip its width and height parameters..., but if you will use:
View preview = layoutInflater.inflate(R.layout.item_cm_preview_image,parent,false);
it should work correct, for example if you inflate view in activity as parent you can provide (ViewGroup) getView():
View preview = layoutInflater.inflate(R.layout.item_cm_preview_image,(ViewGroup) getView(), false);

dynamically created Buttons overlapping

I have created a layout with a database call where a button will be created for each item inside the database. The buttons are created like I need and I also found out, how to set up the layout_width and layout_height but all buttons are placed in the same position and overlap each other so that only the last created button can be accessed. My code for creating the buttons looks like this:
Button bt = new Button(this);
bt.setText("Button Title");
bt.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
linerLayout.addView(bt);
The activity looks like that, after generating the buttons:
I looked at each method that can be used for the button but didn't find anything to define the position. I just thought about following method:
bt.layout(l, t, r, b);
but don't know exactly how to use it and thought there might be a simpler method to solve this problem. Anybody who knows a workaround?!
CHANGED CODE
I just tryied to set the layout parameters like explained from "Chen doron". I have a relative layout inside my xml file:
<RelativeLayout
android:id="#+id/llActOver"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="2" >
</RelativeLayout>
and formatted the generated buttons like this:
Button bt = new Button(context);
bt.setText(c.getString(iDef));
fontClass.setFont(bt);
//RelativeLayout placeholder = new RelativeLayout(context);
RelativeLayout.LayoutParams layoutParam =
new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT);
if(rowCount < 1){
layoutParam.addRule(RelativeLayout.ALIGN_PARENT_TOP);
rowCount++;
}else{
layoutParam.addRule(RelativeLayout.ALIGN_PARENT_TOP, lastButtonId);
}
lastButtonId = bt.getId();
//placeholder.addView(bt, layoutParam);
linearLayout.addView(bt, layoutParam);
I save the buttons id at the end of the loop so that the last buttons id can be accessed in the next round.
I also tryied to create a new relativ layout for each new button like the commented part of the code shows but even without the new layout nothing happens and i still just have all buttons overlapped.
I finally solved the problem, but just by trying each possible combination of layout types.
I found out, i have to define a LinearLayout inside the XML file and the attribute android:orientation="vertical" is affordable. all the other parameters that have been set before were unimportant.
So now i have a LinearLayout inside a ScrollView in my xml file:
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="2" >
<LinearLayout
android:id="#+id/llActOver"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
and inside the java database i have following code to create a button for each row in the db, setting its Text and Font and add it to the loaded layout:
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
Button bt = new Button(context);
bt.setText(c.getString(iDef));
fontClass.setFont(bt);
linearLayout.addView(bt);
}
and here a screenshot of the result:
maybe somebody else who has the same problem won't need to worry as long as me with this description.
You could use a Relative Layout, and have the first Button align to the parent's top.
Then each button aligned to the previous button's bottom.
Use:
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
And then:
params.addRule(RelativeLayout.BELOW,ID-Of-Previous-Button);
Also check out:
http://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams.html

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.

It inflate the view without the margin

I have this code
View item = View.inflate(context, R.layout.item_layout, null);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT);
layout.addView(item, params);
my item_layout: (note the part android:layout_marginTop="2dip")
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" android:layout_marginTop="2dip" android:layout_width="fill_parent">
<ImageView android:src="#drawable/pic_unknown" android:id="#+id/image1"
android:layout_height="50dip" android:layout_width="50dip"
android:padding="5dip"></ImageView>
</RelativeLayout>
and then in my layout I see the list of items inflated but with no margin in-between them. I tried with margintop=10dip still nothings happen my point is that the value I put in the layout it is not taken in the calculation with or without the margin top the layout is the same.
How can I add some empty space between the items ?
How can I inflate a empty space between the items ?
Is it possible to inflate something like gap or some space ?
or I must use workaround like inflating some empty layout with 2dip height or something
Thanks
The last parameter of the inflate method is the parameter to which you add the inflated view. In your case it is null. Try this instead:
View item = View.inflate(context, R.layout.item_layout, layout);
Try Padding the RelativeLayout instead if your margins apply to the outside.
You can add margin to layout which you inflated like below:
final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.topMargin = 10;

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