Android - Fragment와 FragmentManager

MUNGI JO·2024년 2월 7일

Android 공부

목록 보기
3/8

Fragment란

FragmentActivity내의 어떤 동작 또는 사용자 인터페이스의 일부를 나타낸다.
여러개의 fragment를 사용하여 하나의 액티비티에 결합해 여러개의 창을 가진 UI를 빌드할 수 있고 하나의 프래그먼트로 여러 액티비티에서 재사용 가능하다. 즉, 액티비티의 모듈식 섹션이라고 볼 수 있다. - 공식문서

특징 -
1. 자체 수명을 가진다.
2. 자체 입력 이벤트를 수신한다.
3. 액티비티 실행 중에 추가 및 삭제가 가능하다. (하위 액티비티 같은 개념)
4. 항상 액티비티 내에서 호스팅 되어야 한다. 따라서 호스팅 액티비티의 수명 주기에 직접적인 영향을 받는다. ex) 호스팅 된 액티비티가 정지되거나 삭제되면 fragment도 정지/삭제 된다. 즉, 독립적으로 존재할 수 없다.
5. 프래그먼트는 하나 이상의 하위 프래그먼트 호스팅이 가능하다.
6. 액티비티가 실행중에는 개별적인 조작이 가능하다. 이런 fragment tranjection을 수행할 때는 이를 액티비티가 관리하는 백 스택(뒤로 버튼 누르면 이전 화면으로 돌아가는 것 처럼 뒤로 돌아갈 화면들의 스택 자세히)에도 추가할 수 있다.
7. 프래그먼트를 액티비티 레이아웃에 추가하면 ViewGroup에 들어가고 자체적인 뷰 레이아웃을 정의한다.

메서드 -
프래그먼트는 기본적으로 아래 2가지 메서드를 가진다.
onCreate(LayoutInflater inflater, Bundle bundle)
onCreateView(Bundle bundle)
생명주기를 학습했다면 금방 감이 올 것이다.
onCreate부분은 Fragment가 생성될 때 호출되는 부분이고
onCreateView는 onCreate이후 화면을 구성할 때 호출되는 메서드다.
따라서 화면을 구성하는 부분을 onCreateView 메서드 안에 넣어서 구현해야 한다.

리사이클러뷰나 다른 뷰를 사용할 때 onCreateView 메서드 안에 작성하면 된다.

FragmentManager란

프래그먼트를 사용할 때 프래그먼트 관리자를 가져와야 한다. 프래그먼트 관리자(FragmentManager)는 삭제, 교체를 도와주고 백 스택에 추가하는 등의 작업을 실행한다.

getSupportFragmentManager() 메서드를 통해 프래그먼트의 하위 요소를 관리하는 FragmentManaget 참조를 가져올 수 있다.

프래그먼트, 프래그먼트 호스트, 각각과 연결된 FragmentManager 인스턴스 간의 관계를 확인해보면

Example 1은 분할 뷰 화면으로 여러 프래그먼트를 한 번에 보여주고
Example 2는 Swipe를 통해 여러 프래그먼트를 볼 수 있도록 구성하는 (수평 방향 리사이클러 뷰 같은) Layout이다.
2가지 예 모두 단일 활동 호스트가 있고 호스트 활동으로 호스트 프래그먼트를 다양한 화면으로 교체하는 작업을 담당하는 BottomNavigationView를 가진다. 이를 통해 최상위 탐색(흔히 최상위 메뉴바) 사용자에게 표시할 수 있다.

Example 1에서는 분할 뷰 화면을 구성하는 하위 프래그먼트 2개를 호스팅하고
Example 2에서는 스와이프 뷰의 디스플레이 프래그먼트를 구성하는 하위 프래그먼트 하나를 호스팅 하는데 이를 통해 하위 프래그먼트를 관리하는 FragmentManager가 각 호스트에 연결되어 있다고 생각할 수 있다.
즉, HostFragment에 있는 FragmentManager가 하위 Fragment를 구성할 수 있도록 해준다는 것. 따라서 어떤식으로 해당 화면이 구성되어 있는 지 그림으로 보게 되면

  1. HostActivity 는 최초로 fragment를 호스팅한 액티비티이며 ex)MainActivy
  2. HostFragment HostActivity에 제일 처음 호스팅 된 Fragment다.
  3. ChildFragment(s)는 HostFragment밑에 있는 모든 Fragment를 말한다.
    따라서 HostFragment에게는 HostActivity가 parent가 되고 HostActivity에 있는 FragmentManager가 parentFragmentManager를 가지게 되는 것.
  • FragmentActivity는 Fragment를 사용하는 Activity를 말하므로 HostActivity가 FragmentActivity가 될 것이다. 이후 존재하는 Fragment가 가지는 FragmentManager는 모두 ChildFragmentManager가 되는 것.

Fragment 사용

1. FragmentContainer

FragmentContainer는 FrameLayout을 확장한 Fragment전용 Layout으로 여러 개의 Fragment를 사용할 수 있는 Layout이다. z-ordering 문제점도 해결되어 더욱 깔끔하고 자연스러운 모션을 보여준다. 이 FragmentContainer를 사용해서 간단한 Fragment 구현을 해보겠다.

FragmentTestActivity
FistFragment
SecondFragment
를 액티비티와 프래그먼트로 새로 생성해주고

activity_fragment_test.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    android:background="@color/white"
    tools:context=".FragmentTestActivity">

    <android.widget.Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="First"
        app:layout_constraintEnd_toStartOf="@+id/button2"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <android.widget.Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Second"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/button1"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/flContainer"
        android:name="com.example.newsrecyclerpage_ipp.FirstFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button1" />

</androidx.constraintlayout.widget.ConstraintLayout>

fragment_first 와 fragment_sencond 는 id와 text값만 다를 뿐이므로 해당 부분만 수정하면 된다.

fragment_first.xml & fragment_sencond.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".FirstFragment">

    <TextView
        android:id="@+id/tvFirstFragment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="First Fragment"
        android:textSize="30sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.5" />
</androidx.constraintlayout.widget.ConstraintLayout>

activity_gragment_test.xml은 간단하게 두 버튼과 하나의 FragmentContainerLayout으로 구성하였다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    android:background="@color/white"
    tools:context=".FragmentTestActivity">

    <android.widget.Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="First"
        app:layout_constraintEnd_toStartOf="@+id/button2"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <android.widget.Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Second"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/button1"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/flContainer"
        android:name="com.example.newsrecyclerpage_ipp.FirstFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button1" />


</androidx.constraintlayout.widget.ConstraintLayout>

FragmentTestActivity는 두 버튼을 통해 각기 다른 글자가 보이도록만 했다.

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

public class FragmentTestActivity extends AppCompatActivity {

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

        findViewById(R.id.button1).setOnClickListener(v->{
            getSupportFragmentManager().beginTransaction().replace(R.id.flContainer, new FirstFragment()).commit();
        });
        findViewById(R.id.button2).setOnClickListener(v->{
            getSupportFragmentManager().beginTransaction().replace(R.id.flContainer, new SecondFragment()).commit();
        });
    }
}

다른 FragmentFirst, Second는 건드리지 않았다. 이렇게 생성해서 실행하면

Fragmentcontainer name에 firstFragment를 적용해놨으므로 default로 FirstFragment가 보이게 되고 버튼을 눌러서 양 Fragment간 화면 전환이 가능하다.

참고 사이트 :
Android developer - fragment

profile
안녕하세요. 개발에 이제 막 뛰어든 신입 개발자 입니다.

0개의 댓글