반응형
Fragment (프래그먼트)
- 프래그먼트 는 일종의 컴포넌트 같은 개념이다.
- 여러 개의 프래그먼트를 하나의 액티비티에 결합하여 창이 여러 개인 UI를 빌드할 수 있다.
- 그리고 하나의 프래그먼트를 여러 액티비티에서 재사용할 수 있습니다.
- 프래그먼트는 액티비티처럼 레이아웃을 가진 독립적인 개체로서, 자체적인 생명주기를 가지고 액티비티 실행 중에 화면에 동적으로 추가되거나 다른 프래그먼트로 교체가 가능하다.
- 한 개의 액티비티에 들어가는 화면 요소를 프래그먼트 단위로 나누어 관리하기 때문에 레이아웃을 분리 관리할 수 있고, 액티비티의 화면 구성을 위한 레이아웃의 복잡도도 줄일 수 있다.
- 프래그먼트는 항상 액티비티 내에서 호스팅되어야 하며, 해당 프래그먼트의 생명주기는 호스트 액티비티의 생명주기에 직접적으로 영향을 받는다.
- 예를 들어 액티비티가 일시정지되는 경우, 그 안의 모든 프래그먼트도 일시정지된다. 마찬가지로 액티비티가 소멸하면 그 안의 모든 프래그먼트도 소멸한다.
How Fragments Work (프래그먼트 동작 방식)
- 프래그먼트는 FragmentManager에 의해 관리되며, 프래그먼트 트랜잭션(추가, 교체, 삭제 등) 수행은 FragmentManager로부터 FragmentTransaction 인스턴스를 가져와 사용한다.
- supportFragmentManager.beginTransaction()
Fragment lifecycle (프래그먼트 생명주기)
- onAttach(): 프래그먼트가 액티비티와 연결될 때 호출 (이 시점부터 프래그먼트가 동작한다.)
- onCreate(): 프래그먼트가 초기화될 때 호출된다.
- onCreateView(): 시스템은 프래그먼트가 자신의 사용자 인터페이스를 처음으로 구성할 때 이 메서드를 호출한다.
프래그먼트에 맞는 UI를 그리려면 메서드에서 View를 반환해야 하며, 이 메서드는 프래그먼트 레이아웃의 root다.
프래그먼트가 UI를 제공하지 않는 경우 null을 반환한다. - onActivityCreated(): 액티비티의 onCreate() 메서드가 반환할 때 호출된다.
- onStart(): 프래그먼트가 보여질 수 있을 때 호출된다.
- onResume(): 프래그먼트가 사용자와 상호작용할 수 있을 때 호출된다.
- onPause(): 시스템이 이 메서드를 호출하는 것은 유저가 프래그먼트 사용을 중지한다는 것을 암시한다.
- onStop(): 프래그먼트나 부모 액티비티가 중지 됐을 때 호출 View의 상태 값을 저장하는 함수다.
- onDestroyView(): 프로그먼트 View에 대한 모든 참조를 해제할 수 있도록 호출한다.
- onDestroy(): 프래그먼트가 완전히 제거되거나 FragmentManager가 destroy 되었을 때 호출된다.
- onDetach(): onDestory()가 호출된 후 호출된다.
프래그먼트 주요 클래스
클래스 요약 | |
Fragment.SavedState | FragmentManager.saveFragmentInstanceState() 메소드에 의해 저장된 프래그먼트 상태 정보 |
FragmentManager | 액티비티 내에서 프래그먼트 객체와 상호작용하기 위한 인터페이스를 제공하는 프래그먼트 매니저 |
FragmentTransaction | 프래그먼트를 추가하거나 제거 또는 삭제 등을 수행할 수 있는 프래그먼트 트랜잭션 |
Activity 내의 Fragment를 관리하기 위해서는 FragmentManager를 사용한다.
FragmentManager가 할 수 있는 일은 아래와 같은 일이 있다.
- findFragmentById() or findFragmentByTag()로 Fragment 가져오기
- popBackStack()을 사용하여 Fragment를 BackStack에서 꺼내기
- beginTransaction()을 사용하여 FragmentTransaction을 가져오기
FragmentTransaction을 이용하여 아래와 같은 일을 할 수 있다.
- add(): Fragment 추가
- remove(): Fragment 제거
- replace(): Fragment 변경
프레그먼트 사용 예시 코드
먼저 first_fragment_exam.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=".FirstFragmentExamMainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragmentContainerView"
android:layout_width="match_parent"
android:layout_height="600dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_fragment_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="프래그먼트 1"
app:layout_constraintEnd_toStartOf="@+id/btn_fragment_2"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/fragmentContainerView" />
<Button
android:id="@+id/btn_fragment_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="프래그먼트 2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/btn_fragment_1"
app:layout_constraintTop_toTopOf="@+id/btn_fragment_1" />
</androidx.constraintlayout.widget.ConstraintLayout>
다음은 first_fragment_exam_first_fragment.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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/fragment_first">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fragment 1"
android:textColor="@color/black"
android:textSize="30sp"
android:layout_marginTop="300dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_go_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Go to Fragment-2"
android:textAllCaps="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout>
다음은 first_fragment_exam_second_fragment.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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/fragment_second">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fragment 2"
android:textColor="@color/black"
android:textSize="30sp"
android:layout_marginTop="300dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_go_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Go to Fragment-1"
android:textAllCaps="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout>
이제 프래그먼트를 구현한 코틀린 코드와 액티비티 코드다.
먼저 사용되는 프래그먼트 2개에 관한 코드다.
class FragmentFirst : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.first_fragment_exam_first_fragment, container, false)
view.findViewById<Button>(R.id.btn_go_second).setOnClickListener{
(activity as FirstFragmentExamMainActivity).onReplaceFragment(FragmentSecond());
}
return view;
}
}
class FragmentSecond : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.first_fragment_exam_second_fragment, container, false)
view.findViewById<Button>(R.id.btn_go_first).setOnClickListener{
(activity as FirstFragmentExamMainActivity).onReplaceFragment(FragmentFirst());
}
return view
}
}
마지막으로 FirstFragmentExamMainActivity 클래스 코드다.
class FirstFragmentExamMainActivity : AppCompatActivity() {
val binding by lazy{
FirstFragmentExamBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.btnFragment1.setOnClickListener{
onReplaceFragment(FragmentFirst())
}
binding.btnFragment2.setOnClickListener{
onReplaceFragment(FragmentSecond())
}
}
fun onReplaceFragment(fragment: Fragment){
val ft = supportFragmentManager.beginTransaction()
ft.replace(R.id.fragmentContainerView,fragment).commit()
}
}
그럼 메인 화면에서 버튼을 누르면 아래와 같은 두 UI를 확인할 수 있다.
이상으로 포스팅을 마칩니다. 감사합니다!
참고자료
https://developer.android.com/guide/components/fragments?hl=ko
반응형
댓글