📝 스파르타코딩클럽의 '내일배움캠프' 지급 강좌를 정리한 글 입니다.
액티비티 위에서 동작하는 모듈화된 사용자 인터페이스
앱을 개발하면서 액티비티가 점점 늘어날 경우에 그것들을 모두 Intent로 연결하는 것은 너무 복잡하다.
그래서 Fragment
를 사용하게 된다.
즉, 하나의 액티비티 안에서 특정 영역
만 프래그먼트로 표시하는 것이다.
Activity
는 시스템의 액티비티 매니저에서 인텐트를 해석해 액티비티 간 데이터를 전달
Fragment
는 액티비티의 프래그먼트 매니저에서 메소드로 프래그먼트 간 데이터를 전달
Fragment를 사용하면 Activity를 적게 만들 수 있다.
Activity의 복잡도를 줄일 수 있다.
Fragment를 사용하면 재사용할 수 있는 레이아웃을 분리해서 관리가 가능하다.
Fragment를 사용하면 최소 1개의 Activity 안에서 Fragment 공간에 View만 집어넣으면 여러 Activity 를 만들지 않아도 여러 화면을 보여줄 수 있다.
액티비티의 화면 전환보다 프래그먼트로 화면 일부만 전환하는 것이 자원이 적게 든다.
❗ 결국 퍼포먼스 때문에 사용한다는 의미
액티비티와 비슷하게 하나의 KT 파일과 하나의 XML 레이아웃을 정의한다.
그리고 액티비티 레이아웃 파일에 추가한다.
class FirstFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_first, container, false)
}
Fragment를 상속 받는다.
반드시 onCreateView() 콜백 메소드를 구현한다.
inflate로 사용할 레이아웃 XML 파일 지정한다.
/res/layout 폴더 하위에 레이아웃.xml 생성
2가지 방법이 있다.
액티비티 XML 파일 안에서 정적으로 추가
KT 소스 코드에서 동적으로 추가
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<fragment
android:name="com.skmns.fragmentbasic.FirstFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fragment" />
</LinearLayout>
android:name
으로 사용할 프래그먼트 지정❗ 프래그먼트는 액티비티가 재시작되는 경우 프래그먼트를 복구하기 위해 시스템이 사용할 수 있는 고유한 식별자가 필요하다. 프래그먼트에 ID를 지정하는 방법은 3가지가 있다.
android:id 속성으로 지정
android:tag 속성으로 지정
만약 아무것도 지정하지 않는다면 시스템은 컨테이너 뷰의 ID를 사용한다.
Fragment Manager
를 사용한다.supportFragmentManager.commit {
replace(R.id.frameLayout, frag)
setReorderingAllowed(true)
addToBackStack("")
}
supportFragmentManager
사용자 상호작용에 응답해 Fragment를 추가하거나 삭제하는등 작업을 할 수 있게 해주는 매니저
replace
어느 프레임 레이아웃에 띄울것이냐, 어떤 프래그먼트냐
setReorderingAllowed
애니메이션과 전환이 올바르게 작동하도록 트랜잭션과 관련된 프래그먼트의 상태 변경을 최적화
addToBackStack
뒤로가기 버튼 클릭시 다음 액션 (이전 fragment로 가거나 앱이 종료되거나)
아래와 같은 화면을 구성해보자.
<?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="#F19B9B">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="프래그먼트 1"
android:textAllCaps="false"
android:textSize="40sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?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:background="#C785D3"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="프래그먼트 2"
android:textAllCaps="false"
android:textSize="40sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<?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_marginStart="10dp"
android:layout_marginEnd="10dp"
app:layout_constraintBottom_toTopOf="@+id/fragment1_btn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</FrameLayout>
<Button
android:id="@+id/fragment1_btn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="Frag1"
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/fragment2_btn"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/frameLayout" />
<Button
android:id="@+id/fragment2_btn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="Frag2"
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/fragment1_btn"
app:layout_constraintTop_toBottomOf="@+id/frameLayout" />
</androidx.constraintlayout.widget.ConstraintLayout>
Fragment 를 동적으로 추가 해보자.
implementation("androidx.fragment:fragment-ktx:1.5.5")
KT 파일 작성
package com.example.test
class MainActivity : AppCompatActivity() {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.apply {
fragment1Btn.setOnClickListener {
setFragment(FirstFragment())
}
fragment2Btn.setOnClickListener {
setFragment(SecondFragment())
}
}
setFragment(FirstFragment())
}
private fun setFragment(frag: Fragment) {
supportFragmentManager.commit {
replace(R.id.frameLayout, frag)
setReorderingAllowed(true)
addToBackStack("")
}
}
}