Setting a Maximum Width on a Viewgroup

Setting a maximum width on a ViewGroup

One option which is what I did is to extend LinearLayout and override the onMeasure function. For example:

public class BoundedLinearLayout extends LinearLayout {

private final int mBoundedWidth;

private final int mBoundedHeight;

public BoundedLinearLayout(Context context) {
super(context);
mBoundedWidth = 0;
mBoundedHeight = 0;
}

public BoundedLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BoundedView);
mBoundedWidth = a.getDimensionPixelSize(R.styleable.BoundedView_bounded_width, 0);
mBoundedHeight = a.getDimensionPixelSize(R.styleable.BoundedView_bounded_height, 0);
a.recycle();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Adjust width as necessary
int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
if(mBoundedWidth > 0 && mBoundedWidth < measuredWidth) {
int measureMode = MeasureSpec.getMode(widthMeasureSpec);
widthMeasureSpec = MeasureSpec.makeMeasureSpec(mBoundedWidth, measureMode);
}
// Adjust height as necessary
int measuredHeight = MeasureSpec.getSize(heightMeasureSpec);
if(mBoundedHeight > 0 && mBoundedHeight < measuredHeight) {
int measureMode = MeasureSpec.getMode(heightMeasureSpec);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(mBoundedHeight, measureMode);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}

Then you XML would use the custom class:

<com.yourpackage.BoundedLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:bounded_width="900dp">

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</com.youpackage.BoundedLinearLayout>

And the attr.xml file entry

<declare-styleable name="BoundedView">
<attr name="bounded_width" format="dimension" />
<attr name="bounded_height" format="dimension" />
</declare-styleable>

EDIT: This is the actual code I am using now. This is still not complete but works in most cases.

how to set max Width for a Layout

The appropriate way to handle your situation is to create a separate layout file to optimize your form view for tablets while using the existing file for phones. You do this by creating separate res/layout directories with qualifiers for screen size and/or resolution attached to them.

You can read more about the available resource qualifiers here. There are a number of choices here and I will leave it to you to pick the best for your application, but here is a simple example:

Let's assume your current layout file is form.xml.

Place your existing layout file in res/layout/form.xml. This will make it the default layout.

Create another file and place it in res/layout-large/form.xml. This layout file will be used on devices with a physical screen size > ~5" (all standard tablets). To handle your issue, I have modified your default layout to display the form centered horizontally and only take up 60% of the screen width:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/adlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:gravity="center_horizontal"
android:weightSum="1" >

<TableLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.6"
android:stretchColumns="1" >

<TableRow android:id="@+id/tableRow1">

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="6dip"
android:text="Barcode Format" >
</TextView>

<EditText
android:id="@+id/edit_barcode_format"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="6dip" >
</EditText>
</TableRow>

<TableRow android:id="@+id/tableRow1">

<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="6dip"
android:text="Barcode Type" >
</TextView>

<EditText
android:id="@+id/edit_barcode_type"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="6dip" >
</EditText>
</TableRow>
</TableLayout>

</LinearLayout>

The change utilizes the layout_weight and weightSum properties of LinearLayout, which tell the table to only fill 60% (layout_weight=0.6) of its parent. This is more efficient than try to set a maximum width, especially when devices have variable resolutions and aspect ratios.

FYI, I also tried to remove as many of the unnecessary attributes that you had in your XML that were doing nothing but creating clutter (such as multiple xmlns:android declarations). One of those changes was removing extra layout_ parameters from the TableLayout children, because TableLayout ignores all these parameters anyway and forces its children to use certain constraints. From the Docs:

The children of a TableLayout cannot specify the layout_width attribute. Width is always MATCH_PARENT. However, the layout_height attribute can be defined by a child; default value is WRAP_CONTENT. If the child is a TableRow, then the height is always WRAP_CONTENT.

You can read more about TableLayout in the SDK docs.

HTH

Setting a max width for LinearLayout

This does it - what I needed beyond what was suggested in prior answer is to add another layout (@+id/TheLayout) as a wrapper between the content and the top layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="100dip"
android:paddingRight="100dip">
<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/TheLayout"
android:layout_gravity="right">
<TextView android:id="@+id/TextView01"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="1"
android:text="this is my text."
android:layout_gravity="center_vertical">
</TextView>
<ImageView android:id="@+id/ImageView01"
android:layout_height="wrap_content"
android:background="@drawable/icon"
android:layout_width="fill_parent">
</ImageView>
</LinearLayout>
</LinearLayout>

How to use android:maxWidth?

I want to set a maximum width of an edit box.

In your example:

<EditText 
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ems="10" />

The layout_width and ems attributes are trying to set the same value. Android seems to choose the larger fill_parent value and ignores the other. And when you use this:

<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:maxWidth="50dp"
android:minWidth="50dp" />

Here ems and maxWidth are trying to set the same value, again the greater value is used. So depending on what you actually want you can use:

<EditText 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10" />

or replace android:ems="10" with android:maxWidth="50dp" if you prefer to work with dp.

Lastly your LinearLayout only has one child, the EditText. Typically when this happens you can remove the LinearLayout tags and use the EditText by itself.

Combine layout_weight and maxWidth for views

I don't have Eclipse here to test it, but I would use a RelativeLayout instead, something like:

<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<View
android:id="@+id/centerView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
/>
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/centerView"
android:enabled="false"
android:textStyle="bold"
android:text="@string/button1"
/>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/centerView"
android:text="@string/button2"
/>
</RelativeLayout>

As I said, I can't test it right now, but you can work around this idea.

On a side note, unless your layout is very simple, I usually create separate layouts for landscape. It's a little more work, but you can optimize the views much better that way. Specially, if you plan to support larger screens.

how to set max Width for a Layout

The appropriate way to handle your situation is to create a separate layout file to optimize your form view for tablets while using the existing file for phones. You do this by creating separate res/layout directories with qualifiers for screen size and/or resolution attached to them.

You can read more about the available resource qualifiers here. There are a number of choices here and I will leave it to you to pick the best for your application, but here is a simple example:

Let's assume your current layout file is form.xml.

Place your existing layout file in res/layout/form.xml. This will make it the default layout.

Create another file and place it in res/layout-large/form.xml. This layout file will be used on devices with a physical screen size > ~5" (all standard tablets). To handle your issue, I have modified your default layout to display the form centered horizontally and only take up 60% of the screen width:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/adlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:gravity="center_horizontal"
android:weightSum="1" >

<TableLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.6"
android:stretchColumns="1" >

<TableRow android:id="@+id/tableRow1">

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="6dip"
android:text="Barcode Format" >
</TextView>

<EditText
android:id="@+id/edit_barcode_format"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="6dip" >
</EditText>
</TableRow>

<TableRow android:id="@+id/tableRow1">

<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="6dip"
android:text="Barcode Type" >
</TextView>

<EditText
android:id="@+id/edit_barcode_type"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="6dip" >
</EditText>
</TableRow>
</TableLayout>

</LinearLayout>

The change utilizes the layout_weight and weightSum properties of LinearLayout, which tell the table to only fill 60% (layout_weight=0.6) of its parent. This is more efficient than try to set a maximum width, especially when devices have variable resolutions and aspect ratios.

FYI, I also tried to remove as many of the unnecessary attributes that you had in your XML that were doing nothing but creating clutter (such as multiple xmlns:android declarations). One of those changes was removing extra layout_ parameters from the TableLayout children, because TableLayout ignores all these parameters anyway and forces its children to use certain constraints. From the Docs:

The children of a TableLayout cannot specify the layout_width attribute. Width is always MATCH_PARENT. However, the layout_height attribute can be defined by a child; default value is WRAP_CONTENT. If the child is a TableRow, then the height is always WRAP_CONTENT.

You can read more about TableLayout in the SDK docs.

HTH



Related Topics



Leave a reply



Submit