Установка максимальной ширины в ViewGroup - PullRequest
58 голосов
/ 04 мая 2011

Как установить максимальную ширину ViewGroup? Я использую упражнение Theme.Dialog, однако, оно не выглядит так хорошо при изменении размера на большие экраны, оно также немного облегчено, и я не хочу, чтобы оно занимало весь экран.

Я пытался это предложение безрезультатно. Также нет свойства android:maxWidth, как у некоторых представлений.

Есть ли способ ограничить корневую линию LinearLayout, чтобы она была (например, только для 640 провалов)? Я готов перейти на другую ViewGroup для этого.

Есть предложения?

Ответы [ 6 ]

88 голосов
/ 02 июня 2011

Один из вариантов, который я сделал, - это расширение LinearLayout и переопределение функции onMeasure.Например:

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);
    }
}

Тогда вы XML будете использовать пользовательский класс:

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

И запись в файле attr.xml

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

РЕДАКТИРОВАТЬ: Этофактический код, который я использую сейчас.Это все еще не завершено, но работает в большинстве случаев.

29 голосов
/ 25 июля 2012

Вот лучший код для ответа Дори.

В методе onMeasure, если вы сначала вызовете super.onMeasure(widthMeasureSpec, heightMeasureSpec); в методе, тогда ширина всех объектов в макете не изменится.Потому что они инициализируются до того, как вы установите ширину макета (родителя).

public class MaxWidthLinearLayout extends LinearLayout {
    private final int mMaxWidth;

    public MaxWidthLinearLayout(Context context) {
        super(context);
        mMaxWidth = 0;
    }

    public MaxWidthLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MaxWidthLinearLayout);
        mMaxWidth = a.getDimensionPixelSize(R.styleable.MaxWidthLinearLayout_maxWidth, Integer.MAX_VALUE);
        a.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
        if (mMaxWidth > 0 && mMaxWidth < measuredWidth) {
            int measureMode = MeasureSpec.getMode(widthMeasureSpec);
            widthMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxWidth, measureMode);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

А вот ссылка на использование xml attr:http://kevindion.com/2011/01/custom-xml-attributes-for-android-widgets/

Спасибо за этот вопрос и ответы.Ваш ответ мне очень помог, и я надеюсь, что он поможет и кому-то еще в будущем.

29 голосов
/ 23 декабря 2011

Опираясь на исходный ответ Чейза (+1), я бы сделал пару изменений (обрисовано в общих чертах ниже).

  1. Я бы установил максимальную ширину через пользовательскийатрибут (xml под кодом)

  2. Сначала я вызову super.measure(), а затем проведу сравнение Math.min(*).Используя исходный код ответов, мы можем столкнуться с проблемами, если входящий размер, установленный в MeasureSpec, равен либо LayoutParams.WRAP_CONTENT, либо LayoutParams.FILL_PARENT.Поскольку эти действительные константы имеют значения -2 и -1 соответственно, исходный Math.min(*) становится бесполезным, так как он сохранит эти значения в пределах максимального размера и скажет измеренное значение WRAP_CONTENT больше, чем наш максимальный размер, эта проверка не поймает его.Я полагаю, что ОП думал только о точных затемнениях (для которых он прекрасно работает)

    public class MaxWidthLinearLayout extends LinearLayout {
    
    private int mMaxWidth = Integer.MAX_VALUE;
    
    public MaxWidthLinearLayout(Context context) {
    
        super(context);
    }
    
    public MaxWidthLinearLayout(Context context, AttributeSet attrs) {
    
        super(context, attrs);
    
        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MaxWidthLinearLayout);
        mMaxWidth = a.getDimensionPixelSize(R.styleable.MaxWidthLinearLayout_maxWidth, Integer.MAX_VALUE);
    }
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //get measured height
        if(getMeasuredWidth() > mMaxWidth){
            setMeasuredDimension(mMaxWidth, getMeasuredHeight());
        }
    }
    }
    

и xml attr

    <!-- MaxWidthLinearLayout -->
    <declare-styleable name="MaxWidthLinearLayout">
        <attr name="maxWidth" format="dimension" />
    </declare-styleable>
7 голосов
/ 02 июня 2017

Теперь android.support.constraint.ConstraintLayout делает это проще. Просто оберните ваше представление (любого типа) с ConstraintLayout и установите следующие атрибуты для представления:

android:layout_width="0dp"
app:layout_constraintWidth_default="spread"
app:layout_constraintWidth_max="640dp"

http://tools.android.com/recent/constraintlayoutbeta5isnowavailable

3 голосов
/ 15 апреля 2014

Добавьте слой Outer Layout или Viewgroup в ваш текущий файл Layout.Высота и ширина этого макета будет максимальной высотой / шириной.Теперь ваш внутренний макет может быть настроен для переноса содержимого и ограничен внешним макетом.Например:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!-- OuterLayout to set Max Height and Width  -- Add this ViewGroup to your layout  File  -->
    <LinearLayout
        android:id="@+id/outerLayout"
        android:layout_width="650dp"
        android:layout_height="650dp"
        android:orientation="vertical" >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical" >
        </LinearLayout>
    </LinearLayout>
</LinearLayout>
0 голосов
/ 06 октября 2012

Вот простой ответ:

Ширина / Высота, кажется, всегда должны быть установлены вместе.На мой взгляд, это работает.

    <Button
        android:text="Center"
        android:layout_width="100dp"
        android:layout_height="fill_parent"
        android:id="@+id/selectionCenterButton"
        android:minWidth="50dp"
        android:minHeight="50dp"
        android:maxWidth="100dp"
        android:maxHeight="50dp"
        android:layout_weight="1" />

Родитель кнопки настроен на перенос содержимого, поэтому масштабируется, но не более 400 в ширину (4 кнопки).

...