Android Fragment. Что это? – Devcolibri – Android для начинающих

Android Fragment. Что это?

В этом уроке, я хочу объяснить, что такое Fragment и почему его нужно использовать. Мы рассмотрим немного теории, а также практический пример применения Fragments.

Представьте себе пазл, который вы можете сложить и получить общий вид картинки, именно так можно представить Fragment. Или же если вы работали разработкой сайтов, а именно PHP то вам знакома возможность подключать общие части сайта например меню как отдельного блока с помощью include.

Шаг 0. Теория

Так как определение не совсем понятно, я решил сказать своими словами его.

Fragment (Фрагмент) – по сути это подобие Activity, которое мы можем подключать в разные части приложения. Но одно Activity может содержать несколько fragment.

Фрагменты появились в API 11 (Android 3.0) для поддержки на более старых версиях был доработан Android Support library.

Также важно понимать, что фрагменты – это не замена активности, они не могут существовать сами по себе, а только вместе с Activity. Поэтому в AndroidManifest регистрировать Fragments не нужно.

Шаг 1. Создаем проект

Давайте создадим простой проект, пока без использования Fragment-ов. Создаем Android Gradle Project:

Теперь создадим Activity в пакете com.myfragmentexam.app назовем его MainActivity:

package com.myfragmentexam.app;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_layout);
    }
}

Для этого activity нам нужно создать layout, создаем в res/layout новый layout и называем его main_layout:

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Кнопка 1"
            android:id="@+id/button" android:layout_marginTop="20dp"/>
    <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Кнопка 2"
            android:id="@+id/button2"/>
    <CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Новый компонент 1"
            android:id="@+id/checkBox" android:layout_gravity="center_horizontal" android:checked="false"
            android:layout_marginTop="20dp"/>
    <CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Новый компонент 2"
            android:id="@+id/checkBox2" android:layout_gravity="center_horizontal" android:checked="false"/>
    <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/imageView" android:layout_gravity="center_horizontal" 
            android:src="@drawable/android_img"
            android:layout_marginTop="20dp"/>
</LinearLayout>

Как видите в 33-й строке мы указываем на ресурс изображения, для этого вам нужно в res/drawable добавить следующее изображение:

Последним шагом нужно зарегистрировать activity MainActivity в AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.myfragmentexam.app">

    <application android:allowBackup="true"
        android:label="@string/app_name"
        android:icon="@drawable/ic_launcher"
        android:theme="@style/AppTheme">

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

</manifest>

Начиная с 9-й строки мы регистрируем Activity в контексте.

Теперь запустим. Мы должны увидеть следующее:

Пока это простое приложение, которое не выполняет никакой логики и не имеет фрагментов.

Шаг 2. Делим на части

Особенность Fragment-ов в том, что вы можете разбить внешний вид на блоки и потом подключать их для отображения на разных устройствах по своему (смартфон/планшет). Также мы получим возможность переиспользования блоков(Fragments).

Первыйм делом вынесем кнопки в отдельный фрагмент, в res/layout создаем новый layout и называем его button_fragment:

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Кнопка 1"
            android:id="@+id/button" android:layout_marginTop="20dp"/>
    <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Кнопка 2"
            android:id="@+id/button2"/>

</LinearLayout>

Выглядеть это будет так:

Теперь вынесем CheckBox-сы в отдельный layout назовем его checkbox_fragment:

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Новый компонент 1"
            android:id="@+id/checkBox" android:layout_gravity="center_horizontal" android:checked="false"
            android:layout_marginTop="20dp"/>
    <CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Новый компонент 2"
            android:id="@+id/checkBox2" android:layout_gravity="center_horizontal" android:checked="false"/>

</LinearLayout>

Выглядеть это будет так:

И вынесем картинку в layout назвав его image_fragment:

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/imageView" android:layout_gravity="center_horizontal"
            android:src="@drawable/android_img"
            android:layout_marginTop="20dp"/>

</LinearLayout>

Выглядеть это будет так:

Шаг 3. Создаем Fragments

Мы поделили наш первоначальный вид на части, теперь давайте создадим на их основе фрагменты.

Посмотрите на структуру классов ниже и на её основе создайте пакет fragments и в нем классы классы ButtonFragmentCheckBoxFragmentImageFragment.

Для того чтобы все эти классы стали фрагментами их нужно унаследовать от класса Fragment. Обратите внимание что класс фрагмент мы будем использовать не со стандартной библиотеки android.app, а с android.support.v4.app.

Причина этого то что фрагменты в вспомогательном пакете более лучше поддерживаются и если сравнивать со стандартным, то он не имеет тех багов, которые имеет стандартный пакет(android.app).

В Activity мы подключали layout в методе onCreate() через метод setContentView(). Но в фрагментах метод onCreate() используется немного для других целей. Поэтому для подключения layout используется отдельный метод onCreateView().

Давайте начнем с ButtonFragment:

package com.myfragmentexam.app.fragments;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.myfragmentexam.app.R;

public class ButtonFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
                             Bundle savedInstanceState) {
        
        View viewHierarchy = inflater.inflate(R.layout.button_fragment, container, false);
        
        return viewHierarchy;
    }
}

Теперь детальней рассмотрим что же мы тут делаем.

LayoutInflater –  позволяет построить нужный макет, считывая информацию из указанного XML-файла.

Обратите внимание на то что 16-й строке в метод inflate() мы передаем 3 параметра разметку нашего фрагмента, контейнер, и значение (true |false), которое указывает на возможность подключения фрагментов в Activity через контейнер. Мы указали false так как сами создаем блоки для фрагментов.

Теперь по аналогии создадим реализацию для фрагмента CheckBoxFragment:

package com.myfragmentexam.app.fragments;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.myfragmentexam.app.R;

public class CheckBoxFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View viewHierarchy = inflater.inflate(R.layout.checkbox_fragment, container, false);

        return viewHierarchy;
    }

}

И для последнего ImageFragment:

package com.myfragmentexam.app.fragments;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.myfragmentexam.app.R;

public class ImageFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View viewHierarchy = inflater.inflate(R.layout.image_fragment, container, false);

        return viewHierarchy;
    }
}

Шаг 4. Собираем все в кучу

Мы создали пачку фрагментов, но что с ними делать? Их мы теперь можем подключать в те места куда нам нужно. Для примера мы переделаем MainActivity и main_layout под фрагменты.

Для начало давайте модифицируем MainActivity:

package com.myfragmentexam.app;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_layout);
    }

}

Обратите на строку 6, как видите мы наследуемся не просто от Activity, а от FragmentActivity это нужно делать когда вы используете Fragment с пакета android.support.v4.app.

Теперь модифицируем layout для нашего Activity, а именно main_layout:

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent">

    <fragment
            android:name="com.myfragmentexam.app.fragments.ButtonFragment"
            android:id="@+id/button_fragment"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"/>

    <fragment
            android:name="com.myfragmentexam.app.fragments.CheckBoxFragment"
            android:id="@+id/checkbox_fragment"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"/>

    <fragment
            android:name="com.myfragmentexam.app.fragments.ImageFragment"
            android:id="@+id/image_fragment"
            android:layout_weight="1"
            android:layout_height="0dp"
            android:layout_width="match_parent"/>

</LinearLayout>

Обратите внимание на выделенные строки, тут мы указываем какой фрагмент подключать.

Но теперь в Intellij IDEA режим Preview работает не корректно:

Для того чтобы это исправить нам нужно немного модифицировать main_layout:

<?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:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent">

    <fragment
            android:name="com.myfragmentexam.app.fragments.ButtonFragment"
            android:id="@+id/button_fragment"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            tools:layout="@layout/button_fragment"/>

    <fragment
            android:name="com.myfragmentexam.app.fragments.CheckBoxFragment"
            android:id="@+id/checkbox_fragment"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            tools:layout="@layout/checkbox_fragment"/>

    <fragment
            android:name="com.myfragmentexam.app.fragments.ImageFragment"
            android:id="@+id/image_fragment"
            android:layout_weight="1"
            android:layout_height="0dp"
            android:layout_width="match_parent"
            tools:layout="@layout/image_fragment"/>

</LinearLayout>

На выделенных строках видно изменения, таким образом мы указали фрагментам на нашем layout какие layout они отображают.

И теперь режим Preview работает корректно:

После этого, можно запустить и проверить. Вы должны увидеть тоже что показано на Preview.

Шаг 5. Добавляем альбомный вид

Для этого создаем в res папке layout-land и копируем в в него все содержимое папки layout.

После этого немного изменим расположение фрагментов на main_layout. Обратите внимание, что мы будем менять расположение фрагментов, а не их компонентов, что довольно таки удобно.

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

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:orientation="horizontal"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent">

    <fragment
            android:name="com.myfragmentexam.app.fragments.ButtonFragment"
            android:id="@+id/button_fragment"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            tools:layout="@layout/button_fragment"
            android:layout_alignParentLeft="true"
            android:layout_marginLeft="15dp"
            android:layout_alignParentTop="true"
            android:layout_toLeftOf="@+id/image_fragment"/>

    <fragment
            android:name="com.myfragmentexam.app.fragments.CheckBoxFragment"
            android:id="@+id/checkbox_fragment"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            tools:layout="@layout/checkbox_fragment"
            android:layout_below="@+id/button_fragment"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_toLeftOf="@+id/image_fragment"
            android:layout_marginLeft="15dp"/>

    <fragment
            android:name="com.myfragmentexam.app.fragments.ImageFragment"
            android:id="@+id/image_fragment"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            tools:layout="@layout/image_fragment"
            android:layout_alignParentTop="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true"
            android:layout_marginRight="15dp"
            android:layout_marginLeft="15dp"/>

</RelativeLayout>

Теперь запускаем и смотрим на результат:

Теперь у нас есть вид как для смартфонов так и для планшетов.

ПОХОЖИЕ ПУБЛИКАЦИИ

    None Found

61094
24/05/2014

12 комментариев к статье "Android Fragment. Что это?"

Добавить комментарий

Сайт использует cookie-файлы для того, чтобы вам было удобнее им пользоваться. Для продолжения работы с сайтом, вам необходимо принять использование cookie-файлов.

Я ознакомлен(а)