본문 바로가기
안드로이드

[android-1team] unit 04. Navigation

by cyun-404 2021. 1. 23.

이번 강의에서는 조각을 만들고, 탐색 경로를 정의하고, 외부 활동을 시작합니다. 안드로이드 개발 관련 사소한 질문에 답하고, 이기면 결과를 공유할 수 있는 게임인 안드로이드 트리비아 앱을 완성합니다.

​03.1 Create a fragment

- https://github.com/google-developer-training/android-kotlin-fundamentals-starter-apps

 

google-developer-training/android-kotlin-fundamentals-starter-apps

android-kotlin-fundamentals-starter-apps. Contribute to google-developer-training/android-kotlin-fundamentals-starter-apps development by creating an account on GitHub.

github.com

- 깃허브에서 AndroidTrivia-Starter를 다운받아서 코드 작성을 진행합니다.

 

Add a fragment

- fragment는 활동의 모듈식 섹션

- fragment는 자체 라이프사이클을 가지며 자체 입력 이벤트를 수신

- <fragment> 태그를 사용하여 XML 레이아웃 파일에서 조각에 대한 레이아웃을 정의

- onCreateView()에서 fragment 레이아웃을 올림

- 활동이 실행되는 동안 fragment를 추가하거나 제거

 

File > New > Fragment > Fragment (Blank)

- Fragment's lifecycle 동안 호출되는 방법중 하나인 onCreateView()

TitleFragment.kt에 아래 코드를 추가해 보기를 확장(inflate)하는 DataBindingUtil.inflate() 호출해 인수 전달

val binding = DataBindingUtil.inflate<FragmentTitleBinding>(inflater,
                R.layout.fragment_title,container,false)

03.2 Define navigation paths

navigation 종속성 추가

- Navigation component : 앱의 화면 간에 전달되는 복잡한 탐색, 전환 애니메이션, 심층 링크 및 컴파일 시간 확인 인수를 관리할 수 있는 라이브러리

- 탐색 라이브러리를 사용하려면 네비게이션 종속성을 Gradle 파일에 추가 (navigationVersion에 대한 변수 추가)

- build.gradle(:app)navigation-fragment-ktx , navigation-ui-ktx종속성 추가

implementation "androidx.navigation:navigation-fragment-ktx:$navigationVersion"
    implementation "androidx.navigation:navigation-ui-ktx:$navigationVersion"

Add a navigation graph

New > Android Resource File

● Create the NavHostFragment

- navigation host fragment : 탐색 그래프의 조각에 대한 호스트 역할

- activity_main.xml에 아래 사항들을 추가해 준다.

<fragment
                android:id="@+id/myNavHostFragment"
                android:name="androidx.navigation.fragment.NavHostFragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:navGraph="@navigation/navigation"
                app:defaultNavHost="true"
                />
더보기

- ID를 myNavHostFragment로 변경

- app:navGraph 특성을 추가하여 탐색 그래프 리소스(@navigation/navigation)로 설정

 

- app:defaultNavHost = "true" 특성을 추가하여 탐색 호스트가 기본 호스트이며 시스템 뒤로 버튼을 인터셉트

 

● Add fragments to the navigation graph

- New Destination : TitleFragment, GameFragment

두 Fragment를 연결하는 화살표

- TitleFragment.kt에 setOnClickListener 추가: 바인딩 클래스를 통해 play button 액세스하는 코드 추가, 게임 fragment로 이동

 binding.playButton.setOnClickListener{view : View ->
            view.findNavController().navigate(R.id.action_titleFragment_to_gameFragment)}

- conditional navigation: 사용자가 모든 질문에 올바르게 대답하는지 여부에 따라 앱이 다른 Fragment로 이동

- else를 사용해 이기고 진 경우를 나누어 설정

● Change the Back button's destination

- 사용자가 뒤로 버튼을 누르면 앱이 백 스택의 맨 위에 있는 대상으로 이동. 기본적으로 백 스택의 맨 위는 사용자가 마지막으로 본 화면

- 게임이 끝나고 뒤로 버튼을 누르면 TitleFragment로 돌아가도록 설정

- Layout Editor의 Attributes 창에 있는 Pop To 필드를 사용하여 수행(백 스택 관리)

 

- GameWonFragment.kt에 아래의 코드를 추가해 back stack을 관리

// Add OnClick Handler for Next Match button
        binding.nextMatchButton.setOnClickListener{view: View->
            view.findNavController()
                    .navigate(R.id.action_gameWonFragment_to_gameFragment)}

 

● Add an Up button in the app bar

 ( app bar = action bar : 앱 브랜딩 및 아이덴티티를 위한 전용 공간 )

- The Up button: app bar에 위치한 뒤로가기 버튼을 사용해 이전 동작으로 돌아갈 수 도 있음

 

● Add an options menu

Add the AboutFragment to the navigation graph
Add the options-menu resource

- 속성에 id ="aboutFragment", title = "@string/about으로 설정

 

● Add an onClick handler

 

TitleFragment.kt

package com.example.android.navigation

import android.os.Bundle
import android.view.*
import androidx.fragment.app.Fragment
import androidx.databinding.DataBindingUtil
import androidx.navigation.findNavController
import androidx.navigation.ui.NavigationUI
import com.example.android.navigation.databinding.FragmentTitleBinding

private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"

class TitleFragment : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        val binding = DataBindingUtil.inflate<FragmentTitleBinding>(inflater,
                R.layout.fragment_title,container,false)
        binding.playButton.setOnClickListener{view : View ->
            view.findNavController().navigate(R.id.action_titleFragment_to_gameFragment)}
        setHasOptionsMenu(true)
        return binding.root
    }
    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        super.onCreateOptionsMenu(menu, inflater)
        inflater.inflate(R.menu.options_menu, menu)
    }
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return NavigationUI.
        onNavDestinationSelected(item,requireView().findNavController())
                || super.onOptionsItemSelected(item)
    }
}

- setHasOptionsMenu() 메서드를 호출하고 true로 전달

- 메소드에서 옵션 메뉴를 추가하고 메뉴 리소스 파일 inflate

- onOptionsItemSelected(): 메뉴 항목을 누를 때 적절한 작업을 수행

 

● Add the navigation drawer

- Material library추가

implementation "com.google.android.material:material:$version"

- ID확인

- drawer menu 생성

- Mainactivity.kt 코드에 SetupActionBarWithNavController() 메소드에 매개 변수로 Drager Layout 추가, UI.navigate Up 반환

class MainActivity : AppCompatActivity() {
    private lateinit var drawerLayout: DrawerLayout
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        @Suppress("UNUSED_VARIABLE")
        val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)

        drawerLayout = binding.drawerLayout

        val navController = this.findNavController(R.id.myNavHostFragment)

        NavigationUI.setupActionBarWithNavController(this,navController, drawerLayout)

        NavigationUI.setupWithNavController(binding.navView, navController)

    }

    override fun onSupportNavigateUp(): Boolean {
        val navController = this.findNavController(R.id.myNavHostFragment)
        return NavigationUI.navigateUp(navController, drawerLayout)
    }

}

 

03.3 Start an external Activity

Safe Args:

- 한 조각에서 다른 조각으로 데이터를 전달할 때 키 누락 또는 불일치 유형으로 인한 오류를 포착하려면 SafeArgs라는 Gradle 플러그인을 사용(apply plugin: 'androidx.navigation.safeargs' 추가)

- 앱의 각 조각에 대해 SafeArgs 플러그인은 해당 NavDirection 클래스를 생성

- NavDirection 클래스를 조각 코드에 추가한 다음 클래스를 사용하여 조각과 다른 조각 간에 인수를 전달

- NavDirection 클래스는 모든 앱의 동작에서 탐색

 

● 추가인수 전달

Implicit intents:

- 앱이 다른 앱(카메라 앱 또는 이메일 앱 등)을 대신 수행하기를 원하는 액션을 선언

→ GameFragment.kt : 현재 질문 수와 총 질문수를 나타냄

 

- TitleFragment, GameOverFragment, GameWonFragment 에 아래 코드를 추가해 필요할 때마다 NavDirection 클래스를 사용하여 인수를 쉽게 전달할 수 있도록 앱이 설정됨

view.findNavController()

.navigate(TitleFragmentDirections.actionTitleFragmentToGameFragment())

※ Intent는 Android 구성 요소 간의 통신에 사용되는 간단한 메시지 개체(명시적/ 암시적)

 

 

Sharing functionality:

 ( 이 예제에서는 암시적 intent 사용 )

- GameWonFragment.kt에 아래와 같은 코드 추가

    // Creating our Share Intent
    private fun getShareIntent() : Intent {
        val args = GameWonFragmentArgs.fromBundle(requireArguments())
        val shareIntent = Intent(Intent.ACTION_SEND)
        shareIntent.setType("text/plain")
                .putExtra(Intent.EXTRA_TEXT, getString(R.string.share_success_text, args.numCorrect, args.numQuestions))
        return shareIntent
    }

    // Starting an Activity with our new Intent
    private fun shareSuccess() {
        startActivity(getShareIntent())
    }

 

더보기

- EXTAR_TEXT에 실제 전송 데이터 포함됨

- 공유 기능은 GameWonFragment 클래스 내의 옵션 메뉴를 통해 액세스

 

- intent를 구축하기 위해 ACTION_SEND와 같은 수행할 작업을 선언(암묵적)

 

- 성공 공유 시 Intent action이 Intent.ACTION_SEND 됨

 

- Fragment 옵션 메뉴를 추가하려면 Fragment 코드에서 setHasOptionsMenu() 메서드를 true로 설정

 

- startActivity()를 사용해 onOptionsItemSelected()를 오버라이드 해 다른 앱으로

 

퀴즈 정답

출처: https://developer.android.com/courses/pathways/kotlin-fundamentals-four#quiz-/courses/quizzes/kotlin-fundamentals-four/kotlin-fundamentals-four

Navigation  |  Android 개발자  |  Android Developers

Create a fragment, define navigation paths, and start an external activity. Complete the AndroidTrivia app, which is a game in which users answer trivia questions about Android development and can share their results if they win.

developer.android.com