Визначення розмірів
Розробляючи інтерфейс, ми часто стикаємося з необхідністю задати розміри елементів. У Android можна використовувати як фіксовані значення, так і спеціальні параметри, які адаптуються до контексту використання.
Фіксовані значення
Фіксовані значення розмірів вказуються у вигляді чисел з одиницями вимірювання. Основні одиниці:
px— пікселі поточного екрана. Однак ця одиниця виміру не рекомендується, оскільки реальне представлення зовнішнього вигляду може змінюватися залежно від пристрою; кожен пристрій має певний набір пікселів на дюйм, тому кількість пікселів на екрані може також змінюватися.dpабоdip— density-independent pixels (пікселі, незалежні від щільності). Абстрактна одиниця виміру, заснована на фізичній щільності екрана з роздільною здатністю 160 dpi (точок на дюйм). У цьому випадку 1dp = 1px. Якщо розмір екрана більший або менший за 160 dpi, кількість пікселів, що застосовуються для відтворення 1dp відповідно збільшується або зменшується. Наприклад, на екрані з 240 dpi 1dp=1,5px, а на екрані з 320dpi 1dp=2px. Загальна формула для отримання кількості фізичних пікселів із dp: px = dp * (dpi / 160)sp— scale-independent pixels (незалежні від масштабування пікселі.). Допускають налаштування розмірів, здійснюване користувачем. Рекомендуються для роботи зі шрифтами.mm— міліметриin— дюйми
Наприклад, встановлення ширини елемента в 150 пікселів виглядає так:
android:layout_width="150px"
Проте, використання пікселів (px) не є рекомендованим, оскільки вони не адаптуються до різних екранів. Краще використовувати dp для розмірів та sp для тексту.
dp. Це пов'язано з тим, що світ мобільних пристроїв на Android сильно фрагментований у плані роздільної здатності та розмірів екрана. І що більша щільність пікселів на дюйм, то відповідно більше пікселів нам буде доступно:
Використовуючи ж стандартні фізичні пікселі, ми можемо зіткнутися з проблемою, що розміри елементів також будуть сильно варіюватися залежно від щільності пікселів пристрою. Наприклад, візьмемо 3 пристрої з різними характеристиками екрана Nexus 4, Nexus 5X і Nexus 6P і виведемо на екран квадрат розміром 300px на 300px:
В одному випадку квадрат за шириною займатиме 40%, в іншому - третину ширини, у третьому - 20%.
Тепер також візьмемо квадрат зі сторонами 300х300, але тепер замість фізичних пікселів використовуємо одиниці dp:
Тепер же розміри квадрата на різних пристроях виглядають більш консистентно.
Для спрощення роботи з розмірами всі розміри розбиті на кілька груп:
ldpi (low): ~120dpimdpi (medium): ~160dpihdpi (high): ~240dpi (до цієї групи можна віднести такий давній пристрій як Nexus One)xhdpi (extra-high): ~320dpi (Nexus 4)xxhdpi (extra-extra-high): ~480dpi (Nexus 5/5X, Samsung Galaxy S5)xxxhdpi (extra-extra-extra-high): ~640dpi (Nexus 6/6P, Samsung Galaxy S6)
Встановлення розмірів
Основна проблема, пов'язана з розмірами, пов'язана з їх встановленням у коді Java. Наприклад, деякі методи приймають як значення фізичні пікселі, а не density-independent pixels. У цьому випадку може знадобитися перевести значення з одного типу одиниць в інший. Для цього потрібно застосувати метод TypedValue.applyDimension(), який приймає три параметри:
public static float applyDimension(int unit,
float value,
android.util.DisplayMetrics metrics)
Параметр unit представляє тип одиниць, з якої треба отримати значення в пікселях. Тип одиниць описується однією з констант TypedValue:
COMPLEX_UNIT_DIP-dpабо незалежні від щільності екрана пікселіCOMPLEX_UNIT_IN-inабо дюймиCOMPLEX_UNIT_MM-mmабо міліметриCOMPLEX_UNIT_PT-ptабо точкиCOMPLEX_UNIT_PX-pxабо фізичні пікселіCOMPLEX_UNIT_SP-spабо незалежні від масштабування пікселі (scale-independent pixels) Параметрvalueпредставляє значення, яке треба перетворити. Параметрmetricsпредставляє інформацію про метрику, в рамках якої треба виконати перетворення.
У підсумку метод повертає перетворене значення. Розглянемо абстрактний приклад. Наприклад, нам треба отримати з 60dp звичайні фізичні пікселі:
int valueInDp = 60;
int valueInPx = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, valueInDp, getResources().getDisplayMetrics());
Як третій аргумент передається виклик методу getResources().getDisplayMetrics(), який дає змогу отримати інформацію про метрику, пов'язану з поточним пристроєм. У підсумку ми отримаємо з 60dp деяку кількість пікселів.
Спеціальні параметри розмірів
Замість фіксованих значень можна застосовувати наступні параметри:
match_parent— елемент займає весь доступний простір свого контейнера.wrap_content— елемент займає мінімальний простір, необхідний для відображення його вмісту.
Приклад використання в XML:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
Пріоритетність розмірів
Параметри розмірів часто комбінуються з вагами (weight) для управління відносними розмірами елементів. Це особливо корисно в контейнерах, таких як LinearLayout.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Елемент 1" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="Елемент 2" />
</LinearLayout>
У цьому прикладі:
- Перший елемент займатиме 1 частину доступного простору.
- Другий елемент — 2 частини.
Мінімальні та максимальні розміри
Можна також задати обмеження:
android:minWidth/android:minHeight— мінімальні розміри.android:maxWidth/android:maxHeight— максимальні розміри.
Приклад:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="100dp"
android:maxWidth="200dp"
android:minHeight="50dp"
android:maxHeight="100dp"
android:text="Текст з обмеженнями" />
Приклад коду
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<!-- TextView з мінімальним і максимальним розміром шрифту -->
<TextView
android:id="@+id/titleText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Розміри у дизайні Android"
android:textSize="24sp"
android:minHeight="48dp"
android:maxHeight="72dp"
android:gravity="center"
android:layout_marginBottom="16dp" />
<!-- Button з мінімальними розмірами -->
<Button
android:id="@+id/actionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:minWidth="150dp"
android:minHeight="48dp"
android:text="Натисни мене"
android:textSize="18sp" />
<!-- EditText із фіксованими розмірами -->
<EditText
android:id="@+id/inputField"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:hint="Введіть текст"
android:textSize="16sp"
android:minHeight="40dp"
android:maxHeight="80dp" />
<!-- TextView з текстом, який автоматично змінює розмір -->
<TextView
android:id="@+id/adaptiveText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Автоматичний розмір тексту"
android:textSize="18sp"
android:minHeight="40dp"
android:maxHeight="80dp"
android:layout_marginBottom="16dp" />
</LinearLayout>
package com.example.sizerexample;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Отримання посилань на елементи
TextView titleText = findViewById(R.id.titleText);
Button actionButton = findViewById(R.id.actionButton);
EditText inputField = findViewById(R.id.inputField);
TextView adaptiveText = findViewById(R.id.adaptiveText);
// Динамічне налаштування розмірів тексту
adaptiveText.setTextSize(14); // Мінімальний розмір тексту
adaptiveText.setMaxHeight(120); // Максимальна висота текстового блоку
// Додавання події на кнопку
actionButton.setOnClickListener(view -> {
String input = inputField.getText().toString();
if (input.isEmpty()) {
Toast.makeText(this, "Введіть текст", Toast.LENGTH_SHORT).show();
} else {
// Виводимо текст у адаптивний TextView
adaptiveText.setText(input);
adaptiveText.setTextSize(input.length() > 20 ? 12 : 18); // Зменшення шрифту для довгого тексту
}
});
// Зміна тексту titleText
titleText.setText("Динамічні розміри в Android");
}
}