Урок 16. Программное создание экрана. LayoutParams


В этом уроке мы:

- рисуем экран программно, а не через layout-файл


До этого мы создавали экран с помощью layout-файлов. Но то же самое мы можем делать и программно.

Создадим проект:

Project name: P0161_DynamicLayout
Build Target: Android 2.3.3
Application name: DynamicLayout
Package name: ru.startandroid.develop.dinamiclayout
Create Activity: MainActivity

Открываем MainActivity.java и обратим внимание на строку:

        setContentView(R.layout.main);


Напомню, что в этой строке мы указываем, что Activity в качестве экрана будет использовать layout-файл main.xml. Есть другая реализация этого метода, которая на вход принимает не layout-файл, а View-элемент и делает его корневым. В layout-файлах корневой элемент обычно LinearLayout, мы тоже используем его.

    @Override
   
public void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
       
// создание LinearLayout
       
LinearLayout linLayout = new LinearLayout(this);
       
// установим вертикальную ориентацию
       
linLayout.setOrientation(LinearLayout.VERTICAL);
       
// создаем LayoutParams 
       
LayoutParams linLayoutParam = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
       
// устанавливаем linLayout как корневой элемент экрана
       
setContentView(linLayout, linLayoutParam);
   
}


Обновим импорт – CTRL+SHIFT+O. Eclipse предложит нам выбрать, какой именно LayoutParams мы будем использовать. Тут надо остановиться подробнее. Вспомним теорию про экраны. Экран состоит из ViewGroup и вложенных в них View.

Известные нам примеры ViewGroup – это LinearLayout, TableLayout, RelativeLayout и т.д. Каждая их этих ViewGroup имеет вложенный класс LayoutParams. Базовым для этих LayoutParams является ViewGroup.LayoutParams.

ViewGroup.LayoutParams имеет всего два атрибута: height и width. Его подкласс ViewGroup.MarginLayoutParams наследует два этих атрибута и имеет свои четыре: bottomMargin, leftMargin, rightMargin, topMargin. Класс LinearLayout.LayoutParams в свою очередь является подклассом ViewGroup.MarginLayoutParams, наследует от него уже 6 аттрибутов и добавляет свои два: gravity и weight.

Т.е. объект LinearLayout имеет вложенный класс LinearLayout.LayoutParams с layout-аттрибутами. И эти аттрибуты распространяются на все дочерние View и ViewGroup.


Т.е. View, находящаяся в LinearLayout имеет один набор layout-параметров:


а View из RelativeLayout – другой:

Есть и общие элементы, т.к. родители у этих ViewGroup одни.


Вернемся в Eclipse, он ждет нашего выбора. Используем базовый класс ViewGroup.LayoutParams


Давайте разберем код. Мы создаем LinearLayout и ставим вертикальную ориентацию. Далее создаем LayoutParams. Конструктор на вход принимает два параметра: width и height. Мы оба ставим MATCH_PARENT. Далее вызывается метод setContentView. На вход ему подается LinearLayout и LayoutParams. Это означает, что корневым элементом Activity будет LinearLayout с layout-свойствами из LayoutParams.

Если мы сейчас запустим приложение, то ничего не увидим, т.к. LinearLayout – прозрачен. Давайте добавлять в LinearLayout View-компоненты.

        LayoutParams lpView = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
       
        TextView tv =
new TextView(this);
        tv.setText
("TextView");
        tv.setLayoutParams
(lpView);
        linLayout.addView
(tv);
       
        Button btn =
new Button(this);
        btn.setText
("Button");
        linLayout.addView
(btn, lpView);


Мы снова создаем объект LayoutParams с атрибутами width = wrap_content и height = wrap_content. Теперь если мы присвоим этот объект какому-либо View, то это View будет иметь ширину и высоту по содержимому.

Далее мы создаем TextView, настраиваем его текст, присваиваем ему выше созданный LayoutParams и добавляем в LinearLayout с помощью метода addView (View child).

С Button аналогично – создаем, правим текст, а затем используем другую реализацию метода addView (View child, ViewGroup.LayoutParams params), которая одновременно добавляет Button в LinearLayout и присваивает для Button указанный LayoutParams. Результат будет тот же, что и с TextView, но вместо двух строк кода получилась одна.

Обратите внимание, что для двух объектов View я использовал один объект LayoutParams - lpView. И если я теперь буду менять свойства этого объекта, меняться будут оба View.

Сохраним и запустим приложение. Видим, что компоненты на экране появились. И видно, что их высота и ширина определена по содержимому (wrap_content).


Объект lpView имеет базовый тип android.view.ViewGroup.LayoutParams. А значит позволит настроить только ширину и высоту. Но для View в LinearLayout доступны, например, отступ слева или выравнивание по правому краю. И если мы хотим их задействовать, значит надо использовать LinearLayout.LayoutParams:

        LinearLayout.LayoutParams leftMarginParams = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        leftMarginParams.leftMargin =
50;
       
        Button btn1 =
new Button(this);
        btn1.setText
("Button1");
        linLayout.addView
(btn1, leftMarginParams);


Смотрим код. Мы создаем объект типа LinearLayout.LayoutParams с помощью такого же конструктора, как и для обычного LayoutParams, указывая width и height. Затем мы указываем отступ слева = 50. Отступ здесь указывается в пикселах. Далее схема та же: создаем объект, настраиваем текст и добавляем его в LinearLayout c присвоением LayoutParams.

Аналогично добавим компонент с выравниванием:

        LinearLayout.LayoutParams rightGravityParams = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        rightGravityParams.gravity = Gravity.RIGHT;
       
        Button btn2 =
new Button(this);
        btn2.setText
("Button2");
        linLayout.addView
(btn2, rightGravityParams);


Сохраним и запустим. Button1 имеет отступ 50px. А Button2 выравнена по правому краю:



Вероятно, эта тема будет не очень понятна с первого раза. Поэтому на следующих двух уроках мы закрепим эти знания и попрактикуемся в добавлении элементов на экран и их настройке.

Полный код урока:

public class MainActivity extends Activity {
   
/** Called when the activity is first created. */
   
@Override
   
public void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
       
// создание LinearLayout
       
LinearLayout linLayout = new LinearLayout(this);
       
// установим вертикальную ориентацию
       
linLayout.setOrientation(LinearLayout.VERTICAL);
       
// создаем LayoutParams 
       
LayoutParams linLayoutParam = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
       
// устанавливаем linLayout как корневой элемент экрана
       
setContentView(linLayout, linLayoutParam);
       
        LayoutParams lpView =
new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
       
        TextView tv =
new TextView(this);
        tv.setText
("TextView");
        tv.setLayoutParams
(lpView);
        linLayout.addView
(tv);
       
        Button btn =
new Button(this);
        btn.setText
("Button");
        linLayout.addView
(btn, lpView);

       
        LinearLayout.LayoutParams leftMarginParams =
new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        leftMarginParams.leftMargin =
50;
       
        Button btn1 =
new Button(this);
        btn1.setText
("Button1");
        linLayout.addView
(btn1, leftMarginParams);

       
        LinearLayout.LayoutParams rightGravityParams =
new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        rightGravityParams.gravity = Gravity.RIGHT;
       
        Button btn2 =
new Button(this);
        btn2.setText
("Button2");
        linLayout.addView
(btn2, rightGravityParams);
   
}
}


На следующем уроке:

- добавляем компоненты на экран во время работы приложения