본문 바로가기
Android/이것저것

Fragment

by 일상 속 둔치 2020. 7. 5.

안드로이드는 Activity 단위로 화면을 표시해준다.

 

그러나 Activity 내의 일부만 변경하고 싶은 경우가 생길 수 있다.

 

물론, 새 Activity로 구현할 수 있지만 중복되는 코드가 생기기 때문에 바뀌는 부분만 새로 작성하고 싶다!

 

이때 사용되는 것이 Fragment이다.

 

출처 : https://developer.android.com/guide/components/fragments?hl=ko

Activity 내에 fragment라는 View를 만들어주고 해당 View에 Fragment를 등록해주는 방식으로 사용한다.

 

Fragment 클래스를 통해 xml을 인플레이트하고 Activity에서 FragmentManager를 통해 원하는 Fragment를 Activity에 있는 fragment View에 등록하여 사용한다.

 

요약하면 다음과 같다.

 

1. Activity XML에 Fragment를 담을 View를 선언

2. Fragment를 상속 받는 클래스로 Activity처럼 구현 (생명주기는 다르긴하지만 기본적인 형식은 Activity와 유사하다)

3. Activity에서 FragmentManager를 통해 원하는 Fragment를 1에서 선언한 View에 등록

 

코드를 살펴보자.

 

1. Activity XML에 Fragment를 담을 View를 선언

<?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=".MainActivity">

    <EditText
        android:id="@+id/searchEditTxt"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:background="#ECECEC"
        android:hint="어떤 비밀번호를 찾으시나요?"
        android:drawableStart="@drawable/search"
        android:layout_marginTop="16dp"
        android:layout_marginHorizontal="8dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

    <FrameLayout
        android:id="@+id/mainFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/searchEditTxt"
        app:layout_constraintBottom_toTopOf="@id/bottomNavigationView"/>

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottomNavigationView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:menu="@menu/bottomnavigationview"/>
</androidx.constraintlayout.widget.ConstraintLayout>

위 코드에서 FrameLayout이 Fragment를 담을 View이다.

하지만 찾아보면 fragment 태크가 있음에도 FrameLayout을 사용한 것을 볼 수 있다!

왜냐하면 fragment 태그를 사용하면 android:name 속성을 사용하여 사용할 Fragment를 최초 지정해주어야한다.

만약 최초 fragment를 코드를 사용하여 지정하고 싶다면 FrameLayout 같은 ViewGroup을 사용해야한다.

 

2. Fragment를 상속 받는 클래스로 Activity처럼 구현

class AllFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_all, container, false)
    }
}

더 많은 생명주기가 있지만 간단한 예제이기 때문에 onCreateView만 선언하였다. 위는 Fragment를 상속 받은 클래스이다.

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

    <TextView
        android:text="all"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:gravity="center"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

fragment에서 사용할 layout.xml도 함께 선언해주자!

위와 동일하게 다른 Fragment를 2개 더 선언해주었다.

 

3. Activity에서 FragmentManager를 통해 원하는 Fragment를 1에서 선언한 View에 등록

class MainActivity : AppCompatActivity() {

    private var fragmentManager = supportFragmentManager
    private var allFragment = AllFragment()
    private var categoryFragment = CategoryFragment()
    private var settingFragment = SettingFragment()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var transaction = fragmentManager.beginTransaction()
        transaction.replace(R.id.mainFragment, allFragment).commit()

        bottomNavigationView.setOnNavigationItemSelectedListener {
            var newTransaction = fragmentManager.beginTransaction()
            when(it.itemId){
                R.id.allItem -> newTransaction.replace(R.id.mainFragment, allFragment).commit()
                R.id.categoryItem -> newTransaction.replace(R.id.mainFragment, categoryFragment).commit()
                else -> newTransaction.replace(R.id.mainFragment, settingFragment).commit()
            }
            return@setOnNavigationItemSelectedListener true
        }
    }

}

supportFragmentManager로 FragmentManager를 가져온 후 beginTransaction으로 fragment를 지정할 수 있는 현재 상태를 가져온다.

그 후 replace로 1에서 등록한 fragment태그 혹은 viewgroup을 첫번째 인자로, 두번째는 2에서 선언한 fragment클래스를 등록해주고 commit을 해준다. 이때 commit을 해주어야 반영이 된다.

Fragment에 다른 Fragment를 등록하고 싶을 때에도 replace로 원하는 fragment를 등록 후 commit 해주면된다.

* fragment 변경시에 이전에 사용했던 beginTransaction 객체가 아닌 새로 선언하여 갱신해준 후 사용해야한다. 그렇지 않으면 이미 commit했다면서 에러가 발생한다.

 

-끝-

'Android > 이것저것' 카테고리의 다른 글

[Android] Cleartext HTTP ~ bot permitted Error  (0) 2020.07.19
FloatingActionButton  (0) 2020.07.11
NotificationListenerService  (0) 2020.05.10
스플래쉬  (0) 2020.05.10
그라데이션 만들기  (0) 2020.05.10

댓글