Почему параметры макета работают в программировании на Android?

#java #android #android-layout

#java #Android #android-layout

Вопрос:

Начнем с моей предыстории: я новичок в Java, перешедший из Ruby. Если это поможет.

Я не понимаю, как работают параметры макета. Я следую базовому введению Hello World в создание приложения для Android. Шаг 1, расширьте класс Activity и метод onCreate() для доступа к XML-макету. Хорошо, я понял это.

Затем я создаю макет (скажем, RelativeLayout) в Main.XML . Итак, здесь используется класс RelativeLayout, который расширяет класс ViewGroup, пока все в порядке. Тогда, допустим, я создаю кнопку внутри этого. Здесь начинается мой вопрос. Если я посмотрю на следующий пример, я увижу, что кнопке присваиваются атрибуты, которые принадлежат классу RelativeLayout (т.е. android:layout_alignParentRight=»true»). Похоже, это параметры макета. Но почему это работает? Класс button, похоже, наследуется от класса View. Почему объект button может принимать атрибуты для объекта RelativeLayout? Возможно, мое программирование на Ruby сбивает меня с толку..

Спасибо!

Обновление: Ради потомков: спасибо Slothsberry за указание ссылки на XML Layouts, которая, по-видимому, четко описывает ответ в двух разделах — разделе «Атрибуты» и «Параметры макета». Раздел атрибутов гласит:

Каждый объект View и ViewGroup поддерживает свои собственные атрибуты XML. Некоторые атрибуты специфичны для объекта View (например, TextView поддерживает атрибут textSize), но эти атрибуты также наследуются любыми объектами View, которые могут расширять этот класс. Некоторые из них являются общими для всех объектов View, потому что они унаследованы от корневого класса View (например, атрибут id). И другие атрибуты считаются «параметрами макета», которые являются атрибутами, описывающими определенные ориентации макета объекта View, как определено родительским объектом ViewGroup этого объекта.

Раздел параметров макета, возможно, действительно отвечает на этот вопрос. Где говорится:

Каждый класс ViewGroup реализует вложенный класс, который расширяет ViewGroup.Параметры макета. Этот подкласс содержит типы свойств, которые определяют размер и положение для каждого дочернего представления, в зависимости от группы представлений. Как вы можете видеть на рисунке 1, родительская группа представлений определяет параметры макета для каждого дочернего представления (включая дочернюю группу представлений).

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

Комментарии:

1. Нет, вы правы, считая это странным. Я программирую на Java более 5 лет, и это то, что, когда я впервые увидел, не имело для меня никакого смысла. Я все еще не уверен, почему это работает так. Надеюсь, мы получим ответ.

2. developer.android.com/reference/android/view/View.html#Layout

Ответ №1:

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

Таким образом, такие параметры, как android:layout_below, будут игнорироваться, если родительский макет не является RelativeLayout. С точки зрения ООП может иметь смысл поместить этот параметр в объект RelativeLayout . Но именно так вы бы сделали это в коде Java.

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

Комментарии:

1. Спасибо, вы четко поняли мое непонимание и дали отличный ответ. Я добавил примечания в свой вопрос для потомков, основываясь на некоторых дальнейших чтениях. Ценю это.

2. Понимание «инфляции» макета, похоже, также является ключом к пониманию .. еще немного чтения, которое я нашел на основе вашего ответа: androidguys.com/2008/07/09/inflation-is-a-good-thing

3. Я считаю, что сами свойства макета наследуются строгим образом, аналогично наследованию классов. Однако то, что Android делает с ними, похоже, варьируется в зависимости от (по крайней мере) родительского элемента. В общем, поскольку вы создаете макеты от корня вниз (если вы не используете повторно includes, у которых уже установлены собственные свойства), вы можете просто игнорировать неподходящие свойства для ваших элементов. Я даже не заметил, что layout_below был доступен все время, поскольку я никогда не смотрел на него, если только я не был в RelativeLayout

Ответ №2:

Все элементы макета в Android наследуются от View, хотя многие и косвенно.

Универсальный класс View имеет свойства (attributes), подходящие для ЛЮБОГО видимого элемента макета. для корневого макета некоторые свойства, такие как плотность макета, размеры макета и т.д., Устанавливаются системой (я полагаю, в большинстве случаев).

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

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

Комментарии:

1. Спасибо, что добавили к обсуждению. Хотя я не смог полностью разобраться в проблеме из вашего ответа, ваша ссылка на XML Layouts дала мне то, что мне было нужно. Я обновил свой вопрос выше, включив в него то, как я разрешил свое понимание. Вы можете дать мне знать, если это кажется правильным. 🙂

Ответ №3:

вы немного сбиты с толку, что параметру макета не принадлежит определенный объект XML. Если вы поместите это в один дочерний XML XXXView или XXXLAyout , он поймет, что его правая сторона должна находиться в том же месте, что и родительская правая.

Тогда, если вы не создадите параметры макета для этого дочернего элемента, дочерний элемент попытается наследовать параметры своего родителя.

Комментарии:

1. Спасибо за ответ. Возможно, вы можете помочь мне понять с точки зрения Android / Java. Объекты в Android имеют атрибуты, да? Я бы предположил, что у всех атрибутов есть объект-владелец, да? Когда я создаю тег button, вы говорите, что не все атрибуты, определенные в теге button, принадлежат объекту button. Это правильно?

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

Ответ №4:

Макет

Верстка — это двухпроходный процесс: прохождение измерения и прохождение макета. Этап измерения реализован в measure(int, int) и представляет собой обход дерева представления сверху вниз. Каждое представление перемещает спецификации размеров вниз по дереву во время рекурсии. В конце прохода измерения каждое представление сохраняет свои измерения. Второй проход выполняется в layout(int, int, int, int) и также сверху вниз. Во время этого этапа каждый родительский элемент отвечает за позиционирование всех своих дочерних элементов, используя размеры, вычисленные на этапе измерения.

Когда возвращается метод measure() представления, должны быть установлены его getMeasuredWidth() и getMeasuredHeight() значения, а также значения для всех потомков этого представления. Измеренные значения ширины и высоты представления должны соответствовать ограничениям, налагаемым родителями представления. Это гарантирует, что в конце прохождения измерения все родители примут все измерения своих детей. Родительский вид может вызывать measure () более одного раза для своих дочерних элементов. Например, родитель может измерить каждого дочернего элемента один раз с неопределенными размерами, чтобы выяснить, насколько большими они хотят быть, затем снова вызвать для них measure () с фактическими числами, если сумма всех неограниченных размеров дочерних элементов слишком велика или слишком мала.

Передача measure использует два класса для передачи измерений. View.MeasureSpec Класс используется представлениями, чтобы сообщить своим родителям, как они хотят, чтобы их измеряли и позиционировали. Базовый класс LayoutParams просто описывает, насколько большим должно быть представление как по ширине, так и по высоте. Для каждого измерения он может указывать одно из:

  • точное число
  • MATCH_PARENT, что означает, что представление должно быть таким же большим, как его родительский элемент (минус заполнение)
  • WRAP_CONTENT , что означает, что представление должно быть достаточно большим, чтобы вместить его содержимое (плюс дополнение).

Существуют подклассы LayoutParams для разных подклассов ViewGroup. Например, AbsoluteLayout имеет свой собственный подкласс LayoutParams, который добавляет значения X и Y.

MeasureSpecs используются для передачи требований вниз по дереву от родительского элемента к дочернему. Параметр MeasureSpec может находиться в одном из трех режимов:

  • НЕ УКАЗАНО: это используется родителем для определения желаемого размера дочернего представления. Например, LinearLayout может вызвать функцию measure() для своего дочернего элемента с высотой, установленной в НЕУКАЗАННОЕ значение, и шириной РОВНО 240, чтобы выяснить, какой высоты дочерний вид хочет, чтобы ему была присвоена ширина в 240 пикселей.
  • ТОЧНО: это используется родителем для наложения точного размера на дочерний элемент. Дочерний элемент должен использовать этот размер и гарантировать, что все его потомки будут соответствовать этому размеру.
  • AT_MOST: Это используется родительским для наложения максимального размера на дочерний элемент. Дочерний элемент должен гарантировать, что он и все его потомки будут соответствовать этому размеру.

Чтобы запустить макет, вызовите requestLayout() . Этот метод обычно вызывается представлением о самом себе, когда оно считает, что is больше не может вписываться в его текущие границы.