사용 용도
✔ 변화하는 여러 화면을 표현할 때, 액티비티를 계속 띄우는 것 보다는 같은 크기의 화면이라면 프래그먼트로 전환시키는 것이 더 효율적인 구조 설계이다.
✔ 변하지 않는 한 화면을 layout에서 프래그먼트로 표현할 때는 <fragment>를 사용하지만, 이벤트에 의해서 같은 크기의 layout에 여러 화면이 전환되는 경우에는 <FrameLayout>에 여러 프래그먼트를 표현하는 방법이 효율적이다.
액티비티에서 프래그먼트 전환하기
액티비티에서 프래그먼트로 값 전달하면서 프래그먼트 전환하기
✔ 프래그먼트는 액티비티에서 관리해주기 때문에 프래그먼트 전환에 관련한 코드는 액티비티에 구현하는 것이 효율적이다.
✔ activity_main.xml 내에 있는 <FrameLayout>에 FirstFragment를 띄워주기 위한 코드이다.
✔ 또한, 액티비티에서 프래그먼트로 데이터를 전송하기 위한 기능도 추가되어 있다.
MainActivity
fun moveToFirst() {
// 1. 사용할 프래그먼트 생성
var firstFragment = FirstFragment()
// 2. 액티비티에서 프래그먼트로 전달할 데이터 추가
var bundle = Bundle()
bundle.putString("key_1", "First Fragment")
bundle.putInt("key_2", 20210910)
firstFragment.arguments = bundle
// 3. 트랜잭션 생성
val transaction = supportFragmentManager.beginTransaction()
// 4. 트랜잭션을 통해 프래그먼트 삽입
transaction.add(R.id.frameLayout, firstFragment)
transaction.commit()
}
액티비티에서 보낸 값을 프래그먼트에서 받으면서 다른 프래그먼트로 전환하기
FirstFragment
class FirstFragment: Fragment() {
lateinit var binding: FragmentFirstBinding
lateinit var mainActivity: MainActivity
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentFirsttBinding.inflate(inflater, container, false)
mainActivity = context as MainActivity
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
with (binding) {
arguments?.apply {
Log.d("Ryong", getString("key_1"))
Log.d("Ryong", "${getInt("key_2")}")
}
// FirstFragment의 버튼을 누르면 SecondFragment로 이동
btnNext.setOnClickListener {
mainActivity.moveToSecond()
}
}
}
}
MainActivity
fun moveToSecond() {
val secondFragment = SecondFragment()
val transaction = supportFragmentManager.beginTransaction()
transaction.add(R.id.frameLayout, secondFragment)
transaction.addToBackStack("second")
transaction.commit()
}
◽ addToBackStack을 사용하면 트랜잭션을 마치 하나의 액티비티처럼 백스택에 담아둘 수 있다. 이를 설정하지 않을 경우, 뒤로가기를 하면 액티비티가 종료되고, 설정해 줄 경우, 트랜잭션을 액티비티처럼 제거할 수 있게 된다.
프래그먼트에서 프래그먼트로 값 전달하기
프래그먼트에서 다른 프래그먼트로 직접 값을 전달하기 위해서는 부가적인 설정이 필요하다.
https://developer.android.com/jetpack/androidx/releases/fragment#kts
SenderFragment
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnYes.setOnClickListener {
val bundle = bundleOf("valueKey" to "Yes")
setFragmentResult("request", bundle)
}
binding.btnNo.setOnClickListener {
val bundle = bundleOf("valueKey" to "No")
setFragmentResult("request", bundle)
}
}
◽ 앞에서는 Bundle() 생성자를 통해서 번들을 사용하여 bundle에 putString으로 값을 넣어주는 방법을 사용했으나, bundleOf("키" to "값") 메서드를 사용하면 더 간단하게 번들을 만들 수 있다.
◽ request는 프래그먼트 요청 전체에 대한 키이고, valueKey는 요청에 담겨 있는 여러 개의 값 중에 하나의 값을 가리키는 키이다.
ReceiverFragment
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setFragmentResultListener("request") { key, bundle ->
bundle.getString("valueKey")?.let {
binding.textView.setText(it)
}
}
}
◽ 값을 보내는 프래그먼트 측에서 "request"라는 키로 값을 보내면 위의 리스너 안의 코드가 실행된다.
'Android > Code' 카테고리의 다른 글
[Project] [Android] [Kotlin] Log Window (0) | 2021.10.18 |
---|---|
[Android] [Kotlin] Google Map (0) | 2021.09.24 |
[Android] [Kotlin] EditText 자동 포커싱 및 키보드 (0) | 2021.09.23 |
[Android] [Kotlin] Dialog로 액티비티 띄우기 (0) | 2021.09.15 |
[Android] [Kotlin] chooser Intent (카메라, 갤러리) (0) | 2021.09.12 |