Android constraint layout vs linearlayout

Layout интерфейса приложения Android

В приложении Android контейнер компонентов имеет тип ViewGroup. Существует несколько разновидностей классов, наследующих свойства ViewGroup и определяющих структуру расположения компонентов в интерфейсе : LinearLayout, RelativeLayout, FrameLayout, TableLayout, ConstraintLayout и т.д. Отличия этих классов связаны с упорядочиванием компонентов :

ConstraintLayout позволяет привязывать компонент к границам экрана или к другим компонентам.
LinearLayout позволяет размещать View-компоненты в виде одной строки (horizontal) или одного столбца (vertical).
RelativeLayout настраивает положение каждого компонента относительно других.
AbsoluteLayout использует для каждого компонента явную позицию на экране в системе координат X, Y.
TableLayout отображает элементы в виде таблицы, по строкам и столбцам.

Рассмотрим вопрос привязки компонентов в ConstraintLayout. Для этого создадим новое приложение p02layout по типу и подобию, описанному на странице Модули Android.

Привязка компонента в ConstraintLayout

Во вновь созданном проекте p02layout откроем модуль activity_main.xml в режиме Design и удалим включаемый по умолчанию компонент TextView с текстом «Hello World!», поскольку ему не требуется привязка; она создана студией. После этого добавим новый компонент TextView из палитры (Pallete) в интерфейс окна.

Если переключиться на текстовое представление модуля activity_main.xml, то можно сразу же увидить, что :

  • в качестве контейнера компонентов студия использовала при создании приложения ConstraintLayout;
  • компонент TextView подчеркнут красной линией.

При наведении на TextView мышкой во всплывающей подсказке Android Studio покажет ошибку :

This view is not constrained, it only has designtime positions, so it will jump to (0,0) unless you add constraints.

Этим сообщением IDE подсказывает нам, что компонент не «привязан», и его текущее положение в интерфейсе актуально только на время разработки. А при старте приложения положение компонента будет проигнорировано, и View переместится в точку (0,0), т.е. в верхний левый угол. Чтобы зафиксировать положение View в определенном месте ConstraintLayout необходимо добавить привязки (constraints). Они будут задавать положение View на экране относительно каких-либо других элементов или относительно родительского View.

Как добавить привязки?

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

Чтобы привязать компонент к левой стороне экрана по горизонтали выделите его левой кнопкой мыши, после этого тащите левый круг к левой границе экрана. Как только стрелка коснется левой границы экрана, то компонент также сразу же переместиться к левой стороне экрана. Изображение курсора меняется в зависимости от нахождения курсора на компоненте, перемещения круга или перемещения компонента.

После этого необходимо «схватить» компонент левой клавишей мыши и переместить вправо на требуемую величину (нижний скриншот). Обратите внимание на число под стрелкой, которое меняется при перемещении компонента. Это величина отступа TextView от объекта, к которому он привязан; в нашем случае от левой границы родителя ConstraintLayout.

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

Читайте также:  Ip reporter antminer android

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

«Привязка» компонентов между собой

Компоненты можно привязывать не только к границам родителя, но и к другим View. Связанные между собой компоненты перемещаются по экрану вместе. То есть, перемещение главного компонента в новую позицию формы автоматически переместит и связанные с ним другие компоненты.

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

Удаление привязки

Чтобы удалить привязку, необходимо просто нажать на соответствующий кружок компонента.

Исходный текст activity_main.xml

Исходный текст включает описания двух компонентов. Главный тег описания макета интерфейса представлен типом android.support.constraint.ConstraintLayout. Идентификатор компонента в описании обозначается атрибутом android:id. Остальные параметры (атрибуты) определяют размеры, относительные положения и специфические свойства компонента.

На следующем скриншоте представлен интерфейс работающего приложения. При вводе в текстовую строку PlainText символов устройство Android (эмулятор) открыл панель клавиатуры и высветил подсказки.

Шаблон LinearLayout

Прежде чем переходить к линейному макетированию компонентов заглянем в основной класс приложения MainActivity.java.

Класс MainActivity.java имеет метод onCreate, который вызывается, когда приложение создает и отображает Activity. В первой строке метода происходит обращение к суперклассу. А вот во второй строке метод setContentView(int) фоормирует интерфейс Activity из layout-файла. В качестве аргумента методу передается не путь к layout-файлу (res/layout/activity_main.xml), а идентификатор файла ID.

Создадим новый layout. Для этого выберем пункт меню New => XML => Layout XML file. Любители горячих клавиш могут использовать второй способ : при выделенной папке res/layout нажать ALT+Insert, и там уже клавишами выбрать соответствующий пункт.

Во вновь открывшемся окне необходимо определить наименование XML-файла макетирования интерфейса и выбрать тип (Root Tag).

После определения имени linear в папке layout должна появиться новая запись (linear.xml). Все файлы XML, связанные с настройкой интерфейса, размещаются в директории приложения res/layout.

Теперь откроем файл linear.xml в режиме Design и разместим в интерфейсе три кнопки. При перетаскивании первой кнопки, Вы увидете, что она заняла весь экран по ширине. После перетаскивания второй кнопки размер первой уменьшился наполовину. И так далее. На скриншоте можно увидеть положения кнопок в интерфейсе. Кроме этого, в панели дерева (Component Tree) родителем кнопок является контейнер LinearLayout.

В исходном коде файла linear.xml (вкладка Text) можно посмотреть описание интерфейса :

Положение с горизонтального без каких-либо проблем можно изменить на вертикальное. Для этого следует либо в тексте файла linear.xml переопределить атрибут «android:orientation» на «vertical», либо в панели атрибутов установить соответствующее значение, как это представлено на скриншоте.

Чтобы стартовать приложение с шаблоном интерфейса linear.xml необходимо в метод onCreate класса MainActivity.java внести изменения во вторую строку : setContentView(R.layout.linear). Интерфейс работающего приложения с линейным контейнером расположения компонентов LinearLayout представлен на скриншоте.

Читайте также:  Taxsee driver андроид последняя версия

Если Вы полностью самостоятельно повторили все действия, связанные с привязками компонентов в контейнерах типа ConstraintLayout и LinearLayout, то Вам не составит труда выполнить подобные действия с контейнерами RelativeLayout и AbsoluteLayout.

Продолжение статьи с табличным расположением компонентов TableLayout представлено здесь.

Источник

A Battle towards Performance- Constraint Layout vs Other Layouts(Part -1)

Imagine, you’ve just joined a new job and you need to shop for a whole new wardrobe that goes with your workplace culture and outlook (formals in most cases). You walk into an apparel store, head straight to the formals section, and you notice that some of the items hanging there are quite impractical and uncomfortable. Now, would you rather just buy the items listed there because the store tells you to or would you rather walk around the other sections and see what’s best for you?

Choosing a layout for your app and website is also a similar process. But before we head to that, it’s important that we understand how our UI is created. If you look at the image below, it shows you the steps that go into creating a UI.

Once uploaded, the display list object is cached. That way, should we need to draw the display list again? Instead of creating it, we can just redraw the existing one- which is much cheaper probably like that not-so-quirky shirt hanging in the casual section.

So, creating this display list through CPU and GPU uploading might be expensive. And that’s why we should reduce the number of times these actions are performed.

Let’s understand the Rendering process—

  1. Measure —The system completes a top-down traversal of the view tree to determine how large each ViewGroup and View element should be. When a ViewGroup is measured, it also measures its children.
  2. Layout —Another top-down traversal occurs, with each ViewGroup determining the positions of its children using the sizes determined in the measure phase.
  3. Draw —The system performs yet another top-down traversal. For each object in the view tree, Canvas object is created to send a list of drawing commands to the GPU. These commands include the ViewGroup and View objects’ sizes and positions, which the system determined during the previous 2 phases.

Manage complexity: Layouts matter

Android Layouts allow you to nest UI objects in the view hierarchy. This nesting can also impose a layout cost. When your app processes an object for layout, the app performs the same process on all children of the layout as well. For a complicated layout, sometimes a cost only arises the first time the system computes the layout. For instance, when your app recycles a complex list item in a RecyclerView object, the system needs to lay out all of the objects. In another example, trivial changes can propagate up the chain towards the parent until they reach an object that doesn’t affect the size of the parent.

Double taxation

Typically, the framework executes the layout or measure stage in a single pass and quite quickly. However, with some more complicated layout cases, the framework may have to iterate multiple times on parts of the hierarchy that require multiple passes to resolve before ultimately positioning the elements. Having to perform more than one layout-and-measure iteration is what we call double taxation.

Читайте также:  Как поставить драйвера для андроид

For example, when you use the RelativeLayout container, which allows you to position View objects with respect to the positions of other View objects, the framework performs the following actions:

  1. It executes a layout-and-measure pass, during which the framework calculates each child object’s position and size, based on each child’s request.
  2. and then, it uses this data, also taking object weights into account, to figure out the proper position of correlated views.
  3. After that, it performs a second layout pass to finalize the objects’ positions.
  4. Finally, goes on to the next stage of the rendering process.

The more levels your view hierarchy has, the greater the potential performance penalty.

Containers other than RelativeLayout may also give rise to double taxation. For example:

  • A LinearLayout view could result in a double layout-and-measure pass if you make it horizontal. A double layout-and-measure pass may also occur in a vertical orientation if you add measureWithLargestChild, in which case the framework may need to do a second pass to resolve the proper sizes of objects.
  • The GridLayout has a similar issue. While this container also allows relative positioning, it normally avoids double taxation by pre-processing the positional relationships among child views. However, if the layout uses weights or fills with the Gravity class, the benefit of that preprocessing is lost, and the framework may have to perform multiple passes if the container were a RelativeLayout .
  • FrameLayout is designed to host a single child. It stacks its children one over another which is helpful to create overlay UI. Also, It’s a very good option for parent view in case of custom views. But FrameLayout can only position child views by applying gravity relative to their parent.
  • ConstraintLayout has dual power of both Relative Layout as well as Linear layout: Set relative positions of views ( like Relative layout ) and also set weights for dynamic UI (which was only possible in Linear Layout). Despite the fact that it’s awesome, it fails to serve the purpose with simple UI layouts. Much like the formal section in your apparel store.

Multiple layout-and-measure passes are not, in themselves, a performance burden. But they can become so if they’re in the wrong spot. Just like shopping from the casual isn’t harmful until and unless you don’t know what you are looking for. You should be wary of situations where one of the following conditions applies to your container:

  • It is a root element in your view hierarchy.
  • It has a deep view hierarchy beneath it.
  • There are many instances of it populating the screen, similar to children in a ListView object.

I hope you enjoyed this blog and learned something! In my next blog, I have covered the tools I used for measuring various layout performances.

Please feel free to share your views and feedback in the comments section below.

If you liked this blog, hit the 👏 . Stay tuned for the next one!

Источник

Оцените статью