listView items is not match parent n linear layout - android

I need to create LinearLayout, which has ListView. I did it with this code:
this.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
final ListView listView = (ListView) LayoutInflater.from(getContext()).inflate(R.layout.chat_timer_rollout, null);
addView(listView);
My chat timer rollout is:
<ListView
xmlns:a="http://schemas.android.com/apk/res/android"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:background="#color/white"
a:cacheColorHint="#color/white"
a:paddingBottom="12dp"
a:paddingTop="12dp">
After creating i've tried to add items in list view like this:
final ArrayAdapter<TimeInterval> adapter = new ArrayAdapter<>(getContext(),
R.layout.chat_timer_item,
R.id.timer_label, TimeInterval.INTERVALS);
listView.setAdapter(adapter);
Chat timer item has code:
<TextView
a:id="#+id/timer_label"
xmlns:a="http://schemas.android.com/apk/res/android"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:paddingBottom="11dp"
a:paddingLeft="#dimen/timer_label_margin_right"
a:paddingTop="11dp"
a:textColor="#color/primary_text"
a:textSize="#dimen/timer_text_size"/>
After creating this i see my linear layout on screen, but when i click item it has width wrap_content, not match parent? how to fix it? I've tried to set one more linear layout for inflated with params match_parent, but it didnt help. Thank you!

The second parameter in the LayoutInflater#inflate() method is the (optional) parent View of the inflated layout. When you pass null for the parent, the Inflater doesn't know which type of LayoutParams are appropriate, so it uses a default ViewGroup.LayoutParams, which has ViewGroup.WRAP_CONTENT for both dimensions.
Since your posted code is in your LinearLayout subclass, you can pass this as the second argument in the inflate() call. Also, when you provide the parent View in that two-parameter method, the inflated layout is added to it automatically, so you don't need the addView() call.
final ListView listView = (ListView) LayoutInflater.from(getContext())
.inflate(R.layout.chat_timer_rollout, this);

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.

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.

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....!

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;

How to Programmatically Add Views to Views

Let's say I have a LinearLayout, and I want to add a View to it, in my program from the Java code. What method is used for this? I'm not asking how it's done in XML, which I do know, but rather, how can I do something along the lines of this sample code?
(One View).add(Another View)
Like one can do in Swing.
Calling addView is the correct answer, but you need to do a little more than that to get it to work.
If you create a View via a constructor (e.g., Button myButton = new Button();), you'll need to call setLayoutParams on the newly constructed view, passing in an instance of the parent view's LayoutParams inner class, before you add your newly constructed child to the parent view.
For example, you might have the following code in your onCreate() function assuming your LinearLayout has id R.id.main:
LinearLayout myLayout = findViewById(R.id.main);
Button myButton = new Button(this);
myButton.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
myLayout.addView(myButton);
Making sure to set the LayoutParams is important. Every view needs at least a layout_width and a layout_height parameter. Also getting the right inner class is important. I struggled with getting Views added to a TableRow to display properly until I figured out that I wasn't passing an instance of TableRow.LayoutParams to the child view's setLayoutParams.
The best way I found is to use the inflate static method of View.
View inflatedView = View.inflate(context, yourViewXML, yourLinearLayout);
where yourViewXML is something like R.layout.myView
please notice that you need a ViewGroup in order to add a view (which is any layout you can think of)
so as an example lets say you have a fragment which it view already been inflated and you know that the root view is a layout, and you want to add a view to it:
View view = getView(); // returns base view of the fragment
if (view == null)
return;
if (!(view instanceof ViewGroup))
return;
ViewGroup viewGroup = (ViewGroup) view;
View popup = View.inflate(viewGroup.getContext(), R.layout.someView, viewGroup);
EDIT:
Kotlin code for the example above (view is the getView() of a fragment)
(view as? ViewGroup)?.let {
View.inflate(context, R.layout.add_credit_card, it)
}
To add the view programmatically, you can do:
LinearLayout rlmain = new LinearLayout(this);
LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT);
LinearLayout ll1 = new LinearLayout (this);
ImageView iv = new ImageView(this);
iv.setImageResource(R.drawable.logo);
LinearLayout .LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
iv.setLayoutParams(lp);
ll1.addView(iv);
rlmain.addView(ll1);
setContentView(rlmain, llp);
You can also add any number of views.
LinearLayout is a subclass of ViewGroup, which has a method called addView. The addView method should be what you are after.
The idea of programmatically setting constraints can be tiresome. This solution below will work for any layout whether constraint, linear, etc. Best way would be to set a placeholder i.e. a FrameLayout with proper constraints (or proper placing in other layout such as linear) at position where you would expect the programmatically created view to have.
All you need to do is inflate the view programmatically and it as a child to the FrameLayout by using addChild() method. Then during runtime your view would be inflated and placed in right position. Per Android recommendation, you should add only one childView to FrameLayout [link].
Here is what your code would look like, supposing you wish to create TextView programmatically at a particular position:
Step 1:
In your layout which would contain the view to be inflated, place a FrameLayout at the correct position and give it an id, say, "container".
Step 2
Create a layout with root element as the view you want to inflate during runtime, call the layout file as "textview.xml" :
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
</TextView>
BTW, set the layout-params of your frameLayout to wrap_content always else the frame layout will become as big as the parent i.e. the activity i.e the phone screen.
android:layout_width="wrap_content"
android:layout_height="wrap_content"
If not set, because a child view of the frame, by default, goes to left-top of the frame layout, hence your view will simply fly to left top of the screen.
Step 3
In your onCreate method, do this :
FrameLayout frameLayout = findViewById(R.id.container);
TextView textView = (TextView) View.inflate(this, R.layout.textview, null);
frameLayout.addView(textView);
(Note that setting last parameter of findViewById to null and adding view by calling addView() on container view (frameLayout) is same as simply attaching the inflated view by passing true in 3rd parameter of findViewById(). For more, see this.)
One more way to add view from Activity
ViewGroup rootLayout = findViewById(android.R.id.content);
rootLayout.addView(view);
You guys should also make sure that when you override onLayout you HAVE to call super.onLayout with all of the properties, or the view will not be inflated!

Categories

Resources