Android Kotlin : Activity에 Fragmeent 추가, 변경, 삭제 및 고려사항 정리
Activity의 FrameLayout에 Fragment를 추가, 대체, 삭제 하는 방법과 기타 유의점
등을 정리합니다.
Fragment는?
Fragment는 Activity 내에서 UI의 일부분을 나타내는 요소입니다. 즉, 아래와 같이 한 화면에 여러개의 화면을 보여주기위해 많이 사용됩니다. 물론 여러개의 Activity를 사용해서 여러 화면을 보여 줄 수 있지만, 안드로이드 가이드에서 Activity는 앱 UI의 탐색 네비게이션(구역)과 같은 전역적인 요소를 사용하고, 탐색 네비게이션 선택에 따라 컨텐츠가 보이는 부분은 프래그먼트로 사용 할 것을 권장합니다.
※ 화면이 하나만 필요할 때는 프래그먼트를 사용하지 않습니다.
Fragment 사용하기
키워드
- Fragment
- Activity 내에서 UI의 일부분을 나타내는 요소 입니다. Activity의 부분 집합이 될 수 있습니다.
- Fragment Manager
- Activity 의 FrameLayout에 Fragment를 등록, 교체, 삭제 등의 기능을 포함한 클래스입니다.
- Fragment 추가, 교체, 삭제 등의 변경 사항은 FragmentTransaction 이라는 객체에서 등록 후
Commit()으로 실행합니다. - FragmentTrasaction 객체는
supportFragmentManager.beginTransaction()함수의 반환값 입니다.
- FrameLayout
- Activity 내에서 화면 전환이 필요한 구역의 컨테이너로 사용됩니다.
앱 따라하기
개요
아래와 같이 실행되는 테스트 앱 제작 방법입니다.
- SWITCH 버튼을 누르면 FrameLayout에 FragmentA 와 FragmentB 가 교차 됩니다.
- REMOVE 버튼을 누르면 FrameLayout의 Fragment 연결이 제거 됩니다.
프로젝트 생성
프로젝트 이름과 언어는 아래와 같이 설정합니다.
- 프로젝트명 : Fragment
- 언어 : Kotlin
ViewBinding 환경 설정
build.gradle(Module: ManagingFolder) 파일에 아래의 ViewBinding 설정 코드를 추가합니다.
android {
...
viewBinding {
enabled = true
}
}
코드 추가가 완료되면 아래와 같이 Sync Now 클릭해서 Gradle 변경 사항을 적용합니다.
※ ViewBinding 은 Layout 에 있는 View의 Id를 코틀린 코드에서 직접 사용 할 수 있게 해주는 도구입니다. View Binding과 관련된 설명은 아래의 링크를 참조해주세요.
Fragment 추가하기
아래와 같이 2개의 Fragment를 추가 합니다. 추가하는 Fragment의 이름은 FragmentA, FragmentB로 추가하였습니다. Fragment가 정상적으로 추가되면 아래 우측 그림과 같이 2개의 코틀린 파일과 2개의 레이아웃 파일이 추가됩니다.
UI만들기
3개의 레이아웃 코드를 아래와 같이 작성합니다. 코드 순서는 activity_main.xml, fragment_a.xml, fragment_b.xml 입니다.
activity_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"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="12dp"
app:layout_constraintBottom_toTopOf="@+id/btnSwitch"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnSwitch"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="12dp"
android:text="Switch"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btnRemove"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btnRemove"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="12dp"
android:text="Remove"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/btnSwitch" />
</androidx.constraintlayout.widget.ConstraintLayout>
fragment_a.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=".FragmentA">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is FragmentA"
android:background="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
fragment_b.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=".FragmentA">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is FragmentB"
android:background="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
코틀린 코드 작성1 : Fragment 사용하기
FrameLayout에 FragmentA를 넣기 위한 MainActivity.kt 최소한의 코드는 아래와 같습니다.
package com.blacklog.fragment
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.blacklog.fragment.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
lateinit var binding : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.btnSwitch.setOnClickListener {
setFragment()
}
}
private fun setFragment() {
val transaction = supportFragmentManager.beginTransaction()
.add(R.id.frameLayout, FragmentA())
transaction.commit()
}
}
위 코드를 작성하고 Switch 버튼을 누르면 FrameLayout에 FragmentA가 나타납니다.
코틀린 코드 작성2 : 최종 코드
Fragment 처리를 위해 생성된 FragmentTransaction 객체에는 위 코드에서 사용한 add() 메서드 이외에 replace() 메서드 및 remove() 메서드를 사용할 수 있습니다. 이 메서드들을 사용하여 작성한 MainActivity의 최종 코드는 아래와 같습니다.
package com.blacklog.fragment
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.blacklog.fragment.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
lateinit var binding : ActivityMainBinding
/*
* when flag is 0 : 처음
* when flag is 1 : FragmentA
* when flag is 2 : FragmentB
* */
var flag = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.btnSwitch.setOnClickListener {
switchFragment()
}
binding.btnRemove.setOnClickListener {
removeFragment()
}
}
private fun switchFragment() {
val transaction = supportFragmentManager.beginTransaction()
when(flag){
0 -> {
transaction.add(R.id.frameLayout, FragmentA())
flag = 1
}
1 -> {
transaction.replace(R.id.frameLayout, FragmentB())
flag = 2
}
2 -> {
transaction.replace(R.id.frameLayout, FragmentA())
flag = 1
}
}
transaction.addToBackStack(null)
transaction.commit()
}
private fun removeFragment() {
val transaction = supportFragmentManager.beginTransaction()
val frameLayout = supportFragmentManager.findFragmentById(R.id.frameLayout)
transaction.remove(frameLayout!!)
transaction.commit()
}
}
위 코드를 작성하면 아래와 같이 Switch버튼을 누르면 FrameLayout에 표시되는 Fragment가 A, B 서로 전환이 되고, Remove 버튼을 누르면 FrameLayout에 연결된 Fragment가 삭제 됩니다.
유의점
Fragment 배경색 지정
Fragment의 배경색은 투명으로 설정되어 있습니다. 위의 fragment_a.xml, fagment_b.xml 코드를 보면 android:background="@color/white" 와 같이 배경색 코드가 삽입 되어 있는 것을 볼 수 있습니다. 배경색이 지정되어 있지 않으면 Activity 화면이 중첩되어 표시됩니다.
백스택 설정
Fragment는 기본적으로 백 스텍에 저장되지 않습니다. 백 스택에 저장하고 싶은 경우 FragmentTransaction 에addToBackStack(null) 코드를 추가하여 뒤로가기 버튼 클릭시 이전 화면을 볼 수 있도록 설정이 가능합니다. 아래 그림은 addToBackStack(null) 코드 유무에 따른 동작 차이 입니다.
끝까지 읽어 주셔서 감사합니다.^^
'Programming > Android App(Kotlin)' 카테고리의 다른 글
안드로이드 코틀린 : Fragment에서 Fragment 생성 및 데이터 보내기 (0) | 2021.03.30 |
---|---|
안드로이드 코틀린 : Activity에서 Fragment에 데이터 보내기 (0) | 2021.03.25 |
안드로이드 코틀린 : Intent 명시적 호출 방법 정리 (0) | 2021.03.25 |
안드로이드 코틀린 : 앱 디렉토리 폴더 생성, 탐색, 삭제 (0) | 2021.03.24 |
안드로이드 코틀린 : AlertDialog 기본, 목록, 라디오 버튼, 체크 박스, EditText 입력 창 (0) | 2021.03.23 |