Освой программирование играючи

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

Шкодим

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

ViewStub

Компонент ViewStub - это легкий View, не имеющий размеров. Находится в разделе Advanced. Он ничего не рисует на экране, если его разместить на форме. Так зачем он нужен?

ViewStub выполняет роль заглушки, заменяя собой дочерние элементы внутри родительской разметки.

Возможно ваша разметка чересчур перегружена тяжёлыми элементами, которые редко используются. ViewStub позволят разгрузить разметку. Предположим, вы разработали экран с книжной полкой. Если у пользователя нет книг в коллекции, то нет особого смысла выводить TextView, Button и другие элементы с указанием авторов книги, названия и т.д. В нужный момент вы программно подгружаете невидимую разметку. По существу, это лёгкий элемент для отображения или сокрытия в иерархии View. Каждый ViewStub просто должен включать в себя атрибут android:layout для указания разметки, которую нужно отобразить.

Создадим новый проект и добавим ViewStub и другие компоненты.


<LinearLayout 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"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Где ViewStub?" />

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="Открыть ViewStub" />

    <ViewStub
        android:id="@+id/viewStub"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:inflatedId="@+id/inflate"
        android:layout="@layout/viewstub_layout" />

</LinearLayout>

Мы указали у ViewStub в атрибуте android:layout разметку @layout/viewstub_layout. Создадим её в папке res/layout:


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

    <TextView
        android:id="@+id/textViewInViewStub"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Я TextView из ViewStub" />

    <Button
        android:id="@+id/buttonInViewStub"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:minWidth="100dp"
        android:text="Я кнопка из ViewStub" />

</LinearLayout>

Теперь переходим к основной активности и напишем код для нажатия кнопки, который и будет выводить подготовленную разметку:


package ru.alexanderklimov.testapplication;

import ...

public class MainActivity extends ActionBarActivity {

    private boolean mIsClicked = true;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
    }

    public void onClick(View v) {
        if (mIsClicked) {
            ViewStub viewStub = (ViewStub) findViewById(R.id.viewStub);
            viewStub.inflate();
            mIsClicked = false;
        }
    }
}

Булева переменная mIsClicked позволяет уберечься от повторного показа ViewStub. C помощью метода inflate() мы выводим разметку из файла viewstub_layout.xml на экран вместо самого ViewStub. Обратите внимание на атрибут android:inflatedId="@+id/inflate" у ViewStub в первой разметке. Когда мы вызываем метод inflate() и ViewStub станет видимым, он больше не будет являться частью иерархии View, и ID для корня View заменится на указанный в атрибуте android:inflatedId идентификатор inflate (android:id, указанный для ViewStub, действует только до того момента, пока ViewStub не станет видимым). В этом легко убедиться. Добавим для кнопки из разметки viewstub_layout.xml обработчик нажатия кнопки:


<Button
    android:id="@+id/buttonInViewStub"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:minWidth="100dp"
    android:onClick="onViewStubButtonClick"
    android:text="Я кнопка из ViewStub" />

Напишем код для щелчка:


public void onViewStubButtonClick(View view) {
    View testView = (View) findViewById(R.id.inflate);
    testView.setBackgroundColor(Color.BLUE);
}

Когда мы нажимаем на первую кнопку, то выводим на экран контейнер ViewStub, который содержит ещё одну кнопку. Кроме того у нас появился новый идентификатор inflate и мы пробуем закрасить разметку в синий цвет. Если запустить проект, то увидим работающий пример. А если мы установим идентификатор самого ViewStub - viewStub, то получим ошибку.

Реклама