MyTetra Share
Делитесь знаниями!
Урок 105. Android 3. Fragments. Динамическая работа
22.04.2017
11:18
Текстовые метки: Fragment
Раздел: Android - Ресурсы - StartAndroid

Урок 105. Android 3. Fragments.


Динамическая работа


03 сентября 2012



В этом уроке:

- динамически работаем с фрагментами

 

Размещать статические фрагменты мы уже умеем. Но, ясно дело, что гораздо интереснее работать с ними динамически. Система позволяет нам добавлять, удалять и заменять фрагменты друг другом. При этом мы можем сохранять все эти манипуляции в BackStack и кнопкой Назад отменять. В общем, все удобно и красиво.

Создадим простое приложение с двумя  фрагментами, которое будет уметь:

- добавлять первый фрагмент
- удалять первый фрагмент
- заменять первый фрагмент вторым фрагментом
- переключать режим сохранения в BackStack операций с фрагментами

 

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

Project name: P1051_FragmentDynamic
Build Target: Android 4.1 
Application name: FragmentDynamic
Package name: ru.startandroid.develop.p1051fragmentdynamic
Create Activity: MainActivity

В strings.xml добавим строки:


1

2

3

4

5

6

<string name="frag1_text">Fragment 1</string>

<string name="frag2_text">Fragment 2</string>

<string name="add">Add</string>

<string name="remove">Remove</string>

<string name="replace">Replace</string>

<string name="stack">add to Back Stack</string>

Создаем фрагменты. Как мы помним из прошлого урока, для этого нам нужны будут layout-файлы и классы, наследующие android.app.Fragment

 

fragment1.xml:


1

2

3

4

5

6

7

8

9

10

11

12

13

<?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:background="#77ff0000"

    android:orientation="vertical">

    <TextView

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="@string/frag1_text">

    </TextView>

</LinearLayout>

 

fragment2.xml:


1

2

3

4

5

6

7

8

9

10

11

12

13

<?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:background="#7700ff00"

    android:orientation="vertical">

    <TextView

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="@string/frag2_text">

    </TextView>

</LinearLayout>

 

Fragment1.java:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

package ru.startandroid.develop.p1051fragmentdynamic;

 

import android.app.Fragment;

import android.os.Bundle;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

 

public class Fragment1 extends Fragment {

 

  @Override

  public View onCreateView(LayoutInflater inflater, ViewGroup container,

      Bundle savedInstanceState) {

    return inflater.inflate(R.layout.fragment1, null);

  }

}

 

Fragment2.java:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

package ru.startandroid.develop.p1051fragmentdynamic;

 

import android.app.Fragment;

import android.os.Bundle;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

 

public class Fragment2 extends Fragment {

 

  @Override

  public View onCreateView(LayoutInflater inflater, ViewGroup container,

      Bundle savedInstanceState) {

    return inflater.inflate(R.layout.fragment2, null);

  }

}

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

 

Рисуем основное Activity.

main.xml:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

    xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:id="@+id/LinearLayout1"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical">

    <LinearLayout

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:orientation="vertical">

        <Button

            android:id="@+id/btnAdd"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="onClick"

            android:text="@string/add">

        </Button>

        <Button

            android:id="@+id/btnRemove"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="onClick"

            android:text="@string/remove">

        </Button>

        <Button

            android:id="@+id/btnReplace"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="onClick"

            android:text="@string/replace">

        </Button>

        <CheckBox

            android:id="@+id/chbStack"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="@string/stack">

        </CheckBox>

    </LinearLayout>

    <FrameLayout

        android:id="@+id/frgmCont"

        android:layout_width="match_parent"

        android:layout_height="match_parent">

    </FrameLayout>

</LinearLayout>

Три кнопки для добавления, удаления и замены фрагментов. Чекбокс для включения использования BackStack. И FrameLayout – это контейнер, в котором будет происходить вся работа с фрагментами. Он должен быть типа ViewGroup. А элементы Fragment, которые мы использовали на прошлом уроке для размещения фрагментов, нам не нужны для динамической работы. 

 

MainActivity.java:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

package ru.startandroid.develop.p1051fragmentdynamic;

 

import android.app.Activity;

import android.app.FragmentTransaction;

import android.os.Bundle;

import android.view.View;

import android.widget.CheckBox;

 

public class MainActivity extends Activity {

 

  Fragment1 frag1;

  Fragment2 frag2;

  FragmentTransaction fTrans;

  CheckBox chbStack;

   

  @Override

  public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

 

    frag1 = new Fragment1();

    frag2 = new Fragment2();

     

    chbStack = (CheckBox)findViewById(R.id.chbStack);

  }

 

  public void onClick(View v) {

    fTrans = getFragmentManager().beginTransaction();

    switch (v.getId()) {

    case R.id.btnAdd:

      fTrans.add(R.id.frgmCont, frag1);

      break;

    case R.id.btnRemove:

      fTrans.remove(frag1);

      break;

    case R.id.btnReplace:

      fTrans.replace(R.id.frgmCont, frag2);

    default:

      break;

    }

    if (chbStack.isChecked()) fTrans.addToBackStack(null);

    fTrans.commit();

  }

}

В onCreate создаем пару фрагментов и находим чекбокс.

В onClick мы получаем менеджер фрагментов с помощью метода getFragmentManager. Этот объект является основным для работы с фрагментами. Далее, чтобы добавить/удалить/заменить фрагмент, нам необходимо использовать транзакции. Они аналогичны транзакциям в БД, где мы открываем транзакцию, производим операции с БД, выполняем commit. Здесь мы открываем транзакцию, производим операции с фрагментами (добавляем, удаляем, заменяем), выполняем commit.

Итак, мы получили FragmentManager и открыли транзакцию методом beginTransaction. Далее определяем, какая кнопка была нажата:

если Add, то вызываем метод add, в который передаем id контейнера (тот самый FrameLayout из main.xml) и объект фрагмента. В итоге, в контейнер будет помещен Fragment1

если Remove, то вызываем метод remove, в который передаем объект фрагмента, который хотим убрать. В итоге, фрагмент удалится с экрана.

если Replace, то вызываем метод replace, в который передаем id контейнера и объект фрагмента. В итоге, из контейнера удалится его текущий фрагмент (если он там есть) и добавится фрагмент, указанный нами.

Далее проверяем чекбокс. Если он включен, то добавляем транзакцию в BackStack. Для этого используем метод addToBackStack. На вход можно подать строку-тэг. Я передаю null.

Ну и вызываем commit, транзакция завершена.

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

 

Жмем Add

появился первый фрагмент.

 

Жмем Remove

фрагмент удалился.

 

Еще раз добавим первый фрагмент – жмем Add. И жмем Replace

первый фрагмент заменился вторым.

Жмем кнопку Назад. Приложение закрылось, т.к. все эти операции с фрагментами не сохранялись в BackStack. Давайте используем эту возможность.

Снова запускаем приложение и включаем чекбокс add to Back Stack

Выполняем те же операции: AddRemoveAddReplace. У нас добавится первый фрагмент, удалится первый фрагмент, добавится первый фрагмент, заменится вторым. В итоге мы снова видим второй фрагмент. Теперь жмем несколько раз кнопку Назад и наблюдаем, как выполняются операции, обратные тем, что мы делали. Когда транзакции, сохраненные в стеке закончатся, кнопка Назад закроет приложение.

Т.е. все достаточно просто и понятно. Скажу еще про пару интересных моментов.

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

Когда мы удаляем фрагмент и не добавляем транзакцию в BackStack, то фрагмент уничтожается. Если же транзакция добавляется в BackStack, то, при удалении, фрагмент не уничтожается (onDestroy не вызывается), а останавливается (onStop).

 

В качестве самостоятельной работы: попробуйте немного изменить приложение и добавлять в один контейнер сразу два фрагмента. Возможно, результат вас удивит ) 

 

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

- рассмотрим взаимодействие между Activity и ее фрагментами

Так же в этом разделе:
 
MyTetra Share v.0.52
Яндекс индекс цитирования