Inflate child with 0dp layout width & weight (programmatically) - android

Simple: I want to inflate parent with 1 child which has 0dp width.
Parent xml:
<com.example.KeyPad // extend LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="4" // for the children
android:layout_weight="1" // this is for its parent
android:clickable="true"
android:background="#color/MidnightBlue" >
The child class:
public class KeyButton extends RelativeLayout implements View.OnClickListener{
public KeyButton(Context c ) {
super(c);
RelativeLayout v = (RelativeLayout) LayoutInflater.from(c).inflate(R.layout.key_button, this, true);
}
}
}
which uses the R.layout.key_button xml:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_weight="1"
android:layout_width="0dp"
android:background="#android:color/holo_red_dark"
android:layout_height="wrap_content">
<TextView ... />
</RelativeLayout>
And the child is getting added by:
Parent.addView(new KeyButton(context) );
The problem is that android:layout_weight doesn't look to take action and the layout_width of the child stays at "0dp". If I change the width to 50dp I can see the child that has been correct inflated.
Also tried to add the parameters programmatically when getting added:
KeyButton bt = new KeyButton(context);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT,1.0f);
bt.setLayoutParams(lp);
Parent.addView(bt);
How can I inflate the child with 0dp/weight? Of course as you can see I have defined the weight_sum of the parent.

You have used a LinearLayout.LayoutParams but the parent of your button are a RelativeLayout.
Try this :
KeyButton bt = new KeyButton(context);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(0, RelativeLayout.LayoutParams.WRAP_CONTENT,1.0f);
Parent.addView(bt, lp);

You can simply set the visibility property to gone or hidden by following code :
bt.setVisibility(View.GONE);
You can find more information about setting views here

Related

Android - Wrap buttons within view

I am trying to make buttons wrap in a LinearLayout in Android, but they are just continuing off to the right of the view (the word shown in the screenshot should be "HELLO", so I want the "O" to drop down to the next line).
I am adding the buttons programmatically, but even if I code them into the XML layout file, they still don't wrap. Here is the layout file with the LinearLayout container into which I am dynamically adding the buttons:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constrainedWidth="true"
tools:context=".LetterTileView">
<LinearLayout
android:id="#+id/TilesContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constrainedWidth="true"
android:orientation="horizontal">
</LinearLayout>
And here is the code I am using to create and add the tile buttons:
Context context = this;
LinearLayout layout = (LinearLayout) findViewById(R.id.TilesContainer);
LayoutParams params = new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT );
params.setMargins(50, 50, 0, 0);
for (int i=0;i<wordLength;i++) {
Button tileButton = new Button(this);
tileButton.setLayoutParams(params);
tileButton.setText(wordStringtoLetters[i]);
tileButton.setId(i);
tileButton.setBackgroundResource(R.drawable.tile_button);
tileButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 36);
layout.addView(tileButton);
}
Any advice would be appreciated. Thanks!
I ended up using FlexboxLayout, which works great for this. Thanks to those who offered suggestions!
First of all, there is no need to use a ConstraintLayout you can use your LinearLayout as the parent layout.
Then for the purpose of displaying all buttons in one line, you have to set weight for the LinearLayout in XML and set weight for the views you add to it.
The xml file should look like:
<LinearLayout
android:id="#+id/TilesContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:weightSum="5"
app:layout_constrainedWidth="true"
android:orientation="horizontal">
</LinearLayout>
And in code you should set weight for each view you by adding ,1.0f to LayoutParam :
Context context = this;
LinearLayout layout = (LinearLayout) findViewById(R.id.TilesContainer);
LayoutParams params = new LayoutParams( LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT,1.0f );
params.setMargins(50, 50, 0, 0);
for (int i=0;i<wordLength;i++) {
Button tileButton = new Button(this);
tileButton.setLayoutParams(params);
tileButton.setText(wordStringtoLetters[i]);
tileButton.setId(i);
tileButton.setBackgroundResource(R.drawable.tile_button);
tileButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 36);
layout.addView(tileButton);
}

android margins not working when dynamically inserting views

I have a simple view:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/contact_selected"
android:layout_marginTop="10dp"
android:layout_marginEnd="5dp"
android:orientation="horizontal"
android:padding="3dp">
<TextView
android:id="#+id/txt_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Billy Bob"
/>
</LinearLayout>
When I statically copy the LinearLayout markup into my main activity layout, the margins are as expected. However, when I add the view into the main activity layout dynamically, the margins are ignored. Here's how I insert the view
LayoutInflater inflater = (LayoutInflater)
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.test, null);
TextView txt_title = (TextView)view.findViewById(R.id.txt_title);
txt_title.setText("Dynamic #1");
llayout.addView(view, llayout.getChildCount()-1);
View view2 = inflater.inflate(R.layout.test, null);
txt_title = (TextView)view2.findViewById(R.id.txt_title);
txt_title.setText("Dynamic #2");
llayout.addView(view2, llayout.getChildCount()-1);
Here's what it looks like:
The container in the main layout is a LinearLayout, which is a child of a HorizontalScrollView. Any insight is appreciated.
When dynamically adding views, you shouldn't inflate the View with a null ViewGroup parent. So, in other words you should be using inflater.inflate(R.layout.test, linearLayout, false);. The parent is used when determining what type of layout parameters to generate. Pass your parent container (in this case, your linear layout), so it correctly instantiates the ViewGroup.MarginLayoutParams from your XML.
This happens because you need to give "Margin" to layouts dynamically. You can do this by creating an object of "LayoutPrams", like this:-
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(30, 20, 30, 0);
Here , you can set the LayoutParams to the linearlayout:
ll.addView(okButton, layoutParams);
Hope it helps.
First, you have to get display density.
related docs are https://developer.android.com/reference/android/util/DisplayMetrics.html
and get ID which you want set margin view.
for my case,
layout_login_box = (ConstraintLayout)findViewById(R.id.login_layout_box);
float density = getResources().getDisplayMetrics().density;
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams)layout_login_box.getLayoutParams();
params.setMargins((int) (24 * density),0,(int) (24 * density),(int) (16 * density));
layout_login_box.setLayoutParams(params);
Also, you can change ConstraintLayout to your own view.

LinearLayout refuses to fill programmaticallycreated LinearLayout wrapper

I'm trying to get a linear layout from an XML file to completely fill up the content of another linear layout I've created programmatically but for some reason it will only take up the space it needs (WRAP_CONTENT, as it were).
Here's the XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<ImageView
android:id="#+id/app_dayheader_previous"
android:layout_width="36dp"
android:layout_height="18dp"
android:layout_margin="10dp"
android:clickable="true"
android:scaleType="center"
android:src="#drawable/leftarrow" />
<TextView
android:id="#+id/app_dayheader_title"
style="#style/titlebar_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center" />
<ImageView
android:id="#+id/app_dayheader_next"
android:layout_width="36dp"
android:layout_height="18dp"
android:layout_margin="10dp"
android:clickable="true"
android:scaleType="center"
android:src="#drawable/rightarrow" />
</LinearLayout>
And here's the code. There's a lot of indirection involved for architecture reasons, but basically what happens is this:
A child class inflates the XML file:
public class child {
public View getView(Context context) {
LayoutInflater inflater = LayoutInflater.from(context);
LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.dayheader, null);
return layout;
}
}
A parent class that extends LinearLayout calls the child class and adds the result of the call to getView to itself:
public class parent extends LinearLayout {
public parent(Context context) {
super(context);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
this.setLayoutParams(layoutParams);
this.setOrientation(LinearLayout.HORIZONTAL);
this.addView(new child().getView(context);
}
}
Finally, another class calls the parent class and adds it to yet another LinearLayout:
headerWrapper = new LinearLayout(context);
headerWrapper.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
));
headerWrapper.setOrientation(LinearLayout.HORIZONTAL);
headerWrapper.addView(new parent(context));
As far as I can tell, all these linear layouts should fill the maximum available width in their respective parents and this is exactly what headerWrapper and the parent class do. However, the linear layout in the XML file (the one returned by child.getView()) does not. Which has me puzzled, as it has exactly the same parameters as the other ones. And yet the only space it takes up is the space it needs rather than filling up its parent.
Does anybody have any idea what I'm missing here?
In order for the layout weight of 1 to take effect, you'll need to set the dimension of that axis to 0px. Try this:
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 1f);

Linearlayout overlay another linearlayout

I have some problem with add linearlayout dynamically. It's add on the top of screen, overlay other linearlayout.
Here XML,code and results.
XML:
<TextView
android:id="#+id/top_km"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="#888"
android:gravity="top"
android:textColor="#fff"
android:textSize="30dip"
android:layout_centerHorizontal="true"/>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#+id/top_km"
android:id="#id/textLayout">
</RelativeLayout>
Code:
myLayout = (RelativeLayout) page.findViewById(R.id.textLayout);
LinearLayout linLayout = new LinearLayout(this);
linLayout.setOrientation(LinearLayout.VERTICAL);
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
myLayout.addView(linLayout);
LinearLayout hozLayout = new LinearLayout(this);
hozLayout.setOrientation(LinearLayout.HORIZONTAL);
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
myLayout.addView(hozLayout);
Results:
enter link description here
Thanks
Don't use a RelativeLayout as your holder. Use a LinearLayout with orientation="vertical" instead.
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#+id/top_km"
android:orientation="vertical"
android:id="#id/textLayout" />
then in code
myLayout = (LinearLayout) page.findViewById(R.id.textLayout);
followed by
// rest of your code
It's because you use RealativeLayout for proper adding use
1. RelativeLayout.LayoutParams for st LayoutParams
2. In LayoutParams use field below
Example:
RelativeLayout rl=new RelativeLayout(this);
LinearLayout ll1=new LinearLayout(this);
TextView tx1=new TextView(this);
tx1.setText("Test1");
ll1.addView(tx1);
rl.addView(ll1);
LinearLayout ll2=new LinearLayout(this);
TextView tx2=new TextView(this);
tx2.setText("Test1");
ll2.addView(tx1);
rl.addView(ll2);
RelativeLayout.LayoutParams lp2=(LayoutParams) ll2.getLayoutParams();
And then use lp2.addRule
Here some help:
Parameters
verb One of the verbs defined by RelativeLayout, such as ALIGN_WITH_PARENT_LEFT.
anchor The id of another view to use as an anchor, or a boolean value(represented as TRUE) for true or 0 for false). For verbs that don't refer to another sibling (for example, ALIGN_WITH_PARENT_BOTTOM) just use -1.
Maybe it's easier for you to add it in the XML file with android:visibility="GONE" and then in the code just show it (View.VISIBLE) or hide it (View.GONE).

The content of a LinearLayout isn't visible

I tried to add some GUI elements like an ImageView or a TextView to a LinearLayout programmatically. But the elements aren't displayed.
To see if a element is drawn or not, I set a different background color for each element. The result was that I can only see the background color of the LinearLayout. But why?
public class MyLinearLayout extends LinearLayout {
public MyLinearLayout(Context context) {
super(context);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
setLayoutParams(params);
setBackgroundColor(Color.RED);
imageView = new ImageView(context);
params = new LinearLayout.LayoutParams(100, 100);
imageView.setLayoutParams(params);
imageView.setBackgroundColor(Color.BLUE);
addView(imageView);
}
}
The strange thing is that I can see the red background color of the LinearLayout but in the size of the ImageView. If I add some other GUI elements like a TextView, I can see how the LinearLayout grows. But I can not see the TextView.
I'm really confused, because this not the first time I do something like this. Can u tell me what I'm doing wrong?
This is a snippet of the layout.xml file:
<LinearLayout android:layout_width="match_parent"
android:layout_height="45dp"
android:id="#+id/bottom_bar"
android:layout_alignParentBottom="true"
android:gravity="bottom">
<FrameLayout android:id="#+id/block_edit_delete_layout"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:background="#drawable/block_edit_delete_selector">
<ImageView android:layout_height="match_parent"
android:layout_width="wrap_content"
android:src="#drawable/block_edit_delete"
android:scaleType="fitXY"
android:contentDescription="#string/delete"/>
</FrameLayout>
<LinearLayout
android:id="#+id/block_edit_progress"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="horizontal"/>
<FrameLayout android:id="#+id/block_edit_random_layout"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:background="#drawable/block_edit_delete_selector">
<ImageView android:layout_height="match_parent"
android:layout_width="wrap_content"
android:src="#drawable/block_edit_random"
android:scaleType="fitXY"
android:contentDescription="#string/random_numbers"/>
</FrameLayout>
</LinearLayout>
The LinearLayout with the ID block_edit_progress is the container layout of multiple instances of the class MyLinearLayout. The instances are added in the code:
for(int i = 0; i < numberOfMyLinearLayouts; i++) {
MyLinearLayout v = new MyLinearLayout(getContext());
addView(v);
}
I hope this helps.
If i convert your code to xml, it would be something like:
<LinearLayout layout_width=wrap_content, layout_height = wrap_content>
<LinearLayout id= MyLinearLayout>//just an idea, syntax may be wrong
<LinearLayout layout_width= 100, layout_width=100>
<ImageView color=BLUE>
</ImageView>
</LinearLayout>
</LinearLayout>
</LinearLayout>
Whenever you call setLayoutParams on a View, parameter params you give should be parent element.
Try something like if you want linearlayout to be the parent of your linearlayout, use MATCH_PARENT for width, height if you want your view to span the width, height of view's parent
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
setLayoutParams(lp);//lp is parent view
Also try this, just in case views are getting added to right of your views, and you are not able to see them on screen
yourview.setOrientation(LinearLayout.VERTICAL);
Change the width and height of linear layout to match_parent and see how it changes. wrap_content will only show the content of the linear layout, which seems to be your problem.
I solved the problem. (Or found a workaround)
I moved the complete initialization stuff out of the constructor of the MyLinearLayout. If I then adding a View after the layout has been completely generated, everything works.
Like this:
MyLinearLayout ll = new MyLinearLayout(getContext());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(100, 100);
ll.setLayoutParams(params);
ll.setBackgroundColor(Color.RED);
ImageView v = new ImageView(getContext());
params = new LinearLayout.LayoutParams(50, 50);
v.setLayoutParams(params);
v.setBackgroundColor(Color.GREEN);
ll.addView(v);
addView(ll);
I don't know why the other way doesn't work. Thanks for the fast answers!

Categories

Resources