android: reuse a RelativeLayout in XML by inflating it at run time? - android

Edition of question
It is already in a separate xml (tablet_shortterm_column.xml) see above.
Anyway, it seems logcat complains that rlo_shortterm_col already has a parent, so it won't allow an another ptr_rlo_rght_middle.addView(rlo_shortterm_col ). Makes no sense.
I spent so many hours on thsi problem and still can't solve it. Can someone please give me a hand? Thanks in advance.
I have an xml file (tablet_shortterm_column.xml) that contains a RelativeLayout that I need to re-use, again and again. Sometimes many times on the same screen stacked one after the other horizontally. I am attempting to insert one into an existing RelativeLayout (ie. one inside the other.)
//exerpts
public class TabletMain extends Activity {
setContentView(R.layout.tablet_main);
public RelativeLayout ptr_rlo_rght_middle;
ptr_rlo_rght_middle = (RelativeLayout) findViewById(R.id.rlo_rght_middle);
//rlo_rght_middle is in tablet_main.xml
LayoutInflater inflater =
(LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View llo_tmp = (View) inflater.inflate(R.layout.tablet_shortterm_column,null);
RelativeLayout rlo_tmp = (RelativeLayout) llo_tmp.findViewById(R.id.rlo_shortterm_col);
// rlo_shortterm_col is the object I want to reuse it a RelativeLayout and is inside
// tablet_shortterm_column.xml
RelativeLayout.LayoutParams rlo_layoutparams;
rlo_layoutparams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
rlo_layoutparams.addRule(RelativeLayout.RIGHT_OF, R.id.llo_rght_middle_col1);
// llo_rght_middle_col1 is a RelativeLayout inside tablet_main.xml,
// I want to put another RelativeLayout view right next to it.
rlo_tmp.setLayoutParams(rlo_layoutparams);
ptr_rlo_rght_middle.addView(rlo_tmp); //Application crashes right on this line.
} //end Activity
//********************* content of tablet_shortterm_column.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<RelativeLayout
android:id="#+id/rlo_shortterm_col"
android:layout_width="180dp"
android:layout_height="fill_parent"
android:background="#436699"
android:orientation="vertical"
android:layout_margin="3px"
android:weightSum="1"
> <!-- android:background="#32CD32" android:layout_height="365dp" android:layout_margin="30px" -->
<Button
android:id="#+id/btn_shortterm_col"
android:layout_alignParentTop="true"
android:text="Tuesday Afternoon"
android:layout_margin="15px"
android:textSize="12px"
android:textColor="#FFFFFF"
android:layout_width="wrap_content"
android:layout_gravity="center_horizontal"
android:background="#296699"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
> <!--android:background="#32CD32" -->
</Button>
<ImageView
android:id="#+id/iv_shortterm_col"
android:layout_below="#+id/btn_shortterm_col"
android:src="#drawable/tblet_icon14_med"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
><!-- android:src="#drawable/tblet_shape1" android:layout_gravity="center_horizontal" -->
</ImageView>
<TextView
android:id="#+id/tv_shortterm_col1"
android:layout_below="#+id/iv_shortterm_col"
android:text="-10ÂșC"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10px"
android:background="#DCDCDC"
android:textColor="#000000"
android:textSize="12px"
android:layout_centerHorizontal="true"
> <!-- android:layout_gravity="center_horizontal" -->
</TextView>
<TextView
android:id="#+id/tv_shortterm_col2"
android:layout_below="#+id/tv_shortterm_col1"
android:text="Flurries"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10px"
android:background="#DCDCDC"
android:textColor="#000000"
android:textSize="12px"
android:layout_centerHorizontal="true"
>
</TextView>
<RelativeLayout
android:id="#+id/rlo_shortterm_col_1"
android:layout_below="#+id/tv_shortterm_col2"
android:src="#drawable/tblet_shape2"
android:background="#32CD32"
android:layout_height="113dp"
android:layout_margin="40px"
android:layout_width="125dp"
> <!--android:background="#32CD32" android:orientation="vertical" -->
</RelativeLayout>
</RelativeLayout>
</LinearLayout>

Create a separate xml file for your RelativeLayout and then inflate it as many times as you want.

llo_tmp is the parent view of the RelativeLayout you're trying to reuse. Thus, you can't add it to another ViewGroup and you get that logcat error.
You can remove the LinearLayout stuff from your xml file and inflate the xml file in the same way (though maybe instead of returned View you'd return a RelativeLayout). You shouldn't have to change much of the java code since the reference is still the same.
Or, a quick fix may be to add llo_tmp to your ViewGroup instead of rlo_tmp. Either way, rlo_tmp already has a parent and can't be reused. Since you don't have your layout fill the entire screen width, you probably don't want this.

Related

How to duplicate xaml code dynamically on button click [duplicate]

The main goal is to use a pre-made layout to create separate modules that can be edited, and then programmatically add them to the root layout. To clarify, several modules stuck together would look like this. I would like to dynamically create each clickable block that consists of a name, date, and letter. The .axml code for each block is as follows:
<RelativeLayout
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/borderLayout"
android:background="#drawable/line"
android:paddingBottom="1dp"
android:paddingTop="1dp">
<RelativeLayout
android:id="#+id/relativeLayout1"
android:padding="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:background="#ff2f2f2f">
<TextView
android:text="C"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textView1"
android:layout_alignParentLeft="true"
android:textSize="30dp" />
<TextView
android:text="Washington"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/textView1"
android:id="#+id/textView2"
android:layout_alignParentRight="true"
android:gravity="right" />
<TextView
android:text="6-8-17"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/textView2"
android:id="#+id/textView3"
android:gravity="right"
android:layout_alignParentRight="true" />
</RelativeLayout>
</RelativeLayout>
The main problem I am having is formatting the views programmatically in the same way that I formatted them in the .axml file.
Lets assume you have a LinearLayout with an orientation of vertical in your main axml that you wish to attach multiple views to.
Get a reference to that "parent" LinearLayout:
var linearLayoutParent = FindViewById<LinearLayout>(Resource.Id.linearLayout1);
Then in some loop, use LayoutInflater.Inflate to inflate your repeating layout, use the view returned and FindViewById on that View each of the elements you need to update and then add that view to the parent view with an increasing index:
index++;
var view = LayoutInflater.Inflate(Resource.Layout.RepeatingLayout, linearLayoutParent, false);
var letter = view.FindViewById<TextView>(Resource.Id.textView1);
letter.Text = index.ToString();
// FindViewById for textView2, textView3 and assign the text on each....
linearLayoutParent.AddView(view, index);
Note: If you have a lot of these repeating elements and you will have to scroll them (off screen), look at using a RecyclerView instead, it will save you a lot of headaches into terms of memory management, scrolling performance, etc... ;-)
Use inflater to create a view from resource. Then you can add it programmatically
context.LayoutInflater.Inflate(Resource.Layout.oneimg_twolbl, null);

Not able to add linerlayout in scrollview programatically in android

I need to use scrollview pragmatically, while include linearlayout in scrollview its shows error like E/AndroidRuntime(22309): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sample.program/com.sample.program.details}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
Check it out my coding :
My linearlayout which i want to add in scrollview
mScrollTolinear = (LinearLayout) findViewById(R.id.toscroll);
My ScrollView
ScrollView mScroll = new ScrollView(Appointmentdetails.this);
mScroll.addView(mScrollTolinear);
To remove the view
mScrollTolinear.removeAllViews();
mScrollTolinear.removeView(mScrollTolinear);
Try to to remove the view some thing like that but no luck, have tried with google also but dint get the solution, any suggestion or help highly accepted.
My XML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/whitebackground"
android:orientation="vertical"
>
<!-- <ScrollView -->
<!-- android:id="#+id/favscroll" -->
<!-- android:layout_width="fill_parent" -->
<!-- android:layout_height="wrap_content" -->
<!-- android:visibility="invisible" > -->
<LinearLayout
android:id="#+id/toscroll"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/topheaderbg" >
<ImageView
"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerInParent="true"
android:contentDescription="#string/app_name"
android:paddingLeft="10dip"
android:src="#drawable/listbutton" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="#color/White"
android:textSize="16sp"
android:textStyle="bold" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerInParent="true"
android:contentDescription="#string/app_name"
android:paddingRight="10dip"
android:src="#drawable/notificationicon" />
</LinearLayout>
</LinearLayout>
Thanks
The problem is that you are trying to add a view which was inflated from XML file hence it already has a parent (because it is already situated in view hierarchy). Instead of the following
mScrollTolinear = (LinearLayout) findViewById(R.id.toscroll);
you will have to implement something like this:
mScrollTolinear = getLayoutInflater().inflate(R.layout.your_layout_file, null);
And also keep in mind that ScrollView can only have one child view, otherwise you can get exceptions
UPD
Update corresponding to your comment
So in case if you want to add ScrollView to LinearLayout you will have to call:
ScrollView scroll = new ScrollView(yourContext); //you may also want to specify LayoutParams for it
mScrollTolinear.addView(scroll);
I hope I've understood your comment correctly

Add Button to XML Layout programatically

This problem has been asked many times here, but none of the solutions work for me, because my XML layout is a bit different.
I have an XML with LinearLayout containing an ImageView and a TextView. The XML is populated using Java code. It is a file picker library from here, it lists the files and folders that exists in the android filesystem.
Here is the XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<ImageView
android:id="#+id/file_picker_image"
android:layout_width="40dip"
android:layout_height="40dip"
android:layout_marginBottom="5dip"
android:layout_marginLeft="5dip"
android:layout_marginTop="5dip"
android:contentDescription="#string/app_name"
android:scaleType="centerCrop"
android:src="#drawable/file" />
<TextView
android:id="#+id/file_picker_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:singleLine="true"
android:text="#string/file_name"
android:textSize="28sp" />
</LinearLayout>
Now, I want to add a button just below this list. When I try to add the button in the XML, it iterates though each row, and buttons are shown in every row.
When I do it using Java code, neighter the button, nor the textview is displayed, but the image view is displayed.
What I want is similar to the image in this post, but cannot achieve it till now. None of those solutions or any other that I read here works in my case.
I am trying to add the button using this code in the Activity whose source is in the link provided above. I tried to add the following code in FilePickerListAdapter's constructor.
RelativeLayout relLayout = new RelativeLayout(context);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
Button filterBtn = new Button(context);
filterBtn.setText("Filter");
relLayout.addView(filterBtn, params);
Please guide me what am I doing wrong, and how to make it possible.
Regards.
Mixing the xml way and programmatic way to create views is not a good idea. You might as well create all views in xml first (including your button), only set your button to android:visibility="gone" to hide it. Set it to visible when you want.
This might not be something you asked for, but it's an alternative that you can try it out. I implemented layout_weight into your xml and included the button at the end of the screen. The outcome of this will be something similar with the link in your question.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:weightSum="1" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_weight=".9" >
<ImageView
android:id="#+id/file_picker_image"
android:layout_width="40dip"
android:layout_height="40dip"
android:layout_marginBottom="5dip"
android:layout_marginLeft="5dip"
android:layout_marginTop="5dip"
android:contentDescription="#string/app_name"
android:scaleType="centerCrop"
android:src="#drawable/file" />
<TextView
android:id="#+id/file_picker_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:singleLine="true"
android:text="#string/file_name"
android:textSize="28sp" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_weight="0.1" >
<Button
android:layout_width="fill_parent"
android:layout_height="fill_parent" /> <!--Your Button-->
</LinearLayout>
</LinearLayout>

Insert a linearLayout inside another linearLayout

I'm trying to insert a LinearLayout inside another LinearLayout. I don't know if what I am doing is right or not. I need to try it this way, without using inflation.
LinearLayout address2;
address2 = new LinearLayout(this);
address2 = (LinearLayout)findViewById(R.id.sfsp2_layout);
LinearLayout teste3 = (LinearLayout)findViewById(R.id.se_contentAdressPostal);
LinearLayout teste4 = (LinearLayout)teste3.findViewWithTag("teste");
teste4.addView(address2);
LinearLayout teste3
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/se_contentAdressPostal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:background="#drawable/background_tile_address_postal"
android:orientation="vertical" >
<include
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
layout="#layout/socio_form_structured_postal" />
LinearLayout teste4
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/sfsp_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/background_tile"
android:orientation="vertical"
android:tag="teste" >
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/sfsp_layout_horizontal"
android:layout_width="wrap_content"
android:layout_height="49dp"
android:layout_gravity="right"
android:background="#drawable/background_tile"
android:orientation="horizontal"
android:tag="teste" >
<Button
android:id="#+id/sfsp_btStructuredPostal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginBottom="2dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="2dp"
android:hint="#string/sfsp_btStructuredPostal" /> .......
LinearLayour address2 ( The layout that i need to insert in layout4)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/sfsp2_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/background_tile"
android:orientation="vertical" >
<EditText
android:id="#+id/sfsp2_etStructuredPostalApartado"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:layout_marginLeft="65dp"
android:layout_marginRight="55dp"
android:layout_marginTop="2dp"
android:layout_weight="0.14"
android:ems="10"
android:hint="#string/sfsp2_etStructuredPostalApartado"
android:inputType="textMultiLine"
android:scrollHorizontally="false" >
The LinearLayout "teste4" is inside "teste3". I need to insert LinearLayout "address2" inside "teste4". Can you tell me what I'm doing wrong?.
I think there is some misunderstanding here about how the findViewById works. I'll try to explain it below. Hope this helps, let me know if it doesn't.
There are two possible findViewById() that can be used.
Activity.findViewById(): this can be used to find a view in the current activity's main content view -- that is, the view that was set using setContentView(). It cannot be used for any other purpose. For example, it cannot find a view from any other layout file -- the function simply would have no way of knowing how to find it. As far as I can tell, this is the function you're trying to use. If the last XML file you have is not the main layout, then the line address2 = (LinearLayout)findViewById(R.id.sfsp2_layout) will fail.
View.findViewById(): this function can be used to find a view that is contained in some other view. E.g. if you have view1 that contains view2, and view2 has ID some_id, then you can find view2 by calling view1.findViewById(R.id.some_id). In order for this to work, view1 has to be fully initialized. E.g. if view1's description is in XML, it has to be fully inflated first.
In essence, if you want to work with a view that is described in a separate XML file, you have to inflate it first. I don't think there is a way around it.

Adding multiple views of the same type

So, I have this nice little view that I've made, which basically shows two buttons with some status labels. Nothing too complicated.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:gravity="center"
android:orientation="vertical">
<LinearLayout android:orientation="horizontal"
android:layout_width="wrap_content" android:layout_height="wrap_content">
<ToggleButton android:text="ToggleButton" android:id="#+id/toggleButton1"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:background="#drawable/on_off">
</ToggleButton>
<TextView android:text="TextView" android:id="#+id/textView1"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_marginLeft="20px" android:layout_marginRight="20px"
android:layout_marginTop="3dp" android:layout_marginBottom="3dp">
</TextView>
<ImageButton android:src="#drawable/preferences"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:id="#+id/imageButton2" android:background="#android:color/transparent">
</ImageButton>
</LinearLayout>
<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:id="#+id/view_monday" android:textSize="10dp" android:layout_marginRight="3dp"
android:layout_height="wrap_content" android:layout_width="wrap_content" android:textColor="#2F4F4F"
android:text="#string/monday_short"></TextView>
<TextView android:id="#+id/view_tuesday" android:textSize="10dp" android:layout_marginRight="3dp"
android:layout_height="wrap_content" android:layout_width="wrap_content" android:textColor="#2F4F4F"
android:text="#string/tuesday_short"></TextView>
<TextView android:id="#+id/view_wednesday" android:textSize="10dp" android:layout_marginRight="3dp"
android:layout_height="wrap_content" android:layout_width="wrap_content" android:textColor="#2F4F4F"
android:text="#string/wednesday_short"></TextView>
<TextView android:id="#+id/view_thursday" android:textSize="10dp" android:layout_marginRight="3dp"
android:layout_height="wrap_content" android:layout_width="wrap_content" android:textColor="#2F4F4F"
android:text="#string/thursday_short"></TextView>
<TextView android:id="#+id/view_friday" android:textSize="10dp" android:layout_marginRight="3dp"
android:layout_height="wrap_content" android:layout_width="wrap_content" android:textColor="#2F4F4F"
android:text="#string/friday_short"></TextView>
<TextView android:id="#+id/view_saturday" android:textSize="10dp" android:layout_marginRight="3dp"
android:layout_height="wrap_content" android:layout_width="wrap_content" android:textColor="#2F4F4F"
android:text="#string/saturday_short"></TextView>
<TextView android:id="#+id/view_sunday" android:textSize="10dp" android:layout_marginRight="3dp"
android:layout_height="wrap_content" android:layout_width="wrap_content" android:textColor="#2F4F4F"
android:text="#string/sunday_short"></TextView>
</LinearLayout>
</LinearLayout>
And I want to add it to my main activity with the following code:
LinearLayout root = (LinearLayout)findViewById(R.id.alarms);
View newView = View.inflate(this, R.layout.alarm, null);
alarms.add(newView);
However, it seems as if I can't add more than one of them, and I'm not sure why, or how to get around this problem to be able to add multiple copies. Furthermore, I don't know how to access individual parts, as they would all have the same id.
Thanks,
Tim
How are you trying to add the multiple copies to the 'root' LinearLayout?
If you're simply trying to call addView(newView) twice, then you're trying to add the same View object reference twice over. This is wrong because you're trying to add the same View object reference twice. I'm not entirely sure what the defined behaviour is when you do this, but I assume that addView() performs no action the second time because it checks that it already holds a reference to newView (would be grateful if anyone could confirm whether that's right or wrong).
So you need to inflate two separate instances of your child View I think, using say:
View newView0 = View.inflate(this, R.layout.alarm, null);
View newView1 = View.inflate(this, R.layout.alarm, null);
And then add them individually.
I think you'd then get around the problem of duplicate IDs by calling findViewById() on the actual child Views, as opposed to the parent:
newView0.findViewById( someID )
Update: Just tested the code in Eclipse for you. I added two child Views created from your XML file to a LinearLayout, and then changed a property (background colour to blue) of one of the Views within the second child View:
LinearLayout root = new LinearLayout(this);
LinearLayout newView0 = (LinearLayout)View.inflate(this, R.layout.main, null);
LinearLayout newView1 = (LinearLayout)View.inflate(this, R.layout.main, null);
root.addView(newView0);
root.addView(newView1);
setContentView(root);
newView1.findViewById(R.id.view_monday).setBackgroundColor(0xff0000ff);
Try to inflate the same view every time that you want to add the view. For example, if you're adding a view every time that a button is pressed you will want to declare the view outside of onClick() but assign the view inside the onCLick() method.

Categories

Resources