Android jetpack: Navigation
(1) 의존설정
https://developer.android.com/guide/navigation/navigation-getting-started
탐색 구성요소 시작하기 | Android 개발자 | Android Developers
탐색 구성요소 시작하기 이 주제는 탐색 구성요소를 설정하고 사용하는 방법을 설명합니다. 탐색 구성요소의 대략적인 개요는 탐색 개요를 참고하세요. 환경 설정참고: 탐색 구성요소는 Android
developer.android.com
url에 접속하여 사용하는 언어에 맞게 의존을 복사하여 (필자는 코틀린) build.gradle (Module)에 의존을 추가한다.
dependencies {
// 추가한 의존
// Graph를 이용한 탐색
def nav_version = "2.3.5"
implementation("androidx.navigation:navigation-fragment-ktx:$nav_version")
implementation("androidx.navigation:navigation-ui-ktx:$nav_version")
// 기존 의존
// ...
}
홈페이지에는 val nav_version = "2.3.5"로 되어 있는데, val로 의존인식이 안되는 경우 def로 변경하여 의존을 추가하자.
의존을 추가했으면 우측 상단의 synch now 버튼을 눌러 재빌드될 수 있도록 하자.
(2) navigation으로 활용할 xml파일 생성
- navigation 디렉토리 생성
res 폴더 우측클릭 -> New -> Android Resource Directory
Directory name: navigation
Resource type: navigation - nav_graph.xml 생성
만들어진 navigation폴더 -> New -> Navigation resource file
파일명: nav_graph
생성된 nav_graph.xml에서 이제 프레그먼트를 하나의 컴포넌트로 탐색 그래프안에서 관리할 수 있도록 할 것입니다. 프레그먼트간의 전환(action), 데이터 전달(arguments) 등의 기능을 관리하고 앱의 모든 탐색 경로를 시각화하여 관리를 더 편하게 할 것입니다.
(3) activity_main.xml에서 대표 Fragment를 추가하기
다시 그 홈페이지에서 XML을 복사하여 activity_main.xml에 NavHostFragment를 추가해줄 겁니다.
=> 홈페이지에선 <androidx.fragment.app.FragmentContainerView>로 되어 있지만 <fragment 로 바꿔주자 !
그렇지 않으면 "fragment container view does not have a NavController set" 오류가 발생한다
이제 mainActivity를 구성하는 FragmentContainerView 안에서 우리가 설정하는 Fragment들로 교체될 수 있고 보여지게 할 수 있습니다. (즉, Activity안에, Activity화면의 일부 또는 전체 (현재는 전체)를 FragmentContainerView에게 할당시켜주고 이 안에서 프레그먼트를 교체하고 보여지게 할 것이란 얘기)
<?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">
<!-- 여기서 설정 -->
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
(4) Fragment를 만들고 nav_graph에 컴포넌트로 등록하기, action 만들기
Fragment 만들기
1. MainActivity가 있는 디렉터리에 fragment라는 새로운 디렉터리를 만든다.
2. fragment에 마우스 우클릭 -> new -> fragment -> Fragment(blank)로 만든다.
3. frament가 생성이되면 자동으로 res->layout폴더에 .xml 파일도 생성되었을 것이다.
일단 2개를 생성해보자
nav_graph에서 fragment와 action 추가하기
1. nav_graph.xml의 Design화면에서 New Destination에서 생성한 프레그먼트를 추가한다.
=> fragment의 component코드가 자동으로 추가되었을 것이다.
2. 프레그먼트 2개 다 추가하고 첫번째 프레그먼트의 오른쪽 부분의 점 부분을 끌어서 두번째 프래그먼트의 왼쪽부분으로 연결하면 그것이 fragment의 이동을 담당하는 action이 된다.
위 사진은 fragment 2개를 추가하고 action까지 설정한 모습이다. 추가할 때 아이콘은 빨간 네모가 그려진 New Destination에서 하면 된다.
(5) Fragment 코틀린파일에서 이동설정하기
1. MainActivity에서 설정
class MainActivity : AppCompatActivity() {
lateinit var navController :NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
navController = nav_host_fragment.findNavController()
}
}
- Activity에서 navController 설정
nav_host_fragment.findNavController() => activity_main.xml에서 nav_host_fragment라는 fragment의 id에 직접 접근하여 NavController를 설정해준다.
ID에 직접 접근할 수 있었던 이유는 gradle에서 설정한 id 'kotlin-android-extensions' 덕분이다. 자세한 내용은 나중에 따로 다뤄보자.
이러한 설정을 안했다면 아래와 같은 코드로 navController에 접근하자
// val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
// val navController = navHostFragment.navController
2. Fragment에서 설정
class MainFragment : Fragment() {
lateinit var navController: NavController
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
navController = Navigation.findNavController(view)
button.setOnClickListener{
navController.navigate(R.id.action_mainFragment_to_secondFragment)
}
}
- Fragment에서 navController 설정
onViewCreated()메소드에서 전달된 매개변수 view를 이용하여
navController = Navigation.findNavContrlloer(view) 코드로 navController를 전달받는다. - button이라는 Id를 가진 버튼 객체를 하나 만들고, 그 버튼을 누르면(setOnClickListener) 2번째 프래그먼트로 넘어가도록 만들었던 action을 설정했다.
.navigate() 메소드를 이용하여 action을 실행해준다.
시연영상
화면1에서 버튼을 누르면 화면2로 가고, 화면2에서 버튼을 누르면 화면1로 간다.
궁금증
화면1(MainFragment)에서 화면2(Second Fragment)로 데이터를 전달하고 싶으면 어떻게 할까 ??
화면2에서 버튼을 누르면 뒤로 돌아가는데, 뒤로 가기 설정은 어떻게 할까??
참고문헌
탐색 구성요소 시작하기: https://developer.android.com/guide/navigation/navigation-getting-started
코틀린 3강으로 끝내기 - 3편 심리테스트 앱 만들기: https://www.youtube.com/watch?v=M1e2tLnzVPo&t=353s