5 лет назад

Android. Обзор AbsoluteLayout (устаревшая и не рекомендуемая компоновка)


AbsoluteLayout является контейнером компоновки с абсолютным позиционированием, т. е. нужно явно указывать X и Y координаты вложенных элементов.

Данный контейнер является устаревшим с версии Android 1.5, его не рекомендуется использовать в приложениях и в новых версиях он может пропасть.

Тот, кто программировал для мобильных телефонов на платформе J2ME, наверное скажет, ну и что в этом такого? В JAVA-ME при построении низкоуровнего интерфейса в классе Canvas и GameCanvas, также приходилось указывать абсолютные значения при позиционировании элементов. Дело в том, что Вы можете создать клёвую компоновку для одного экрана, но запустив приложение на другом экране, с другим dpi, она поплывёт и возможно окажется совсем на другом месте и в другом масштабе. В общем использовать не стоит, но про неё я расскажу.

Начнём как всегда с примера.


Пример 1
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent">
    <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_x="20dp"
            android:layout_y="20dp"
            android:text="Coord 20x20"/>
    <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_x="120dp"
            android:layout_y="20dp"
            android:text="Coord 120x20"/>
    <ImageView android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:src="@drawable/ic_launcher"
               android:layout_x="50dp"
               android:layout_y="100dp"/>
    <TextView android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_x="40dp"
              android:layout_y="150dp"
              android:text="DevPad.RU"/>
</AbsoluteLayout>
Вот, что у нас получилось на разных экранах

Android AbsoluteLayoutAndroid AbsoluteLayout

Android AbsoluteLayoutAndroid AbsoluteLayout


В контейнер AbsoluteLayout вкладываем дочерние элементы представления и чтобы установить координаты, нужно задать значения для атрибутов android:layout_x и android:layout_y.

Например,

<Button android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_x="120dp"
    android:layout_y="20dp"
    android:text="Coord 120x20"
/>
Координаты кнопки мы задали, как 120dp по оси X и 20dp по оси Y.

Система координат на Android устройствах:
Система координат на Android устройствах


Программное создание контейнера компоновки AbsoluteLayout

Разберём, как сделать тот же самый пример, но программно на JAVA.
Для этого нужно воспользоваться вложенным классом AbsoluteLayout.LayoutParams(int width, int height, int x, int y).
Первым параметром передаётся ширина элемента, вторых высота, третьим параметром задаётся координата X, а четвёртым координата Y. Тут есть ещё одна тонкость, что значения задаются в пикселях(px), что вообще не рекомендуется использовать и если нам нужно задать значение в dp, чтобы приложение выглядело более-менее одинаково на различных экранах и разрешениях, напишем вспомогательный статичный метод по конвертации dp в px.
public static int convertDpToPixel(int dp, Context context) {
    Resources resources = context.getResources();
    DisplayMetrics metrics = resources.getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return (int)px;
}
Теперь передав в метод значение в dp, на выходе мы получим значение в px.

int dp = 20;
int px = convertDpToPixel(dp, getApplicationContext());
// px = 30
Только нужно учесть, что для разных ёмкостей экрана, значения будут разные.
Кстати, правильнее рассчитывать значение в типе float, но для упрощения я перевёл его в int.

Напишем наш первый пример полностью на JAVA:
Пример 2 - Создание компоновки AbsoluteLayout программно
package ru.devpad.absolutelayout;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.ViewGroup;
import android.widget.AbsoluteLayout;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class ExampleActivity2 extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setTitle("AbsoluteLayout programmatically");

        Button btn1 = new Button(this);
        btn1.setLayoutParams(new AbsoluteLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT,
                convertDpToPixel(20, this), /* x coord */
                convertDpToPixel(20, this)  /* y coord */
        ));
        btn1.setText("Coord 20x20");

        Button btn2 = new Button(this);
        btn2.setLayoutParams(new AbsoluteLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT,
                convertDpToPixel(120, this), /* x coord */
                convertDpToPixel(20, this)  /* y coord */
        ));
        btn2.setText("Coord 120x20");

        ImageView image = new ImageView(this);
        image.setLayoutParams(new AbsoluteLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT,
                convertDpToPixel(50, this), /* x coord */
                convertDpToPixel(100, this) /* y coord */
        ));
        image.setImageResource(R.drawable.ic_launcher);

        TextView text = new TextView(this);
        text.setLayoutParams(new AbsoluteLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT,
                convertDpToPixel(40, this), /* x coord */
                convertDpToPixel(150, this)  /* y coord */
        ));
        text.setText("DevPad.RU");

        AbsoluteLayout absoluteLayout = new AbsoluteLayout(this);
        absoluteLayout.setLayoutParams(
                new AbsoluteLayout.LayoutParams(
                        ViewGroup.LayoutParams.FILL_PARENT,
                        ViewGroup.LayoutParams.FILL_PARENT,
                        0, /* begin x coord */
                        0 /* begin y coord */
                )
        );
        absoluteLayout.addView(btn1);
        absoluteLayout.addView(btn2);
        absoluteLayout.addView(image);
        absoluteLayout.addView(text);

        setContentView(absoluteLayout);
    }

    public static int convertDpToPixel(int dp, Context context) {
        Resources resources = context.getResources();
        DisplayMetrics metrics = resources.getDisplayMetrics();
        float px = dp * (metrics.densityDpi / 160f);
        return (int) px;
    }
}

Альтернатива AbsoluteLayout

Если вам нужна альтернатива устаревшей компоновки AbsoluteLayout, то можно воспользоваться компоновкой RelativeLayout, просто заменив атрибуты координат на атрибуты внешних отступов слева и сверху (margin)

Атрибут AbsoluteLayout
 Атрибут RelativeLayout
android:layout_x
android:layout_marginLeft
android:layout_y
android:layout_marginTop
Изменим первый пример, согласно таблице выше.
Пример 3 - Альтернатива AbsoluteLayout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent">
    <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="20dp"
            android:text="Coord 20x20"/>
    <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="120dp"
            android:layout_marginTop="20dp"
            android:text="Coord 120x20"/>
    <ImageView android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:src="@drawable/ic_launcher"
               android:layout_marginLeft="50dp"
               android:layout_marginTop="100dp"/>
    <TextView android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_marginLeft="40dp"
              android:layout_marginTop="150dp"
              android:text="DevPad.RU"/>
</RelativeLayout>
Получили точную копию примера 1.

Вот и всё, что я хотел рассказать про эту компоновку.

Исходники примеров из статьи можно взять на гитхабе - https://github.com/devpad/Android-AbsoluteLayout
Поделиться ссылкой:

comments powered by Disqus