Unit 3: Navigation (4)

quokka·2021년 11월 12일
0

Android Basics in Kotlin

목록 보기
13/25
post-thumbnail

탐색 그래프 NavGraph

탐색 그래프는 fragment 간 탐색을 구현하는 데 도움이 되는 시각적 편집기다. 각 화면의 관계를 XML 파일로 나타낸다.

MainActivity에서 FragmentContainerView 사용하도록 수정해보자.

탐색 그래프를 사용하기 위해 gradle 설정은 이 페이지를 참고

Android Studio Bumblebee나 Chipmunk 버전에서는 build.gradle와 settings.gradle 구조가 코드랩 강의와 좀 다르다.

build.gradle (project 수준)

여기에 nav_version과 safe args 플러그인에 대한 buildscript를 작성한다. SafeArgs는 프래그먼트 간 데이터를 전달할 때 유형 안전성을 지원한다.
buildscript는 plugins 보다 위에 작성되어야 한다.

buildscript {
    ext{
        nav_version = "2.4.1"
    }
    dependencies {
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
    }
}
plugins {
	...
    id 'androidx.navigation.safeargs.kotlin' version '2.4.1' apply(false)
}

build.gradle (module 수준)

fragment와 navigation을 사용하기 위한 plugins와 dependecies를 추가한다.

plugins {
    id 'androidx.navigation.safeargs.kotlin'
}
dependencies {
    implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
    implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
}

주의
위에 작성된 dependency나 plugin의 버전이 서로 다르면 빌드에러가 발생할 수 있다.
버전이 동일한지 확인하자.

FragmentContainerView

MainActivity

  1. FragmentContainterView 설정
    RecyclerViewFragmentContainerView로 변경한다.

  2. NavHostFragment 설정
    ID 속성 아래에 name 속성을 추가하고 androidx.navigation.fragment.NavHostFragment로 설정한다. 이 속성의 특정 프래그먼트를 지정할 수 있지만 NavHostFragment로 설정하면 FragmentContainerView가 프래그먼트 간에 탐색을 할 수 있다.

  3. navHost 설정
    app:navHost라는 속성을 추가하고 "true"로 설정한다. 이렇게하면 Fragment Container가 탐색 계층 구조와 상호작용할 수 있다.

  4. nav_graph 생성
    app:navGraph="@navigation/nav_graph" 작성하고, Android Resource File을 추가해 Navigation 유형의 nav_graph.xml을 생성한다.

<!-- activity_main.xml -->

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

</FrameLayout>
  1. action 연결
    New Resource File -> Navigation 타입으로 nav_graph.xml 생성하면 시각적 편집기가 생성된다. 여기서 새로 만들기 버튼을 눌러 각 fragment 대상을 만들고 탐색 작업을 나타내도록 화살표를 이어준다.

  2. 전달할 Arguments 추가
    인텐트에서 선택한 알파벳을 전달했었다. 여기서도 마찬가지로 wordListFragment에 전달할 Arguments를 만든다. 오른쪽에 Arguments + 를 선택해 String 타입 letter를 생성할 수 있다.

  3. 시작 대상 설정
    FragmentContainerView에 Assign start destination

LetterAdapter

  1. setOnClickListener에 탐색 작업에 대한 내용을 추가한다.
    기존에 intent를 만들어 activity를 연결하는 코드를 제거하고, 다음 코드를 추가한다.
 holder.button.setOnClickListener {
     val action = LetterListFragmentDirections
         .actionLetterListFragmentToWordListFragment(letter = holder.button.text.toString())
     holder.view.findNavController().navigate(action)
 }

MainActivity

  1. RecyclerView가 아니라 NavController를 사용해야 한다.

  2. onCreate()를 수정하고 onSupportNavigateUp() 메서드를 구현한다.
    xml에서 작성한 FragmentContainerView(nav_host_fragment)를 가져와서 navController에 할당한다.
    setupActionBarWithNavController()로 앱 바를 표시한다.
    마지막으로 onSupportNavigationUp()은 뒤로가기 버튼 처리에 사용된다. 참고로 navigationUp()은 실패할 수 있으므로 성공 여부에 따라 boolean을 반환한다. 즉 navigationUp()이 false인 경우에만 super.onSupportNavigateUp()이 호출된다.

class MainActivity : AppCompatActivity() {

    private lateinit var navController: NavController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val navHostFragment = supportFragmentManager
            .findFragmentById(R.id.nav_host_fragment) as NavHostFragment
        navController = navHostFragment.navController

        setupActionBarWithNavController(navController)

    }
    override fun onSupportNavigateUp(): Boolean {
        return navController.navigateUp() || super.onSupportNavigateUp()
    }
    
}

WordListFragment

  1. activity?.intent를 참조해서 letter extra에 액세스 했던 방식을 수정한다. letterIdlateinit으로 만들고, onCreate()에서 인수를 가져오는 코드를 작성한다.

  2. onViewCreated()의 activity?.intent?.extras?.getString(LETTER).toString()을 letterId로 바꾼다.

앱 바 설정

앱 바에 표시되는 글자는 nav_graph.xml에서 label 속성에서 설정할 수 있다.

strings.xmlwordListFragment의 라벨이 될 텍스트를 추가하고,

<string name="word_list_fragment_label">Words That Start With {letter}</string>

nav_graph.xml에서 label 속성을 수정한다.

이제 인텐트 없이 하나의 activity에서 두 화면 간 이동이 가능하다!

navigation에 대해 좀 더 알아보자.

Basic Activity 템플릿을 생성하면 버튼으로 fragment 두 개가 왔다갔다하는 어플이 만들어진다.

nav_graph.xml을 살펴보자.

  • 두 fragments(=destinations)가 어떻게 연결되어 있는지 확인할 수 있다.
  • 오른쪽에서는 각 fragment의 속성을 확인할 수 있다.
  • 화살표는 action을 의미한다. actions는 탐색을 정의하고, 목적지간 전달되는 인수들을 정의한다.

Navigation Drawer Activity 템플릿을 생성한다.
계층 구조를 확인하려면 tools > Layout Inspector를 연다.

NavHostFragment: Container for destinations

NavController: Conduct navigation 실제 탐색 작업을 하는 역할

NavigationView: Menu for Drawerlayout. destination들을 보여주는 네비게이션 바인데 탐색 구성요소는 아님. 탐색 구성요소의 항목들과 상호작용하는 것..

NavigationUI: Updates content outside NavHostFragment. NavigationView나 BottomNavBar처럼 NavHostFragment의 바깥에 있지만 NavHostFragment의 변화에 따라 업데이트 되어야 하는 것들 업데이트하는 역할

0개의 댓글