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> 

Это выглядит так:

Базовая настройка

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

130dp в каждом направлении выравнивания

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

Введите описание изображения здесь

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

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

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

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

Введите описание изображения здесь

И после поля:

Введите описание изображения здесь

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

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

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

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

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

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

 130dp + 20dp == 150dp 

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

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

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

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

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


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

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

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

 50dp + 151dp > 150dp 

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

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


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

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

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

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

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

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