Освой Android играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Ориентация

Вступление
Узнать ориентацию программно
Кручу-верчу, запутать хочу!
Установить ориентацию программно и через манифест
Запрет на создание новой активности
Исчезающий текст
Проверка на существование

Вступление

Когда создавались первые портативные устройства - КПК и смартфоны, то за основу бралась настольная операционная система и допиливалась под мобильное устройство. Лишние функции удалялись, а некоторые функции добавлялись. Но при этом как-то совсем упустили из виду, что в отличие от громоздких мониторов и экранов ноутбуков, карманные устройства можно вращать в руках. Первые устройства не умели менять ориентацию экрана. Некоторые программисты самостоятельно стали создавать программы, которые умели переключаться в разные режимы. Затем эту возможность стали включать в настройки аппарата. Позже аппараты научились самостоятельно определять ориентацию экрана.

Всего существует два режима - портретный и альбомный. На большинстве телефонов используется по умолчанию портретный режим (как на паспорте). Альбомный режим знаком нам по обычным мониторам.

Рассмотрим следующий случай. Предположим, у нас в приложении имеется одно текстовое поле и шесть кнопок. Вроде всё нормально.

Портретный режим

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

Альбомный режим

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

Для этой операции нам понадобится сделать несколько важных шагов. Сначала нужно создать новую подпапку в папке res. Выделяем папку res, вызываем из него контекстное меню и последовательно выбираем команды New | Android resource directory. В диалоговом окне из выпадающего списка Resource type: выбираем layout. В списке Available qualifiers: находим элемент Orientation и переносим его в правую часть Chosen qualifiers: с помощью кнопки с двумя стрелками. По умолчанию у вас появится имя папки layout-port в первой строке Directory Name:. Но нам нужен альбомный вариант, поэтому в выпадающем списке Screen orientation выбираем Landscape. Теперь название папки будет layout-land.

layout-land

Можно обойтись без помощи мастера, создав папку сразу через меню New | Directory. Этот способ годится для опытных разработчиков, которые знают, как следует назвать папку. Важно запомнить, что имя даётся не произвольно, а именно в таком виде layout-land. По суффиксу -land система понимает, что речь идёт о новом режиме. Теперь нам осталось создать в созданной папке новый XML-файл activity_main.xml. Вызываем контекстное меню у папки layout-land и выбираем команды New | Layout Resource File. В диалоговом окне присваиваем имя activity_main.xml, которое должно совпадать с именем существующего файла. Во втором поле вводим LinearLayout, по мере ввода появится подсказка, облегчающая выбор.

Откроем созданный файл и модифицируем его следующим образом.

Пример писался во времена Android 2.3. Сейчас проще создать нужную разметку через ConstraintLayout

<?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">

    <LinearLayout
        android:orientation="vertical"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:layout_gravity="center"
        android:paddingLeft="20dp"
        android:paddingRight="20dp">

        <EditText
            android:layout_height="wrap_content"
            android:id="@+id/editText"
            android:layout_width="match_parent"/>

        <TableLayout
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:layout_gravity="center"
            android:stretchColumns="*">

            <TableRow>

                <Button
                    android:id="@+id/button1"
                    android:layout_height="wrap_content"
                    android:layout_width="match_parent"
                    android:text="Первая кнопка"/>

                <Button
                    android:id="@+id/button2"
                    android:layout_height="wrap_content"
                    android:layout_width="match_parent"
                    android:text="Вторая кнопка"/>
            </TableRow>

            <TableRow>

                <Button
                    android:id="@+id/button3"
                    android:layout_height="wrap_content"
                    android:layout_width="match_parent"
                    android:text="Третья кнопка"/>

                <Button
                    android:id="@+id/button4"
                    android:layout_height="wrap_content"
                    android:layout_width="match_parent"
                    android:text="Четвёртая кнопка"/>
            </TableRow>

            <TableRow>

                <Button
                    android:id="@+id/button5"
                    android:layout_height="wrap_content"
                    android:layout_width="match_parent"
                    android:text="Пятая кнопка"/>

                <Button
                    android:id="@+id/button6"
                    android:layout_height="wrap_content"
                    android:layout_width="match_parent"
                    android:text="Шестая кнопка"/>
            </TableRow>
        </TableLayout>
    </LinearLayout>
</LinearLayout>

Запускаем приложение и проверяем. Отлично, теперь видны все кнопки. Поздравляю, вы гений!

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

Узнать ориентацию программно

Чтобы из кода узнать текущую ориентацию, можно создать следующую функцию:


// Kotlin
private fun getScreenOrientation(): String {
    return when (resources.configuration.orientation) {
        Configuration.ORIENTATION_PORTRAIT -> "Портретная ориентация"
        Configuration.ORIENTATION_LANDSCAPE -> "Альбомная ориентация"
        else -> ""
    }
}

// Java private String getScreenOrientation(){ if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) return "Портретная ориентация"; else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) return "Альбомная ориентация"; else return ""; }

Вызовите данную функцию из нужного места, например, при щелчке кнопки и узнайте текущую ориентацию. В примере использовались две распространённые системные константы для ориентации. Есть ещё константа ORIENTATION_SQUARE (квадратный экран). Но я таких телефонов не встречал.

Можно также вычислить ширину и высоту экрана, если высота больше ширины, то устройство в