본문 바로가기
Kotlin 공부 노트

프래그먼트(Fragment) with Kotlin 알아보기!

by 지게요 2022. 2. 10.
728x90
반응형

# 프래그먼트(Fragment)

안드로이드 공식 문서에 보면 프래그먼트를 아래와 같이 설명하고 있다.

Fragment는 FragmentActivity 내의 어떤 동작 또는 사용자 인터페이스의 일부를 나타냅니다. 여러 개의 프래그먼트를 하나의 액티비티에 결합하여 창이 여러 개인 UI를 빌드할 수 있으며, 하나의 프래그먼트를 여러 액티비티에서 재사용할 수 있습니다. 프래그먼트는 액티비티의 모듈식 섹션이라고 생각하면 됩니다.

정리하자면 프래그먼트를 사용하면 재사용할 수 있는 레이아웃을 분리해서 관리할 수 있고, 액티비티의 복잡도도 줄여주며, 크기가 고정이라 하더라도 부분적인 UI 변화에서 유용하게 사용된다. 특히, 액티비티 하나만 만들고 나머지는 프래그먼트로 처리하여 단일 액티비티로 개발할 때도 있다.

 

# 프래그먼트(Fragment)의 특징

●  프래그먼트는 앱의 전체 UI에서 어딘가에 반복적으로 재사용 가능한 부분을 말한다.(Fragment의 존재 이유)

●  프래그먼트는 독립적으로 존재할 수 없고, 반드시 Activity나 다른 프래그먼트에 호스팅되어야 한다.

●  Activity 내에서 실행 중에 추가/제거가 가능하다.

●  다른 Activity에서도 사용할 수 있어 재사용성이 뛰어나다.

●  프래그먼트는 자체 레이아웃(xml파일을 정의할 수 있음)을 가질 수 있으며 자체 생명 주기를 보유한다. 또한 자체 입력 이벤트를 받으며 처리할 수 있다.(자체 레이아웃을 갖는 것은 선택 사항, 자체 UI가 없는 프래그먼트도 만들 수 있음)

※ 프래그먼트의 생명주기가 궁금하다면 여기를 눌러서 보고 오는것도 도움이 될 거 같다.

 

# 프래그먼트(Fragment) 사용법

여기서 나오는 예제는 홍드로이드님의 예제를 사용했다.

위와 같이 버튼을 누르면 프래그먼트가 바뀌는 걸 구현해보겠다.

 

# activity.xml 구성

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".MainActivity"
    android:orientation="vertical"
    android:padding="5dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
    <Button
        android:id="@+id/btn_fragment1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="프래그먼트 1"
        android:layout_marginEnd="5dp"
        android:layout_weight="1"/>
    <Button
        android:id="@+id/btn_fragment2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="프래그먼트 2"
        android:layout_marginEnd="5dp"
        android:layout_weight="1"/>
    <Button
        android:id="@+id/btn_fragment3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginEnd="5dp"
        android:text="프래그먼트 3"
        android:layout_weight="1"/>
    </LinearLayout>

    <FrameLayout
        android:id="@+id/fragment_container_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </FrameLayout>


</LinearLayout>

버튼들을 배치후 그 아래에 FrameLayout을 적용한다.

 

# activity안에 들어갈 Fragment.xml들을 생성해준다.

 

<fragment_main.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:background="#E0EFDB"
    tools:context=".MainFragment">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="프래그먼트 1"
        android:textAlignment="center"
        android:textSize="35sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

<fragment2_main.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:background="#EABCEF"
    tools:context=".MainFragment">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="프래그먼트 2"
        android:textAlignment="center"
        android:textSize="35sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

<fragment3_main.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:background="#F4C1C1"
    tools:context=".MainFragment">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="프래그먼트 3"
        android:textAlignment="center"
        android:textSize="35sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

각기 다른 background color와 textview를 줘서 구분을 쉽게 해 준다.

 

# Fragment()를 상속받는 Fragment 클래스 생성

    - Fragment 클래스를 만드는 방법 1

[New] → [Fragment] → [Fragment(Blank)] 이렇게도 만들 수 있지만 지금은 다른 방법을 사용해보겠다.


- Fragment 클래스를 만드는 방법 2

[New] → [Kotlin Class/File] 클릭 후

이름을 정해준다. 여기서는 MainFragment로 정했다.

class MainFragment : Fragment() {
   
}

Fragment()를 상속받는다.

[Ctrl] + [O]를 눌러 Override Members를 띄운다 그 후 onCreateView를 검색해 [OK]를 눌러준다.

class MainFragment : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_main, container, false)
    }
}

좀 더 보기 좋게 inflater 한 것을 view에 담아서 view를 return 하게 한다.

class MainFragment : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.fragment_main, container, false)

        return view
    }
}

만들어준 MainFragment를 복사해 클래스 파일을 2개 더 만들어 준다.

 

# MainActivity.class

package com.example.fragment_ex

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.fragment_ex.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    // 뷰 바인딩 생성
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        setFrag(0)
        with(binding) {
           btnFragment1.setOnClickListener {
                setFrag(0)
            }
            btnFragment2.setOnClickListener {
                setFrag(1)
            }
            btnFragment3.setOnClickListener {
                setFrag(2)
            }
        }
    }

    private fun setFrag(fragNum : Int){
        // FragmentManager를 이용해 프래그먼트 관리
        val fragmentTransaction = supportFragmentManager.beginTransaction()
        when(fragNum){
            0 ->{
                // replace를 사용해 프래그먼트 교체
                fragmentTransaction.replace(R.id.fragment_container_view,MainFragment()).commit()
            }
            1 ->{
                // replace를 사용해 프래그먼트 교체
                fragmentTransaction.replace(R.id.fragment_container_view,MainFragment2()).commit()
            }
            2 ->{
                // replace를 사용해 프래그먼트 교체
                fragmentTransaction.replace(R.id.fragment_container_view,MainFragment3()).commit()
            }
        }
    }
}

setFrag라는 함수를 만들어 조금 더 간편하게 구현을 하였다.

fragmentTransaction.replace() 안에는 fragmentTransaction.replace("activity에서 만들어준 fragment가 담길 id", "만들어준 fragment클래스")이 담긴다.

 

참고 사이트
https://www.youtube.com/watch?v=BT206iXW9bk
반응형