combine 3 relative layouts multiple times - android

I have 3 relative layouts and i need to create a single setcontetntview which is a combination of these layouts each added 3 times and sharing equal screen space and it needs to be done programatically. I started by creating a new layout adding just 2 screens,
RelativeLayout primaryLayout = new RelativeLayout(this);
LayoutInflater layoutInflater = (LayoutInflater)this.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
RelativeLayout newLayout = (RelativeLayout)layoutInflater.inflate(R.layout.layout3, null, false);
RelativeLayout newLayout1 = (RelativeLayout)layoutInflater.inflate(R.layout.layout4, null, false);
primaryLayout.addView(newLayout);
primaryLayout.addView(newLayout1);
setContentView(primaryLayout);
This is displaying only the layout4. Also, if i add same layout again, its giving error stating the specified child already has a parent, you must call removeview() on the child parent first. Please help!

THe reason its displaying only layout4 is that the primaryLayout is a relative layout. Unless you specify something telling it where they go in that layout, it all goes in the upper left corner. So everything is being put on top of one another.
You can't add the same layout multiple times. You'd have to reinflate it once for every version you want, and add the results. Its like OOP- the RelativeLayout is an instance of the layout, inflating instantiates a new one.

You must use addRule to the layout param to set the views with respect to each other. As for the complaint about re-adding a view, you can try two independent instances of the view. While it will be the same layout, the parent won't know that.
EDIT:
To make occupy half screen you have to tell the parent view how much space to allot for the child view:
RelativeLayout.LayoutParams forChild = new RelativeLayout.LayoutParams(30,40);
childView.setLayoutParams(forChild);

Related

Adding a custom view multiple times in a layout

I have a custom XML file. I want to repeat this in a layout (say Relative) n number of times, dynamically (obviously).
I have seen many posts, but none helped. I am not looking for a ListView or Adapters or so. It's as simple as - A RelativeLayout. Inside it, adding the custom XML one above another. Any number of times.
With a static LinearLayout (Vertical orientation), adding the view dynamically results in rendering it once, not one below another. Don't know why. Although a TextView or so do repeat one below the other in a loop inside a LinearLayout (Vertical).
Then I dynamically created the layout (Relative), and inflated the custom XML. Displayed one. When I tried for another below the first it told me to remove child's parent first (Exception). If I do that and add again, its as good as removing the first rendered view and adding it again.
So how can I get multiple views in same layout?
A rough presentation of what I've attempted:
mainLayout = (RelativeLayout)findViewById(R.id.mainlay); //Mainlayout containing some views already
params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.BELOW,R.id.sideLayout); //sideLayout is an existing LinearLayout within the main layout.
View child = getLayoutInflater().inflate(R.layout.dynamiccustomlayout,null);
RelativeLayout r1 = new RelativeLayout(this);
r1.setLayoutParams(params);
r1.addView(child);
mainLayout.addView(r1);
mainLayout.setLayoutParams(params);
mainLayout.addView( child);
/* r2 = new RelativeLayout(this);
r2.setLayoutParams(params);
r2.addView(contentLayout); [Gives exception] */
This is how it worked out for me...
Before that, the issue with android is:
If you add dynamic views inside a LinearLayout (Horizontal), they will appear horizontally with new created instances, added to the view.
However, shockingly, it's not the same in case of LinearLayout (Vertical orientation). Hence the whole mess.
Solution:
The RelativeLayout layout file was binded with the variable, somewhat like this:
customLay = (RelativeLayout) mainLay.findViewById(R.id.dynamicCustomLayout);
Then, a Dynamic RelativeLayout was created within which the former variable is added/wrapped.
customLayout = new RelativeLayout(this);
customLayout.addView(customLay);
Every layout is assigned an id:
customLayout.setId(i);
And then a loop is run (2 if conditions for i=0 and i>0)
for i>0 (indicates the 2nd dynamic layout, to be added below the first), LayoutParameter is created:
params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
And then for i>0, using the ids of dynamic views, they are added one below the other:
//Following code below used id to place these views below each other to attain list type arrangement of views//
// i==0 for first view on top//
if (i == 0) {
params.addRule(RelativeLayout.BELOW, R.id.sideLayout);
customLayout.setLayoutParams(params);
}
// i>0 for views that will follow the first top//
else {
params.addRule(RelativeLayout.BELOW, i - 1);
customLayout.setLayoutParams(params);
}
Then added to main root layout, where all these views or cards need to be displayed:
includeLayout.addView(customLayout);
Ofcourse, the code is not just this. I have written the essential points that helped me achieve the target and that may help others in future.
So the main essence was ---
using a Dynamic RelativeLayout, to
bind the static RelativeLayout, and
assigning ids to the Dynamic RelativeLayout wrappers, and
on basis of ids use RelativeLayoutParameters to place the following
ids below the previous ones.
You have to instanciate every child by itself
View child = getLayoutInflater().inflate(R.layout.dynamiccustomlayout,null);
r1.addView(child);
View child2 = getLayoutInflater().inflate(R.layout.dynamiccustomlayout,null);
r1.addView(child2);
//ok, i do a analog thing in obne of my apps. here is the code:
public class FlxForm extends LinearLayout {
public FlxForm(Context context) {
super(context);
inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.flxform, this);
this.setPadding(0, 0, 0, 0);
container = (LinearLayout) this.findViewById(R.id.flxform);
this.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
//here is my funtion to calculate the items i want to add, its a little bit too complicated, but in the end it works like:
for(int i=0;i<10;i++){
View x = inflater.inflate(R.layout.dynamiccustomlayout,null);
container.addview(x);
}
}
}
XML for the Form
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/flxform"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:background="#android:color/transparent"
android:orientation="vertical" >
</LinearLayout>
Then you can instantiate a "Form" Objekt and add it into a ScrollView
For doing this You would have to nest your RelativeLayout inside a ScrollView and Manage all the Scrolling, items adding, memory management, etc manually.
So the simple solution for adding n Number of Custom Views is to use a RecyclerView, ListView, GridView, etc with a neat CustomAdapter and Your Custom View.
Here is a nice example of using RecyclerView with custom Adapter :
http://code.tutsplus.com/tutorials/getting-started-with-recyclerview-and-cardview-on-android--cms-23465
I hope this Helps.

How to add view in custom layout in runtime

I am creating custom layout (extends FrameLayout). I have a bunch of view defined in xml(it doesn't matter now).
What I need to do. My custom layout has custom defined attributes, let's assume that it named footer_banner_type.
I have different Banners classes some of them I quite different from one another, so I cannot place some base banner in xml. So I have to add some banner based on attribute value.
I am extending FrameLayout . I am newbie and this is my first custom layout.
I don't know how to improve performance.
As I understand Layout iterating and inflating all child views. But if I need to add view in runtime.I don't want to make layout reiterate view hierarchy, because it will be performance issue.
My question is how to implement my task in better way.
//First create your view:
View wonderfulView = new View(this.getApplicationContext());
//Then, create its LayoutParams
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1);
//Set those layout params in your view
wonderfulView.setLayoutParams(params);
//finaly, add the view to your ViewGroup
yourLayout.addView(wonderfulView);
That's it.
If you want to change the view container, you'll have to remove it form the previous parent like this:
View movingThing = ((YourLayoutClass)findViewById(R.id.currentContainer)).getChildAt(WhereYourViewis);
((YourLayoutClass)findViewById(R.id.currentContainer)).removeView(movingThing);
((YourLayoutClass)findViewById(R.id.newContainer)).addView(movingThing);

Android Overlapping Image Views

I want to create this sort of a view where the cross should be separate image view as I want it to be clickable. How can I achieve this ?
It would be great If I can create this view programatically as I am a dynamic list of images and I am programatically creating the image Views. All I need now is to add the overlapping imageview as well.
Thanks in advance
Use FrameLayout and you can overlay views on top of each other
Ex:
FrameLayout frame = (FrameLayout) findViewById(R.id.frame);
ImageView image = new ImageView(this);
iv.setImageResource(R.drawable.image);
ImageView cross = new ImageView(this);
i.setImageResource(R.drawable.cross);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
layoutParams.gravity = Gravity.RIGHT | Gravity.TOP;
i.setLayoutParams(layoutParams);
frame.addView(image);
frame.addView(cross);
Create a RelativeLayout programmatically, which contains two ImageViews. Place your image in the first one, and your second image in the second one. Adjust the margins accordingly to place it in the top right corner.
First create a completely new layout to use as an placeholder for example "partial_layout.xml". Then in your code first make a LayoutInflater with something like this:
LayoutInflater mInflater = (LayoutInflater) this.getSystemService(this.LAYOUT_INFLATER_SERVICE);
then try to get a fresh copy of this layout with something like this:
View convertView = mInflater.inflate(R.layout.partial_layout, null);
now put your current data to this view, and finally add this view to your content view.
If you create a list of views, you can still use XML by inflating it only when needed - just watch the lecture "the world of listView" in order to do it correctly. Using ListView is much more efficient than creating as many views as the number of items to show (for example, if there are 100 images to show, only those that are on screen need to be created).
Anyway, the xml can contain either FrameLayout or RelativeLayout as the root view, and you just put the 2 imageViews according to the right position you wish to have. You can use the UI designer for this, or edit the XML itself by adding margin-top for the larger image. also, make sure the larger image is written there before the small one.
as for the clicking, you can use setOnClickListener on the small imaveView.
BTW, if it's just images, you should probably use GridView instead of ListView.

combine several types of xml layouts programatically android

I have a requirement where there are 2 programatically generated screens and 2 xml layouts. Now i need to on the fly combine, these layouts multiple times.
For ex, i have screen 1 - programatically created, screen 2 - programatically created, screen 3- from a xml layout, screen 4 - from a xml layout
My final layout design should be a single screen with screen1, screen2, screen 3, screen 4, screen 2... with all screens sharing equal screen space based on the number of screen i input. Please let me know the approach. Some screens are having relative layout and some linear ones. So it should combine these.
You'll need to invoke addView() on the primary layout. Once the primary layout is built (which holds all the other layouts), the addView() method will add new views to the existing primary layout.
To add the new layout, you'll need to inflate it first.
LinearLayout primaryLayout;
LayoutInflater layoutInflater = (LayoutInflater)this.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
LinearLayout newLayout = (LinearLayout)layoutInflater.inflate(R.layout.your_new_layout, null, false);
primaryLayout.addView(newLayout);
AddView also provides an index option to place the new layout at a specific point in the primary layout.
Try starting with a blank, XML layout (say called primary_layout):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/primaryLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</RelativeLayout>
Then, as your activity starts, set that first, then inflate and add as desired:
setContentView(R.layout.primary_layout);
LinearLayout primaryLayout = (LinearLayout) findViewById(R.id.primaryLayout);
Then you can add your new views to that one. As for adding multiple times, I believe that it's done by reference, so it only sees a single view. Try building the view in a method, and just returning the view. Such as:
private View buildNewView(){
LayoutInflater layoutInflater = (LayoutInflater)this.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
LinearLayout newView = (LinearLayout)layoutInflater.inflate( R.layout.my_new_view null, false );
return newView ;
}
And call it via primaryLayout.addView(buildNewView();.
You could look into Fragments. They seem to do exactly what you need. Here are the links to the Training and API Guides on them.In your xml file, you can specify 4 child layouts inside a LinearLayout parent, each with an attribute android:layout_weight="1", so each child layout would only take up the same amount of space. If in portrait orientation, it is suggested to set android:layout_width="match_parent and android:layout_height="0dp" Now, you can label the id's of each child layout as id1, id2, id3, etc, but you can also label the two layouts you will create as something likeandroid:id="#+id/fragment_container_first and android:id="#+id/fragment_container_second.In the Java code, you would set the contentView as the id of the xml file (setContentView(R.layout.myXMLLayout);), create two instances of a Fragment by following the Training guide link I provided above, and add those views to the containers you setup earlier inside your xml files by using something like getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container_first, firstFragment).commit(); and getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container_second, secondFragment).commit();(If you are using the support library, which is what the training guides use).I really hope this helps you out. You can build a really flexible UI with Fragments. For instance, later on, you can replace the first two fragments with other fragments at runtime, increasing flexibility. You can even setup different UIs for different screen sizes, with a more compact view on a phone, but with much more to offer on a larger screen like a tablet.I'd love to hear back if this helped you out!

Array containing all instances of views with Tag = x

Is there a way to create an array containing actual instances of views. For example, if I have one LinearLayout called Container that has within it 3 other LinearLayouts with the same Tag attribute and I wanted to get a list containing all 3 LinearLayouts so I can loop through and handle each.
Tried:
LinearLayout[] layouts = (LinearLayout[]) Container.FindViewWithTag(tag);
and
List<LinearLayout> layouts = (List<LinearLayout>) Container.FindViewWithTag(tag);
and
foreach(LinearLayout layouts in Container.FindViewWithTag(tag))
None of these have been acceptable to Android so far. Another acceptable way to handle my situation would be to just be able to assign each LinearLayout a Parent. But I haven't found a way to programatically set a view's parent, only how to get a view's parent.
What I have understood from your question that you want the child of Linear Layout. Yes, you can get the child of linear layout by container.getChild(index)
for(int i=0;i<container.getChildCount();i++){
View child=container.getChildAt(i);
//your processing....
}

Categories

Resources