Верстка макета для Android приложения
Я только начинаю программировать на Java. Состряпал программу для работы, дал потестировать. С первых же шагов все стало очень плохо.
Разберем самый "нагруженный" макет.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AddOrderActivity">
<LinearLayout
android:id="@+id/layout_first"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:fontFamily="@font/roboto_medium"
android:text="Форма для добавления заказа"
android:textSize="20sp" />
<EditText
android:id="@+id/number_order"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:background="@drawable/input"
android:hint="Номер заказа"
android:textAlignment="center"
android:inputType="number"
android:padding="10dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="@font/roboto_medium"
android:text="Выберите тип доставки:"
android:textSize="18sp" />
<View
android:layout_width="300dp"
android:layout_height="3dp"
android:layout_gravity="center"
android:layout_marginTop="5dp"
android:background="@drawable/delimiter" />
<RadioGroup
android:id="@+id/group_radio_type_order"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:orientation="vertical">
<RadioButton
android:id="@+id/usually_order"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="true"
android:drawableLeft="@drawable/usually_order"
android:padding="5dp"
android:text=" Обычный заказ" />
<RadioButton
android:id="@+id/sdd_order"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/sdd_order"
android:padding="5dp"
android:text=" СДД заказ" />
</RadioGroup>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="@font/roboto_medium"
android:text="Выберите тип заказа"
android:textSize="18sp" />
<View
android:layout_width="300dp"
android:layout_height="3dp"
android:layout_gravity="center"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:background="@drawable/delimiter" />
<RadioGroup
android:id="@+id/group_radio_type_delivery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:padding="5dp">
<RadioButton
android:id="@+id/usually_delivery"
android:layout_width="130dp"
android:layout_height="wrap_content"
android:checked="true"
android:drawableLeft="@drawable/lamoda_order"
android:padding="3dp"
android:text=" Lamoda" />
<RadioButton
android:id="@+id/partner_delivery"
android:layout_width="130dp"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/partner_order"
android:padding="3dp"
android:text=" Партнер" />
<RadioButton
android:id="@+id/econom_delivery"
android:layout_width="130dp"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/econom_order"
android:padding="3dp"
android:text=" Эконом" />
</RadioGroup>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:fontFamily="@font/roboto_medium"
android:text="Введите необходимые данные"
android:textSize="18sp" />
<View
android:layout_width="300dp"
android:layout_height="3dp"
android:layout_gravity="center"
android:layout_marginBottom="5dp"
android:background="@drawable/delimiter" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="280dp"
android:layout_height="wrap_content"
android:orientation="vertical">
<EditText
android:id="@+id/price_order"
android:layout_width="265dp"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:background="@drawable/input"
android:hint="Стоимость заказа"
android:inputType="number"
android:textAlignment="center"
android:padding="10dp" />
<EditText
android:id="@+id/bayout_order"
android:layout_width="265dp"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="15dp"
android:background="@drawable/input"
android:hint="Выкуп"
android:textAlignment="center"
android:inputType="number"
android:padding="10dp" />
</LinearLayout>
<ImageButton
android:id="@+id/full_buying_btn"
android:layout_gravity="center"
android:layout_width="62dp"
android:layout_height="62dp"
android:background="@drawable/button"
android:src="@drawable/buying"/>
</LinearLayout>
</LinearLayout>
<Button
android:id="@+id/add_button"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_below="@+id/layout_first"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:background="@drawable/button"
android:text="Добавить заказ" />
</RelativeLayout>
Я уже всю голову сломал. В Android Studio есть эмулятор Pixel c разрешением 1080х1920 и плотность 420dpi. Тестировщик пытался воспользоваться программой на Sony Xperia XA с разрещением 1080х1920 и плотсностью 401dpi. Я не могу понять, каким образом нужно сделать макет чтобы он подходил на эти 2 телефона, учитывая что они оба large, xxhdpi, long.
Как нужно назвать папки в layout? Bообще почему такая разница в отображение макета если совершенно одинаковое разрешение?
Я уже не говорю о том как это отображается на моем "длинном" Mi9Se..
Ответы (2 шт):
Если вы хотите экран который будет отображаться одинаково на разных экранах, то вы должны стараться избегать ситуаций в которых размер View задается фиксированным значением. Здесь есть разные подходы. Набросаю несколько по разным типам макетов.
LinearLayout:
Задавайте размеры экранов использую параметр weight. Так вы можете задавать пропорции ваших View и они будут одинаково смотреться на любом экране.
Задавайте View-хам размеры match_parent и wrap_content, а расстояния от границ корневой View или соседних регулируйте с помощью отступов (margin).
RelativeLayout:
Тут вы можете расположить элементы относительно друг друга, задать им зависимости от других View. Так же можно задавать расстояния с помощью отступов.
Можете использовать параметры center, center_vertical, center_horizontal.
ConstraintLayout
Как и в случае с RelativeLayout здесь вы можете задавать расположение элементов относительно друг друга.
В ConstraintLayout есть barrier и guideline, вы можете распологать их относительно экрана используя процентный размер от экрана. Например
app:layout_constraintGuide_percent="0.1"
Вывод из этого всего один. Хотите адаптивный экран - переставайте хардкодить размер. Вы должны научиться располагать ваши элементы без использования жестких размеров, это приходит с опытом. Это совершенно не означает, что нигде нельзя хардкодить, но всегда когда размер вашей View задается жестко задумайтесь: "А можно ли это как-то изменить", если же нет, и ваша View действительно должна быть 200dp то остальной макет должен быть построен так, чтоб это все корректно отобразилось везде.
".. почему 2 одинаковых разрешения экрана отображают по разному макет .."
Дело в том, что верстка макета у вас завязана не на пиксели, а на плотность (грубо говоря отношение пикселей к физическому размеру экрана).
Плотность экрана тестируемых устройств у вас разная (420 и 401 соответственно), некоторые размеры виджетов указаны в абсолютных величинах плотности (dp) , поэтому и разный вид в итоге.
К примеру, вы указываете размер виджета 265dp - на экране с плотностью 420dp он займет чуть больше половины, а с плотностью 320dp - почти весь экран. Ваши экраны отличаются на 19dp и поэтому искажения не такие большие, но проблема будет присутствовать на любом отличном от "эталонного" экране (не 420dpi) и чем больше разница плотностей, тем отчетливее.
Для решения проблемы вам не нужно делать отдельную верстку под отличный от "эталонного" экран и искать какую то комбинацию квалификаторов для папки Layout, это бессмысленный и трудный путь решения проблемы - различных комбинаций экранов андроид-устройств очень большое количество и уже окончательно отчаявшись написать собственную разметку для 1001-ой комбинации пикселей и размера экрана, вы стокнетесь с ".. как это отображается на моем "длинном" Mi9Se.. " - Вместо всего этого вам нужно сделать ОДНУ адаптивную верстку под все экраны и все. Основные принципы такой верстки я излагал в этом отете, так же в другом ответе на этот вопрос изложены основные моменты для понимания, куда двигаться, поэтому повторять я это все не буду.
PS: сетка верстки по гайдлайнам гугла - 8dp, поэтому все эти значения в 5dp, 15dp, 150dp, 265dp и тд. достаточно плохая идея. В итоге это выльется в подсознательное ощущения у пользователя, что с этим приложением что то не так, интерфейс .. эээ .. некрасивый.

