Подтвердить что ты не робот

RelativeLayout выровнять родительский * боковой * + margin * side *

Я заметил странное поведение в RelativeLayout, когда вы выравниваете представление со стороной макета (любая сторона) и имеет большой запас в том же направлении.

У меня есть 2 RelativeLayouts, каждый из которых содержит простой вид. В одном макете этот вид совпадает с верхним и левым, а другой - снизу и справа:

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

    <RelativeLayout 
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginTop="110dp"
        android:layout_gravity="center"
        android:background="#ff555555" >

        <View
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:background="#aa8711" />     
    </RelativeLayout>

    <RelativeLayout 
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginBottom="110dp"
        android:layout_gravity="center"
        android:background="#ff555555" >

        <View
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:background="#998877" />         
     </RelativeLayout>      
</FrameLayout>

Он выглядит следующим образом:

basic setup

Я добавил 130dp поля в каждом направлении выравнивания родительских элементов. Это означает, что представление должно быть только частично видимым в макете. Вот что происходит:

130dp in each direction of alignment

Как вы можете видеть, теперь размеры меньше размера оригинала, так как нажимают на "стены" макета. Затем я попытался дать маржу, которая больше, чем макет, поэтому я дал им 151dp поля в выровненных направлениях. Это выглядело так:

enter image description here

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

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

Вопрос один: Может ли кто-нибудь объяснить это непоследовательное поведение?

Я пробовал то же самое, на этот раз сравнивая поведение с FrameLayout. Начальная настройка:

enter image description here

и после полей:

enter image description here

FrameLayout сохраняет вид в своем первоначальном размере во все времена и просто позволяет виду "выйти". Я попытался дать отрицательный запас в противоположном направлении, по крайней мере, размера представления, которое должно быть вне RelativeLayout, и по умолчанию было такое же поведение, что и в FrameLayout.

Вопрос 2: Может ли кто-нибудь объяснить разницу в поведении и противоположный эффект отрицательного поля?

4b9b3361

Ответ 1

Почему это должно быть только частично видимым?

Я добавил 130dp поля в каждом направлении выравнивания родительских элементов. Что означает, что представление должно быть только частично видимым в макете

Коробка становится меньше, потому что предпочтение отдается сохранению ее внутри родительского макета любой ценой, но при этом применяется маржа. Поскольку размер представления меньшего размера 50dp, вы добавили запас 130dp, общая ширина, которая ему нужна, равна 180dp, но только родительское представление имеет ширину 150dp. Это 130dp + 50dp > 150dp - дочерний элемент плюс поле не может помещаться внутри родителя.

Это "глупый вход", и интерпретатор XML делает все возможное, чтобы что-то сделать. Решение, которое оно делает в итоге, состоит в том, что оно может изменить ширину дочернего окна и по-прежнему соблюдать ограничение по границам. Или математически

130dp + 20dp == 150dp

В основном, он сокращает ширину внутреннего блока вниз от назначенного 50dp до 20dp, чтобы он мог поместиться внутри родителя с его добавленным запасом. И если вы посмотрите на размер квадрата 20dp, он будет выглядеть правильно. Это на 60% меньше.

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

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

Когда вы говорите, что "это должно быть частично видимым", я полагаю, вы считаете, что ребенок будет отображать половину внутри родительских границ и половину вне границ родителя, подобно разработке форм в Windows. Это не так, потому что он всегда будет стараться держать детей в пределах родителей в большинстве макетов.

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


Во втором случае:

поэтому я дал им 151dp поля в выровненных направлениях.

Вы переходите от точки, в которой интерпретатор может сжимать изображение. Он не может сжать изображение до отрицательного 1. Это

50dp + 151dp > 150dp

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

Еще раз, это глупый ввод, и интерпретатор делает все возможное, чтобы сделать то, что вы хотите.


Может ли кто-нибудь объяснить разницу в поведении и противоположный отрицательный эффект маржи?

Отрицательный запас будет делать разные вещи в зависимости от типа макета в родительском объекте и выравнивается. В макете кадра он будет относиться по-разному к относительной компоновке. Обычно, если вы смотрите на негативные макеты, вы выбрали неправильные родительские контейнеры, и вы пытаетесь взломать его, чтобы заставить его выглядеть правильно.

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

Вы не были бы первым человеком, который был бы совершенно смущен макетами Android в Android. Вложенные макеты внутри макетов всегда сбивают с толку, и поведение меняется в зависимости от ряда вещей, таких как поля, выравнивания, ширины и т.д. Большинство людей, которых я знаю, просто обманывают его, пока оно не будет правильным, и попробуйте разные типы макета контейнера, чтобы получить правильный дизайн,

Короче говоря, избегайте играть с полями (например, flash или winforms) и играйте без макетов, вместо этого, чтобы получить то, что вам нужно.

надеюсь, что это поможет, извините за tl; dr.