Проблема с ConstraintLayout
Недавно начал изучать Android Studio, наткнулся на проблему. Когда я хочу добавить текст, кнопку и т.д на девайс, добавленные компоненты пропадают за экран телефона. Затем выводится ошибка: This view is not constrained. It only has designtime positions, so it will jump to (0,0) at runtime unless you add the constraints The layout editor allows you to place widgets anywhere on the canvas, and it records the current position with designtime attributes (such as layout_editor_absoluteX). These attributes are not applied at runtime, so if you push your layout on a device, the widgets may appear in a different location than shown in the editor. To fix this, make sure a widget has both horizontal and vertical constraints by dragging from the edge connections. Я перевел, но так и не смог решить проблему.
Отслеживать
задан 28 июн 2018 в 13:52
101 2 2 золотых знака 2 2 серебряных знака 11 11 бронзовых знаков
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
ConstraintLayout требует подробной настройки расположения элементов основываясь на констреинтах (взаимном положении и т.д.) — он как продвинутый RelativeLayout .
Констреинты примерно означают «настройки положения вью» — куда должны «притягиваться» верх/низ и т.д., какой и где марджин, нужно ли как-то взаимодействовать с гайдлайнами.
В интернете информации более чем достаточно — читайте или официальную доку, или статейки вроде этой (первая попавшаяся в гугле, вроде бы неплохо написана).
Ошибка говорит вам:
This view is not constrained. It only has designtime positions, so it will jump to (0,0) at runtime unless you add the constraints
У вашего вью не настроены констреинты. Он имеет только настройку отображения в визуальном редакторе, а в рантайме (на устройстве) он прыгнет в точку (0, 0).
Также в редакторе есть магическая кнопочка (но помогает она не всегда, лучше вручную):

Она на основе того, как вы расположили в редакторе элементы, постарается настроить констреинты (правда, с кучей лишних марджинов и всего такого) вместо вас.
Resolving errors: missing constraints and hardcoded text in Android app development
As you set out on your exciting journey as an Android developer, you will almost certainly encounter errors in your applications. For example, you may notice the Android Studio editor sometimes has a red or yellow warning sign in the top right corner. These warning signs indicate there is a problem with the application’s code. Red warnings indicate a critical error that will prevent the app from running, while yellow warnings are advisory.

To find out more information, click the warning sign and Android Studio should explain the reason for the error. In this tutorial, we will explore how to resolve two common errors, which are called «Missing Constraints in ConstraintLayout» and «Hardcoded text», respectively.
Constraint errors
Constraints are a set of rules which determine how an object positions itself relative to other objects and the wider layout. Without constraints, the objects in your app would likely jump out of position when the app is loaded or the device is rotated. To automatically apply any missing constraints you can press the ‘Infer Constraints’ button at the top of the editor.

The red warning sign should now have turned yellow because we have resolved the missing constraints error. Also, the TextView object should have blue arrows coming out of it when selected in the editor. These blue arrows represent the constraints. They determine how the TextView object will position itself relative to the edges of the app interface.

The infer constraints button adds any missing constraints and resolves the error, but what if you want to fine-tune the position of the object? To adjust the position of an object, select it and refer to the Attributes panel. In this example, inferring constraints created a top margin of 99dp.

A margin is a type of constraint that creates a fixed distance between the object and another reference point (e.g. another object or the edge of the app interface). In the above example, we can adjust the distance between the TextView object and the top of the app layout by editing the value of the layout_marginTop attribute. For instance, if you wanted the TextView to sit near the top of the screen then you could set the layout_marginTop attribute to a small value such as 20dp.
An alternative method for adding constraints is to drag and drop the blue arrows yourself. To illustrate how this is done, add a second TextView object below the first one (for a reminder on how to add TextView objects see this tutorial). Next, select the original TextView object and notice the four circles which appear on each side. Click the bottom circle and drag the arrow down to the top circle of the second TextView object. This creates a constraint connecting the two TextView objects. Note the second TextView object will now have some missing constraints of its own. You can fix this using the Infer Constraints button or by dragging the constraint arrows to the edge of the app layout yourself.

Hardcoded text warnings
While the TextView widgets now have the appropriate constraints, there is still a yellow warning sign in the top right corner of the editor.

This yellow warning sign is there because the TextView widgets contain hardcoded text. Hardcoded text is text that is written directly into the layout file’s code. It can cause issues when the underlying code is being read and edited. Fortunately, hardcoded text is quite easy to rectify. Simply click the yellow warning sign in the top right corner, scroll to the bottom of the hardcoded text error message and press the ‘Fix’ button. In the Extract Resource window that opens, you can simply press OK and the attribute with the hardcoded text will be converted to a String resource. Android apps store all user-facing text as Strings in a resource file. The advantage of this is that a single String resource can be used in multiple locations throughout the app. If you ever need to change a String’s text, then you only need to update a single resource rather than tracking down all the areas that use the text. String resources also make it easier to translate your app into different languages.

For larger projects, it is often best to define any text (or Strings) you intend to use in advance. That way you can prevent the hardcoded text warning from ever appearing. To define a String, open the Strings resource file by clicking Project > app > res > values > Strings.xml

There will likely already be some Strings in there. Simply add new Strings between the opening and closing resources tags in the following format:
Coders' Guidebook
The ‘name’ property is what you will use to refer to the String elsewhere in the app. The text between the two String tags will be displayed to the user whenever the String name is referred to. In other words, using the ‘title’ String will display ‘Coders’ Guidebook’.
Как исправить ошибку в android studio?

Когда добавляю любой элемент, показывает эту ошибку
Текст, который на скрине
Missing Contraints in ContraintsLayout
This view is not constrained. It only has designtime positions, so it will jump to (0,0) at runtime unless you add the constraints The layout editor allows you to place widgets anywhere on the canvas, and it records the current position with designtime attributes (such as layout_editor_absoluteX). These attributes are not applied at runtime, so if you push your layout on a device, the widgets may appear in a different location than shown in the editor. To fix this, make sure a widget has both horizontal and vertical constraints by dragging from the edge connections.
- Вопрос задан более трёх лет назад
- 3564 просмотра
1 комментарий
Средний 1 комментарий
Урок 180. ConstraintLayout. Основы
Android Studio по умолчанию предлагает нам использовать ConstraintLayout при создании разметки экрана. Давайте разберемся, что это за штука и как с ней работать.
Хоть это и 180-й урок, но он будет заточен под новичков, т.к. сюда будет вести ссылка из самых первых уроков. Поэтому, опытных разработчиков прошу не удивляться стилю изложения материала, начало вы можете пропустить.
Начнем с самых азов. Чтобы вы могли размещать на экране различные компоненты (кнопки, поля ввода, чекбоксы и т.п.), необходимо использовать специальный контейнер. Именно в него вы будете помещать компоненты. В Android компоненты называются View, а контейнер — ViewGroup.
Существуют несколько типов ViewGroup: LinearLayout, RelativeLayout, FrameLayout, TableLayout, ConstraintLayout и т.д.
Они различаются тем, как они будут упорядочивать компоненты внутри себя. LinearLayout, например, выстроит их по горизонтальной или вертикальной линии. А TableLayout — в виде таблицы. Более подробно об этом вы можете прочитать в Уроке 6.
В этом уроке мы будет разбираться, как будут вести себя компоненты в контейнере ConstraintLayout.
Вообще, слово Constraint переводится как ограничение, принуждение. Но как по мне, так это не совсем точно отражает смысл. Самое подходящее слово, которое я могу тут подобрать — это привязка. Его и буду использовать.
Практика
Чтобы вам самим попрактиковаться, рекомендую создать модуль для этого урока. О том, как создать модуль, мы уже говорили в Уроке 3.
В меню студии: File > New > New module

Application/Library name: ConstraintLayoutIntro
Module name: p0180constraintlayoutintro
Package name: ru.startandroid.p0180constraintlayoutintro
Итак, у нас в Android Studio есть модуль. А в нем есть файл res > layout > activity_main.xml.

Откроем этот файл двойным кликом. Он выглядит так

Убедитесь, что слева-внизу открытка вкладка Design, и режим просмотра выбран Design, а не Blueprint.
Сейчас на экране вы видите текст Hello World. Этот текст отображен с помощью View, которое называется TextView.
Вы можете видеть его в Component Tree (слева-снизу).

Обратите внимание, что TextView как бы вложен в ConstraintLayout. Это то, о чем я говорил в начале. ConstraintLayout — контейнер, а внутри него находятся различные View, в нашем случае — TextView. Также, можно сказать, что ConstraintLayout является родителем или родительским ViewGroup для TextView.
Давайте удалим TextView с экрана. Для этого просто выделите его на экране или в Component Tree и нажмите кнопку Del на клавиатуре.
Теперь ConstraintLayout пуст и экран ничего не отображает.

Если вы вдруг что-то удалили по ошибке, вы всегда можете восстановить это, нажав Ctrl+Z.
А если вы там совсем чего-то наворотили и не получается все это отменить, то откройте вкладку Text (слева-снизу) и вставьте туда этот код:
Ваш экран вернется к первоначальному состоянию.
Зачем нужны привязки
Давайте добавим на экран какой-нибудь компонент, например, снова TextView. Для этого просто перетащите компонент мышкой из Palette на экран.
После этого TextView появился на экране и в Component Tree.
Запустим приложение и посмотрим, как этот текст будет выглядеть.

Видим, что TextView уехал влево и вверх. Что-то явно пошло не так.
Если вы откроете текстовое представление вашего экрана (вкладка Text слева-снизу), то увидите, что элемент TextView подчеркнут красной линией.

Если навести на него мышкой, то он покажет ошибку:
This view is not constrained, it only has designtime positions, so it will jump to (0,0) unless you add constraints.
Этим сообщением студия говорит нам, что View не привязано. Его текущее положение на экране актуально только для разработки (т.е. только в студии). А при работе приложения, это положение будет проигнорировано, и View уедет в точку (0,0), т.е. влево-вверх (что мы и наблюдали при запуске).
Как сделать так, чтобы View в ConstraintLayout оставалось на месте и не смещалось в угол? Необходимо добавить привязки (constraints). Они будут задавать положение View на экране относительно каких-либо других элементов или относительно родительского View.
Как добавить привязки
Давайте добавим привязки для нашего TextView.

Если вы выделите на экране TextView, то можете видеть 4 круга по его бокам.
Эти круги используются, чтобы создавать привязки.
Существует два типа привязок: одни задают положение View по горизонтали, а другие — по вертикали.
Создадим горизонтальную привязку. Привяжем положение TextView к левому краю его родителя. Напомню, что родителем TextView является ConstraintLayout, который в нашем случае занимает весь экран. Поэтому края ConstraintLayout совпадают с краями экрана.
Чтобы создать привязку, нажмите мышкой на TextView, чтобы выделить его. Затем зажмите левой кнопкой мыши левый кружок и тащите его к левой границе.
TextView также уехал влево. Он привязался к левой границе своего родителя.
Но вовсе необязательно они должны быть вплотную. Мы можем задать отступ. Для этого просто зажмите левой кнопкой мыши TextView, перетащите вправо и отпустите.
Обратите внимание на число, которое меняется. Это величина отступа TextView от объекта, к которому он привязан (в нашем случае — от левой границы родителя).

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

Запускаем, чтобы проверить
TextView никуда не уехал, а находится там, где мы и настроили с помощью привязок.
Давайте добавим еще одно View, например, кнопку — Button.
Если сейчас запустить приложение, то кнопка уедет влево-вверх потому что она ни к чему не привязана.

Мы можем привязывать не только к границам родителя, но и к другим View. Давайте привяжем кнопку к TextView.
Мы привязали кнопку к TextView, создав две привязки

1) Вертикальная привязка. Верхняя граница кнопки привязана к нижней границе TextView. Отступ = 82.
Т.е. можно сказать, что по вертикальной оси:
верхняя граница кнопки = нижняя граница TextView + 82
2) Горизонтальная привязка. Левая граница кнопки привязана к правой границе TextView. Отступ 103.
По горизонтальной оси:
левая граница кнопки = правая граница TextView + 103
Т.к. кнопка привязана к TextView, то, если мы сейчас будем перемещать TextView, то кнопка будет также перемещаться.
Добавим еще View. Например, CheckBox.
Давайте сделаем так, чтобы он по горизонтали находился на том же уровне, что и TextView. Для этого нам надо левую границу CheckBox привязать к левой границе TextView и сделать нулевой отступ. А по вертикали привяжем к нижней границе родителя.
Теперь чекбокс и TextView выравнены по левому краю.
Как удалить привязку
Чтобы удалить привязку, надо просто нажать на соответствующий кружок. Удалим привязки у кнопки.
Чтобы удалить сразу все привязки, есть специальная кнопка
Привязка с двух сторон
Мы рассмотрели примеры, когда View было привязано по каждой оси только с одной стороны. Т.е. только слева или справа по горизонтали, и сверху или снизу по вертикали. Но мы можем привязать View с обоих сторон по каждой оси.
Пока рассмотрим только горизонтальную привязку. Но, разумеется, все это будет работать и для вертикальной привязки.
Давайте попробуем, например, левый край привязать к левой границе родителя, а правый край — к правой границе родителя.
Очистим экран от всех View и добавим новый TextView без каких-либо привязок. Теперь привяжем его к левой и правой границам родителя.
TextView сначала ушел влево, т.к. была привязка к левой границе, но после создания привязки к правой границе он выровнялся и теперь расположен по центру. Т.е. привязки уравняли друг друга, и View находится ровно посередине между тем, к чему он привязан слева, и тем, к чему он привязан справа. Т.е. в нашем случае View находится посередине между левой и правой границами его родителя.
Обратите внимание, что такие двусторонние привязки отображаются как пружинки, а не линии.
Давайте немного усложним пример, добавив кнопку и перенастроив привязки

Кнопка привязана к правому краю. А TextView привязан к левому краю и к кнопке.
Если мы теперь будем перемещать кнопку, то TextView будет оставаться ровно посередине между левым краем и кнопкой.
Мы можем настроить двустороннюю привязку так, чтобы View располагалось не посередине, а ближе к левому краю или к кнопке. Для этого удобно использовать специальный скролл в Properties.
Этим скроллом вы задаете пропорцию. По умолчанию значение = 50. Это половина от 100. Соответственно, View находится на половине расстояния между объектами, к которому оно привязано. В нашем случае, при значении = 50, TextView находится посередине между левым краем и кнопкой.
Если поставить значение, например, 25, то TextView будет находится от левого края на расстоянии равном четверти расстояния между левым краем и кнопкой. Если поставить 75, то TextView будет находится от левого края на расстоянии равном 3/4 от расстояния между левым краем и кнопкой.
И как бы не менялось расстояние между левым краем и кнопкой, эти пропорции всегда будут соблюдаться.
В следующем уроке продолжим рассматривать возможности ConstraintLayout.
P.S.
Если вы пришли в этот урок по ссылке из первых уроков, то теперь вы можете вернуться и продолжить обучение. Этой информации вам будет достаточно.
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня