Как определить размер представления Android в зависимости от размеров его родителя - PullRequest
99 голосов
/ 29 января 2010

Как определить размер представления в зависимости от размера его родительского макета. Например, у меня есть RelativeLayout, который заполняет весь экран, и я хочу, чтобы дочерний вид, скажем, ImageView, занимал всю высоту и 1/2 ширины?

Я пытался переопределить все на onMeasure, onLayout, onSizeChanged и т. Д., И я не смог заставить его работать ....

Ответы [ 10 ]

122 голосов
/ 12 января 2011

Я не знаю, читает ли кто-нибудь эту ветку или нет, но решение Джеффа приведет вас только на полпути (в буквальном смысле). То, что сделает его onMeasure, это отобразит половину изображения пополам родительского. Проблема в том, что вызов super.onMeasure до setMeasuredDimension будет измерять все дочерние элементы в представлении на основе исходного размера, а затем просто разрезать представление пополам, когда setMeasuredDimension изменит его размер.

Вместо этого вам нужно позвонить setMeasuredDimension (как требуется для переопределения onMeasure) и предоставить новый LayoutParams для вашего просмотра, , затем , позвонить super.onMeasure. Помните, что LayoutParams является производным от родительского типа вашего представления, а не от типа вашего представления.

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
   int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
   int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
   this.setMeasuredDimension(parentWidth/2, parentHeight);
   this.setLayoutParams(new *ParentLayoutType*.LayoutParams(parentWidth/2,parentHeight));
   super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

Я считаю, что единственный раз, когда у вас возникнут проблемы с родителем LayoutParams, это если родитель является AbsoluteLayout (что устарело, но иногда полезно).

39 голосов
/ 25 мая 2010

Вы можете решить эту проблему, создав собственный View и переопределив метод onMeasure (). Если вы всегда используете «fill_parent» для layout_width в вашем xml, тогда параметр widthMeasureSpec, который передается в метод onMeasusre (), должен содержать ширину родительского элемента.

public class MyCustomView extends TextView {

    public MyCustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
        this.setMeasuredDimension(parentWidth / 2, parentHeight);
    }
}   

Ваш XML будет выглядеть примерно так:

<LinearLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <view
        class="com.company.MyCustomView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
25 голосов
/ 28 ноября 2011

Я обнаружил, что лучше не возиться с настройкой измеренных размеров самостоятельно. На самом деле между родительским и дочерним представлениями происходит небольшое согласование, и вы не хотите переписывать все эти код .

Что вы можете сделать, это изменить меру specSpecs, а затем вызвать super с ними. Ваше мнение никогда не узнает, что получает измененное сообщение от своего родителя, и позаботится обо всем за вас:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
    int myWidth = (int) (parentHeight * 0.5);
    super.onMeasure(MeasureSpec.makeMeasureSpec(myWidth, MeasureSpec.EXACTLY), heightMeasureSpec);
}
15 голосов
/ 29 января 2010

Когда вы определяете макет и представление в XML, вы можете указать ширину и высоту макета для представления, которое будет переносить содержимое или заполнять родительский элемент. Занимать половину площади немного сложнее, но если у вас есть что-то, что вы хотели в другой половине, вы можете сделать что-то вроде следующего.

   <LinearLayout android:layout_width="fill_parent"
                android:layout_height="fill_parent">
        <ImageView android:layout_height="fill_parent"
                 android:layout_width="0dp"
                 android:layout_weight="1"/>
        <ImageView android:layout_height="fill_parent"
                 android:layout_width="0dp"
                 android:layout_weight="1"/>
   </LinearLayout>

Придание двум вещам одинакового веса означает, что они будут растягиваться, занимая одинаковую часть экрана. Для получения дополнительной информации о макетах см. документы разработчика.

9 голосов
/ 15 июля 2012

Я верю, что XML-подход Mayras может прийти в порядок. Тем не менее, можно сделать его более точным с помощью одного вида, только установив weightSum. Я бы больше не назвал это хаком, но, на мой взгляд, самый простой подход:

<LinearLayout android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:weightSum="1">
    <ImageView android:layout_height="fill_parent"
               android:layout_width="0dp"
               android:layout_weight="0.5"/>
</LinearLayout>

Таким образом, вы можете использовать любой вес, например 0,6 (и центрирование) - это вес, который мне нравится использовать для кнопок.

3 голосов
/ 31 мая 2015

Попробуйте это

int parentWidth = ((parentViewType)childView.getParent()).getWidth();
int parentHeight = ((parentViewType)childView.getParent()).getHeight();

тогда вы можете использовать LinearLayout.LayoutParams для установки параметров chileView

LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(childWidth,childLength);
childView.setLayoutParams(params);
2 голосов
/ 13 сентября 2016

Теперь вы можете использовать PercentRelativeLayout. Boom! Проблема решена.

1 голос
/ 21 июня 2011

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

Это работает в LinearLayout ...

1 голос
/ 10 февраля 2010

Роман, если вы хотите сделать свой макет в коде Java (потомок ViewGroup), это возможно. Хитрость заключается в том, что вам нужно реализовать методы onMeasure и onLayout. Сначала вызывается onMeasure, и вам нужно «измерить» там подпредставление (эффективно подгоняя его к желаемому значению). Вам нужно изменить размер снова в вызове onLayout. Если вы не выполните эту последовательность или не вызовете setMeasuredDimension () в конце кода onMeasure, вы не получите результатов. Почему это разработано таким сложным и хрупким способом, вне меня.

0 голосов
/ 09 октября 2014

Это примерно так:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.company.myapp.ActivityOrFragment"
    android:id="@+id/activity_or_fragment">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/linearLayoutFirst"
    android:weightSum="100">   <!-- Overall weights sum of children elements -->

    <Spinner
        android:layout_width="0dp"   <!-- It's 0dp because is determined by android:layout_weight -->
        android:layout_weight="50"
        android:layout_height="wrap_content"
        android:id="@+id/spinner" />

</LinearLayout>


<LinearLayout
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:layout_below="@+id/linearLayoutFirst"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:id="@+id/linearLayoutSecond">

    <EditText
        android:layout_height="wrap_content"
        android:layout_width="0dp"
        android:layout_weight="75"
        android:inputType="numberDecimal"
        android:id="@+id/input" />

    <TextView
        android:layout_height="wrap_content"
        android:layout_width="0dp"
        android:layout_weight="25"
        android:id="@+id/result"/>

</LinearLayout>
</RelativeLayout>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...