안녕하세요.
이번 포스팅에서는 기본적인 안드로이드 네비게이션을 구현해 보겠습니다.
dependency를 추가합니다.
build.gradle(project)
buildscript {
ext {
nav_version = '2.5.3'
}
dependencies {
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
}
}
build.gradle(:app)
plugins {
...
id 'androidx.navigation.safeargs.kotlin'
...
}
dependencies {
...
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
...
}
프래그먼트 3개를 생성하겠습니다(figure1 참조).
그리고 각각의 프래그먼트를 모두 아래와 같이 만들어 줍니다.
AFragment.kt
class AFragment : Fragment() {
private var _binding: FragmentABinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentABinding.inflate(layoutInflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
BFragment.kt
class BFragment : Fragment() {
private var _binding: FragmentBBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentBBinding.inflate(layoutInflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
CFragment.kt
class CFragment : Fragment() {
private var _binding: FragmentCBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentCBinding.inflate(layoutInflater, container, false)
return binding.root }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
위에서 사용된 view binding은 아래 포스트를 참고해 주세요.
https://it-of-fortune.tistory.com/21
xml은 각각 아래와 같이 구성해 줍니다.
fragment_a.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".fragments.AFragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A 프래그먼트"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<Button
android:id="@+id/move_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="다음"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="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:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".fragments.BFragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B 프래그먼트"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<Button
android:id="@+id/move_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="다음"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
fragment_c.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".fragments.CFragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="C 프래그먼트"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
다음으로, res > navigation directory를 생성한 뒤 Navigation Resource File을 생성해 줍니다(figure2 참조).
저는 nav_main.xml 이름으로 생성했습니다.
생성을 마친 후 Design 탭에서 네비게이션에 사용할 프래그먼트를 추가합니다(figure3-1, 3-2 참조).
위 과정이 끝나면 추가된 fragment들의 preview가 보이게 됩니다(figure4 참조).
이제 navigation direction을 설정해 주겠습니다.
마우스 드래그로 간편하게 설정 가능합니다(figure5 참조).
위 세팅으로 A -> B, B -> C 이동 구현이 가능하게 되었습니다.
참고로 code부분은 자동으로 추가 / 수정됩니다.
위의 과정을 마치면 아래 코드가 자동으로 생성됩니다.
지금은 code 부분을 건드릴 필요는 없습니다.
nav_main.xml(code tab)
<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/nav_main"
app:startDestination="@id/AFragment">
<fragment
android:id="@+id/AFragment"
android:name="com.contents.laboratory.fragments.AFragment"
android:label="fragment_a"
tools:layout="@layout/fragment_a" >
<action
android:id="@+id/action_AFragment_to_BFragment"
app:destination="@id/BFragment" />
</fragment>
<fragment
android:id="@+id/BFragment"
android:name="com.contents.laboratory.fragments.BFragment"
android:label="fragment_b"
tools:layout="@layout/fragment_b" >
<action
android:id="@+id/action_BFragment_to_CFragment"
app:destination="@id/CFragment" />
</fragment>
<fragment
android:id="@+id/CFragment"
android:name="com.contents.laboratory.fragments.CFragment"
android:label="fragment_c"
tools:layout="@layout/fragment_c" />
</navigation>
이제 MainActivity에 navigation container를 추가하겠습니다.
아래와 같이 작성해 줍니다.
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">
<androidx.fragment.app.FragmentContainerView
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_main" />
</androidx.constraintlayout.widget.ConstraintLayout>
이제 프래그먼트의 이동을 구현하겠습니다.
AFragment.kt
class AFragment : Fragment() {
private var _binding: FragmentABinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentABinding.inflate(layoutInflater, container, false)
binding.moveNext.setOnClickListener {
navigateToBFragment()
}
return binding.root
}
private fun navigateToBFragment() {
this@AFragment.findNavController().navigate(
AFragmentDirections.actionAFragmentToBFragment()
)
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
BFragment.kt
class BFragment : Fragment() {
private var _binding: FragmentBBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentBBinding.inflate(layoutInflater, container, false)
binding.moveNext.setOnClickListener {
navigateToCFragment()
}
return binding.root
}
private fun navigateToCFragment() {
this@BFragment.findNavController().navigate(
BFragmentDirections.actionBFragmentToCFragment()
)
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
CFragment는 바뀌는 것이 없습니다.
아래의 코드가 이동을 담당하는 부분입니다.
this@BFragment.findNavController().navigate(
BFragmentDirections.actionBFragmentToCFragment()
)
에뮬레이터에서 실행해 보겠습니다.
정상적으로 동작합니다.
또한, back key 클릭 시 이전의 프래그먼트로 이동하는 것까지 확인 가능합니다.
이상 포스팅을 마치겠습니다.
감사합니다.
'Android Application > 기초 사용법' 카테고리의 다른 글
안드로이드 힐트(hilt) 의존성 주입 사용 (1) | 2023.03.31 |
---|---|
안드로이드 리사이클러뷰(recyclerview) 사용(with DiffUtil) (0) | 2023.03.30 |
안드로이드 데이터바인딩(dataBinding) 사용 (0) | 2023.03.29 |
안드로이드 뷰모델(ViewModel) 사용하기(with LiveData) (0) | 2023.03.28 |
안드로이드 ViewBinding(뷰바인딩) 구현 (0) | 2023.03.26 |
댓글