안드로이드의 back button기능을 내 맘대로 구현해 봅시다.
class MainActivity : AppCompatActivity() {
private lateinit var callback: OnBackPressedCallback
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
onBackPressed()
}
//activity에서는 이 함수를 override하고, 원하는 백버튼 이벤트를 구현하면 된다.
override fun onBackPressed() {
// 주석 처리된 부분 >> 원래 뒤로가기 버튼 기능이다.
//지금은 주석처리 해놨으니까 뒤로가기가 안됨. 뒤로가기를 눌렀을 때 토스트가 나오도록 해놨음.
// super.onBackPressed()
Toast.makeText(this@MainActivity,"onBackPressed",Toast.LENGTH_SHORT).show()}
//fragment
class MyFragment : Fragment() {
private lateinit var callback: OnBackPressedCallback
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_my, container, false)
}
override fun onAttach(context: Context) {
super.onAttach(context)
callback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
//원하는 뒤로가기 기능을 구현해 줍니다.
Toast.makeText(requireActivity(), "onBackPressed", Toast.LENGTH_SHORT).show()
}
}
//프래그먼트가 속한 액티비티에 onBackPressedDispatcher을 설정해줍니다.
requireActivity().onBackPressedDispatcher.addCallback(this, callback)
}
override fun onDetach() {
super.onDetach()
callback.remove()
}
}
class MainActivity : AppCompatActivity() {
private lateinit var callback: OnBackPressedCallback
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.fragment_container, MyFragment()).commit()
}
//fragment에 OnBackPressedCallback를 구현 한 다음 액티비티에서 onBackPressed()를 override해줘야 프래그먼트에서 설정한 백버튼 이벤트가 실행됩니다.
override fun onBackPressed() {
super.onBackPressed()
}
}
//보통 baseFragment를 만들어놓고, 다른 프래그먼트에 baseFragment를 상속받아 사용하는 경우가 많습니다.
open class MyFragment : Fragment() {
private lateinit var callback: OnBackPressedCallback
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_my, container, false)
}
override fun onAttach(context: Context) {
super.onAttach(context)
callback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
when(this@MyFragment){
//프래그먼트마다 다른 백버튼 이벤트를 설정합니다.
is Fragment1 -> {}
is Fragment2 -> {}
else -> {
//ex)여러 프래그먼트를 viewPager로 붙여서 viewPager 내에서 백 버튼 구현하고 싶은 경우
// viewPager로 붙인 프래그먼트들 사이에서는 기본적으로 백버튼이 작동되지 않는다
//f1 > (f2, f3, f4 이 하나의 뷰페이저라면), f3 > f2 이 되는게 아니라
//f3 > f1로 이동해 버린다.
//그래서 parentFragment가 뷰페이저 프래그먼트이면(여기서는 MyViewPager), 뷰페이저에서 구현한 백버튼 함수(보통 뷰페이저 첫 페이지면 뒷 프래그먼트로 , 첫페이지가 아니면 뷰페이저 내의 뒷페이지로 가라고 구현하겠지유)를 실행하라고 적어준다.
when(this@MyFragment.parentFragment){
is MyViewPager -> {(this@MyFragment.parentFragment as MyViewPager).back()}
}
}
}
}
}
//프래그먼트가 속한 액티비티에 onBackPressedDispatcher을 설정해줍니다.
requireActivity().onBackPressedDispatcher.addCallback(this, callback)
}
override fun onDetach() {
super.onDetach()
callback.remove()
}
}
//이런 식으로 baseFragment를 상속해서 사용하는 경우가 많음.
class Fragment1 : MyFragment() {
private lateinit var callback: OnBackPressedCallback
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_my, container, false)
}
}
class MyViewPager : MyFragment() {
private lateinit var callback: OnBackPressedCallback
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_my, container, false)
}
fun back() {
//뷰페이저 내 첫번째 페이지면
if (isFirstPage()) //뒤로가기구현
//뷰페이저 내 첫번째 페이지가 아니면 뷰페이저 내 에서 뒤로가기
else binding.viewPager.currentItem = binding.viewPager.currentItem.minus(1)
}
fun isFirstPage() = binding.viewPager.currentItem == 0
}