네비게이션 컴포넌트는 애플리케이션의 화면간의 이동을 구현하는것을 단순화 시켜주는 라이브러리이다.
Jetpack에는 포함되어있지만 androidx로 패키지 리팩토링은 진행중이며, 게다가 아직은 보편화되지 않은컴포넌트인지라 ‘Navigation’이라는 키워드로 검색하면 Navigation View, Navigation bar 등의 자료가 더 많아 공식문서 외에는 정보를 접하기가 어렵다. 사실 발표되지 얼마 않은 기술들은 공식문서가 제일 보기 좋다.
네비게이션의 기본 원칙
1. 앱은 반드시 고정된 시작점(starting destination)을 가져야 한다.
고정된 시작점은 사용자가 보는 첫번째 화면이자 사용자들이 back 버튼을 눌러서 도착하는 마지막 화면이 되어야 합니다.
2. 스택은 “네비게이션 상태”를 나타냅니다.
스택은 아시다시피 후입선출 구조입니다. 네비게이션 스택은 시작점을 가지며 스택의 바닥에 위치하게 되고 현재의 위치는 스택의 가장 최상단에 위치 하게 됩니다.
3. Up버튼으로는 앱을 종료할 수 없습니다.
만약 사용자가 시작점에 있다면 Up 버튼은 보이지 않을 것입니다. 또다 른 앱의 태스크에서 딥링크를 이용하여 앱이 시작되었다면, Up버튼은 사용자를 원래의 부모계층의 앱의 방향으로 향하지, 다른앱으로 다시 돌아가거나 하지 않습니다.
4. 앱의 태스크내에서 Up , Down 버튼은 동등합니다.
시스탬의 Back 버튼으로 앱이 종료되지 않을때, Up버튼의 기능도 Back버튼과 동일하게 동작합니다.
5. 딥링크나 같은 목적지로 향하는 네비게이션은 같은 동일한 스택으로 처리 됩니다.
사용자는 앱시작점으로 들어갈수도 있고 어떤 지점으로 이동할 수도 있습니다. 사용자는 딥링크를 사용할수도 있으며 가능하다면 같은 목적지로 이동할수도 있도 있죠. 두가지 경우 다 네비게이션 스택은 동일한 스택을 사용합니다. 구체적으로 말하자면 사용자가 어떻게 목적지에 도달했느냐와 상관없이 시작지점을 가기위해 Back버튼이나 Up버튼을 사용가능합니다. 존재하는 네비게이션은 지워지고 딥링크의 네비게이션 스택으로 교체 됩니다.
네비게이션 컴포넌트 구현해보기
기본적으로 네비게이션 컴포넌트는 Fragment와 액티비티를 목적지(destination)라고 부른다. 물론 이 외에도 다른타입의 목적지를 추가 할 수도 있다.
목적지들의 집합은 애플리케이션의 navigation graph로 구성된다.
네비게이션의 그래프는 목적지간의 action으로 연결이 되어진다. 그림을 통해 6개의 목적지가 5개의 액션으로 어떻게 연결되는지 확인해보자
Note:네비게이션은 Android 3.2 Canary 14버전 이상에서만 사용가능합니다. |
---|
네비게이션 라이브러리 의존성 설정하기
네비게이션 그래프를 만들기 전에 네비게이션 아키텍처 컴포너트를 프로젝트에 추가해야합니다.
androidX 패키지에는 포함되었으나 현재는 support library 27.1.1과 관련된 아키텍처 컴포넌트 버전에만 의존하고 있습니다. AndroidX용 버전은 추후 출시될 예정입니다.
앱레벨의 build.gradle
dependencies { def nav_version = "1.0.0-alpha02" implementation "android.arch.navigation:navigation-fragment:$nav_version" implementation "android.arch.navigation:navigation-ui:$nav_version" // optional - Test helpers androidTestImplementation "android.arch.navigation:navigation-testing:$nav_version" }
Note:코틀린에서 사용하려면 패키지명 뒤에, 버전명 앞에 -ktx 를 붙이면됩니다.
Safe args 추가 설정은
프로젝트 레벨의 build.gradle에 다음과 같이 설정합니다.
buildscript { repositories { google() } dependencies { classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha02" } }
앱 레벨의 build.gradle 설정은 다음을 추가합니다.
apply plugin: "androidx.navigation.safeargs"
프로젝트에 네비게이션 추가하기
- 프로젝트 윈도우에서 우클릭을 하여서 New>Android resource file을 클릭합니다.
- 파일명을 정해줍니다. 저는 nav_graph로 정했습니다.
- ResourceType을 Navigation으로 선택합니다.
- Ok를 누릅니다.
그러면 res폴더에 navigation디렉토리가 생성되는것을 확인할수 있고,
nav_graph.xml파일이 위 디렉토리에 생성됩니다. - nav_graph.xml 열고 Text탭과 Design탭을 각각선택하여 코드와 그래프를 번갈아 가면서 볼 수 있는지 확인합니다.
네비게이션 둘러보기
- 목적지 목록 – 그래프 편집기에서 현재 목적지들의 목록을 보여줍니다
- 그래프 편집기 – 네비게이션 그래프의 가시적인 내용들을 포함합니다.
- 속성 편집기 – 목적지와 관련된 속성들 그리고 행위(action)들을 그래프 편집기에 포함시킬수 있습니다.
목적지 정의 하기
네비게이션 그래프를 생성하는데 있어서 첫걸음은 목적지를 설정하는것입니다. 빈 목적지 생성하거나 또는 이미 존재하는 액티비티나 프레그먼트로부터 목적지를 생성할 수 있습니다.
Note : 네비게이션 아키텍처 컴포넌트는 하나의 주된 액티비티와 함께 여러 프레그먼트를 목적지로 하는 방향으로 설계가 되었다. 액티비티는 호스트가 되어 네비게이션 그래프를 관장하고, 여러 액티비티를 목적지로 하는 애플리케이션의 경우 각각의 액티비티가 호스트가 되어 각각의 네비게이션 그래프를 가지면 된다. |
---|
목적지를 정의 하기 위해 다음 지시를 따라 주세요
- Graph Editor로부터 New Destination을 클릭하세요. 다이얼로그가 나타날 것입니다.
- Create blank destination 또는 fragment or activity 를 클릭하세요. Android Component 다이얼로그가 나타날 것입니다.
- Fragment Name에 이름을 적어주세요. 이름은 프레그먼트의 클레스 이름으로 적어주세요.
- Fragment Layout Name필드에 이름을 적어주세요. 이 곳은 프레그먼트에서 쓰이는 레이아웃의 이름을 적어주세요
- finish버튼을 누르세요. 목적지를 표현하는 박스가 그래프 에디터에 나타나고 목적지들의 목록또한 나타날 것입니다.
- 만약 blank destination을 만들었다면 , 그래프에디터에서 Hello blank fragment메시지를 목적지에서 확인할 수 있습니다. 만약 프레그먼트나 액티비티를 클릭했었다면 그래프 에디터는 액티비티나 프레그먼트의 레이아웃 프리뷰를 보여줄 것입니다.
- 프래그먼트의 서브클래스가 생성되었습니다. 이 클래스는 3.에서 정한 이름으로 정해질 것입니다.
- 리소스 파일도 생성되었습니다 이 파일은 4.에서 정한 이름으로 생성됩니다.
- 새롭게 추가된 목적지를 클릭하세요, attributes panel에 다음과 같은 속성들이 나타날것입니다
- Type 필드에는 Fragment나 Activity가 어떤 목적지로 설정되어있지 표시 될것입니다.
- Label 필드에는 목적지의 xml 레이아웃 파일의 이름이 포함되어있습니다.
- ID 필드는 목적지의 ID를 포함하고 있으며, 나중에 목적지를 참조하는데 쓰입니다.
- Class 필드는 목적지 클래스의 이름이 적혀있습니다.
- Text탭을 클릭하여 XML뷰로 전환합니다. XML은 지금 id, name(클래스이름), label, layout 으로 되어있습니다.
<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" app:startDestination="@id/blankFragment"> <fragment android:id="@+id/blankFragment" android:name="com.example.cashdog.cashdog.BlankFragment" android:label="Blank" tools:layout="@layout/fragment_blank" /> </navigation> |
Note: XML은 startDestination 속성을 가지고 있으며, 이 속성은 목적지의 id를 참조합니다. |
---|
목적지 연결하기
목적지에 연결하려면 반드시 하나이상의 목적지를 가지고 있어야 합니다. 다음 예제를 확인해보시죠.
<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" app:startDestination="@id/blankFragment"> <fragment android:id="@+id/blankFragment" android:name="com.example.cashdog.cashdog.BlankFragment" android:label="fragment_blank" tools:layout="@layout/fragment_blank" /> <fragment android:id="@+id/blankFragment2" android:name="com.example.cashdog.cashdog.BlankFragment2" android:label="Blank2" tools:layout="@layout/fragment_blank_fragment2" /> </navigation> |
목적지들은 액션을 통해 연결되어지며, 두개 이상의 목적지를 연결하기 위해서는 다음과 같아야합니다.
- 그래프 에디터에서 사용자가 네비게이팅하고 싶은 목적지의 오른편으로 마우스를 갖다 댑니다. 동그란 모양이 목적지 옆에 생길것입니다.
- 마우스로 왼클릭한채로 드래그하여 연결하고 싶은 목적지로 이동한뒤 놓으면 연결이 됩니다.
- 화살표 모양을 클릭하여 액션을 하이라이트 합니다. 다음과 같은 속성이 Attributes panel에 나타날것입니다.
- Type 필드는 Action을 포함합니다
- 아이디 필드는 action을위한 system에 적용된 id를 포함합니다
- Destination 필드는 목적지 프레그먼트나 액티비티의 ID를 포함합니다.
- Text탭을 눌러 XML뷰로 변경합니다. <action> 은 부모 목적지에 추가되어있는것을 확인할 수 있습니다. 액션은 시스템이 부여한 ID를 가지고 있고 목적지에대한 ID정보도 가지고 있습니다.
<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" app:startDestination="@id/blankFragment"> <fragment android:id="@+id/blankFragment" android:name="com.example.cashdog.cashdog.BlankFragment" android:label="fragment_blank" tools:layout="@layout/fragment_blank" > <action android:id="@+id/action_blankFragment_to_blankFragment2" app:destination="@id/blankFragment2" /> </fragment> <fragment android:id="@+id/blankFragment2" android:name="com.example.cashdog.cashdog.BlankFragment2" android:label="fragment_blank_fragment2" tools:layout="@layout/fragment_blank_fragment2" /> </navigation>
시작 목적지로 화면 지정하기
그래프 에디터에서 집모양의 아이콘을 볼수 있는데 , 이 아이콘은 해당 네비게이션 그래프에서 시작 목적지를 표시해주는 아이콘입니다. 다음과 같은 절차를 걸쳐 새로이 시작 목적지를 변경할 수 있습니다.
- 그래프 에디터에서 하나의 목적지를 선택한다. 목적지가 선택된것을 확인할 수 있다.
- Set Start Destination항목을 Attribute Panel에서 찾아 클릭하자. 이제 해당 목적지는 시작 목적지로 지정되었다.
액티비티를 네비게이션 호스트로 수정하기(Modify an activity to host navigation)
하나의 액티비티는 NavHost 인터페이스 구현을 통해 네비게이션을 관리 하게 된다. 액티비티가 가지고 있는 레이아웃에서 이 작업을 할 수 있다. NavHost는 빈 하나의 빈 껍데기 뷰이며 여기에서 목적지간의 화면전환을 하게 된다.
네비게이션 아키텍쳐 컴포넌의 기본 NavHost구현은 NavHostFragment로 되어있다.
NavHost설정한 뒤 네비게이션 그래프에 navGraph 속성을 이용하여 NavHostFragment를 연결해야 한다. 아래의 스니펫은 어떻게 NavHostFragment를 포함하는지를 보여주고 네비게이션 그래프와 NavHostFragment를 어떻게 액티비티 레이아웃에서 연결하는지를 보여준다.
?xml version="1.0" encoding="utf-8"?> <android.support.constraint.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:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/my_nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" app:navGraph="@navigation/nav_graph" app:defaultNavHost="true" /> </android.support.constraint.ConstraintLayout> |
app:defaultNavHost=”true” 속성은 NavHostFragment가 시스템으로부터 Back버튼을 이벤트를 가로챌수 있게 한다. AppCompatActivity.onSupportNavigateUp() 을 덮어쓰고 NavController.navigateUp를 호출 할수 있게 된다. 아래의 코드를 확인하자.
@Override public boolean onSupportNavigateUp() { return Navigation.findNavController(this, R.id.nav_host_fragment).navigateUp(); } |
UI 위젯에 목적지를 지정하기(Tie destinations to UI widgets)
목적지로 이동하는것은 NavController를 통하 하게 된다. NavController 다음중 하나의 static 메소드들을 통해 얻을 수 있다.
- NavHostFragment.findNavController(Fragment)
- Navigation.findNavController(Activity, @IdRes int viewId)
- Navigation.findNavController(View)
NavController를 가져왔다면, navigate() 메소드를 이용하여 원하는 목적지로 이동할 수 있다. navigate()메소드는 resource Id를 인자로 받는다. 네비게이션 그래프에 정의된 목적지 ID나 액션의 ID가 navigate() 인자로 적합하다. 목적지 ID를 사용하는것 데신에 액션의 ID를 사용하는 것은 화면전환 효과를 간단하게 구현하는데 장점이 있다.
viewTransactionsButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Navigation.findNavController(view).navigate(R.id.viewTransactionsAction); } }); |
안드로이드 시스템은 앱을 실행하면 첫번째 목적지가 백스택에 배치되고, 방문한 목적지들을 차곡차곡 쌓아 관리 하게 된다. navigate()를 호출할때마다 스택의 가장 최상위 부분에 목적지를 채워넣게 된다. 역으로 Up 또는 Back버튼을 누를때 제각기 NavController.navigateUp()과 NavController.popBackStack()메소드가 호출이 된다. 그러면 백스택에서는 최상단에 배치되어있던 목적지가 없어지게 된다.
버튼에서는 Navigation 클래스의 createNavigationOnClickListener()라는 편리한 메소드를 통해 목적지로 이동할 수 있다.
button.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.next_fragment, null)); |
Menu를 중심으로 UI 컴포넌트를 연결하기
Navigation Drawer 나 Overflow menu의 id를 목적지의 id와 똑같이 만들어 목적지로 이동할 수 있다.
<fragment android:id="@+id/details_page_fragment" android:label="@string/details" android:name="com.example.android.myapp.DetailsFragment" /> |
같은 아이디를 메뉴와 목적지같에 사용하는것으로 목적지와 메뉴아이템간에 자동으로 연결이 된다. 아래의 xml코드는 어떻게 프레그먼트 목적지와 메뉴 아이템이 연결되는지 보여준다.
<item android:id="@id/details_page_fragment" android:icon="@drawable/ic_details" android:title="@string/details" /> |
아래의 XML 코드는 어떻게 오버플로 메뉴와 목적지가 결합되는지 보여준다.
<item android:id="@id/details_page_fragment" android:icon="@drawable/ic_details" android:title="@string/details" android:menuCategory:"secondary" /> |
네비게이션 아키텍쳐 컴포넌트는 NavigationUI 클래스를 포함한다. 이클래스는 몇몇 스태틱 메소드를 포함하고 있고 그저 개발자는 가져다 사용하여 메뉴랑 목적지랑 연결해주는 작업만 하면된다. 아래의 예제는 setupWithNavController()메소드를 사용하여 NavigationView에 아이템들을 연결하는것을 보여주고 있다.
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); NavigationUI.setupWithNavController(navigationView, navController); |
이러한 UI요소상태가 NvController의 변화에 맞게 동기화 되려면, NavigationUI를 사용하여 메뉴중심의 네비게이션 컴포넌트를 설정하는것이 필요합니다.
목적지간의 data 공유하기
두가지 방법으로 목적지간의 데이터를 공유할 수 있습니다. Bundle을 이용하는것 또는 Gradle 플러그인을 사용하는 type-safe한 방법.
Gradle을 사용하고 있다면 type-safe한 방법을 고려해보세요. 다음 단락에서 소개 하겠습니다.
- 그래프 에디터에서 인자를 받을 목적지를 클릭한다.
- Attribute Panel의 Argument Section에서 Add(+) 를 누르자. 비어있는 이름과 기본값 필드가 보일것이다.
- 이름 더블클릭하고 인자에 대한 이름을 지정한다.
- 마찬가지로 인자에 대한 기본값도 설정하자
- 방금 설정한 목적지의 액션을 클릭한다. 기본 인자값은 반드시 입력해야한다.
- Text탭을 눌러 XML뷰로 전환하자.<argument> 태그가 설정된것을 확인할 수 있다.
- code에서 bundle을 하나 생성하고 navigate()메소드를 통해 bundle객체를 전달해보도록하자
Bundle bundle = new Bundle(); bundle.putString("amount", amount); Navigation.findNavController(view).navigate(R.id.confirmationAction, bundle);
인자를 받는 목적지 코드에서는 getArgument()를 사용하여 번들에 포함된 데이터를 가져올 수 있다.
TextView tv = view.findViewById(R.id.textViewAmount); tv.setText(getArguments().getString("amount"));
Type-safe한 방법으로 목적지간의 data 공유하기
네비게이션 아키텍처 컴포넌트는 safeargs라는 Gradle plugin을 갖는다. type-safe한 인자 접근 방식을 위해 위해 간단한 오브젝트와 빌더클래스를 생성해준다. Safe args는 Bundle의 최상위에 만들어진다. 하지만 약간의 코드작성을 필요로 한다. 만약 Gradle을 사용하고 있다면 safe args 플러그인을 사용할수 있다. 이 플러그인 설치하기 위해서는 ‘androidx.navigation.safeargs’를 모듈 레벨의 build.gradle에 추가 하면된다.
apply plugin: 'com.android.application' apply plugin: 'androidx.navigation.safeargs' android { //... } |
Gradle 플러그인 설정이 끝나면 다음과 같은 단계를 거쳐 type-safe를 이용하면 된다.
- 그래프 에디터에서 인자를 받고 싶은 목적지를 클릭한다.
- Add(+)를 누른다. 비어있는 이름과 기본값 필드가 보일것이다.
- 이름을 더블클릭하여 인자에 대한 이름을 작성한다.
- 드롭다운 목록으로 부터 인자에 대한 자료형을 선택한다.
- 인자의 기본값을 설정한다.
- 방금 설정한 목적지의 액션을 클릭한다. 기본 인자값은 반드시 입력해야한다.
- Text탭을 눌러 XML뷰로 전환한다. <argument> 태그가 설정되어있고, name과 defaultValue값이 셋팅된것을 확인할 수 있다.
<fragment android:id="@+id/confirmationFragment" android:name="com.example.buybuddy.buybuddy.ConfirmationFragment" android:label="fragment_confirmation" tools:layout="@layout/fragment_confirmation"> <argument android:name="amount" android:defaultValue="1" app:type="integer"/> </fragment> |
safeargs플러그인을 이용하여 코드를 생성할때에는 간단한 오브젝트와 빌더클래스만 액션을 만들수 있었고 목적지에 인자를 전송하거나 받을 수 있었다.
- 액션이 시작된 목적지클래스에 Direction이라는 단어가 추가 됩니다. 그렇기 때문에 만약 프레그먼트는 이름이 SpecifyAmountFragment인 경우 생성된 클래스의 이름은 SpecifyAmountFragmentDirections입니다. 이 클래스는 confirmationAction()이라는 하나의 메소드가지고 있다. 이것은 action을 위해 이름을 짓고, 인자를 전달하기 위해 사용되어졌다.
- 액션을 기반으로 인자전달하는데 사용하는 내부클래스입니다. 건네주는 액션이 confirmationAction이라면 클래스의 이름은 ConfirmationAction입니다.
- 인자가 전달되는 목적지의 클래스에 Args라는 단어가 추가되었습니다
그래서 만약 목적지 프레그먼트가 ConfirmationFragment라면 생성되는 클래스는 ConfirmationFragmentArgs입니다. 이 클래스의 fromBundle() 메소드를 통해 인자값을 가져 올 수 있습니다.
아래의 코드는 인자를 설정하고 navigate()메소드에 넘겨주는것을 어떻게 사용하는지에 대한 코드입니다.
@Override public void onClick(View view) { EditText amountTv = (EditText) getView().findViewById(R.id.editTextAmount); int amount = Integer.parseInt(amountTv.getText().toString()); ConfirmationAction action = SpecifyAmountFragmentDirections.confirmationAction() action.setAmount(amount) Navigation.findNavController(view).navigate(action); } |
인자를 전달받는 코드는 getArguments()를 이용하면 됩니다.
@Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { TextView tv = view.findViewById(R.id.textViewAmount); int amount = ConfirmationFragmentArgs.fromBundle(getArguments()).getAmount(); tv.setText(amount + "") } |
다른 네비게이션을 포함하는 네비게이션 그래프만들기
일련의 목적지들을 네비게이션 그래프 내의 하위 그래프로 그룹화 할 수 있습니다. 하위 그래프는 nested graph라 불리며, root graph를 포함하고 있습니다. Nested graph들은 애플리케이션의 UI를 정리하고 재사용할 때 매우 유용하게 쓰일 수 있습니다. 예를들면 로그인 성공 실패 등과 같은 분기 흐름에서 유용하게 쓰일 수 있습니다.
root graph프와 마찬가지로, nested graph도 반드시 하나의 목적지를 시작점으로 설정해야합니다. nested graph는 자신이 가지고 있는 목적지들을 캡슐화 합니다. nested graph 바깥쪽에 root graph가 가지고 있는 목적지들은 단지 nested graph의 시작점에만 접근 가능합니다. 아래의 그림은 간단한 송금하는 앱의 네비게이션 그래프를 보여주고 있습니다. 이 그래프는 두개의 분기 흐름을 가지고 있는데 하나는 사용자가 돈을 보내는것이고 또 다른 하나는 사용자가 잔고를 확인하는 화면입니다.
nested graph로 목적지를 그룹화 하기 위해서는
- 그래프에디터에서 shift를 누른 상태에서 nested graph에 포함하고 싶은 목적지들을 선택한다. 목적지를 클릭할 때 마다 목적지가 강조되며 선택되는것을 확인할 수 있다. 드래그도 가능함.
- 우클릭하여서 Move to Nested Graph > New Graph를 선택하자. 단축키 cmd+g. 목적지들이 nested graph로 쏙 들어가는 것을 확인할 수 있다.
- nested graph를 클릭한다. 아래의 속성들이 Attribute panel에 나타납니다
– Type 필드에 Nested Graph가 포함되어있습니다.
– ID필드에 시스템에서 적용된 nested grap의 ID가 포함됩니다. 이 아이디는 code에서 nested graph를 참조하기 위해 쓰입니다. - nested graph를 더블클릭합니다. nested graph안에 있떤 목적지들이 나타납니다.
- 목적지를 나타내는 목록에서 Root 를 클릭하여 다시 root 네비게이션 그래프로 돌아올 수 있습니다.
- Text탭을 클릭하여 XML 뷰로 전환합니다. nested 네비게이션 그래프가 추가 된걸 알 수 있고 <navigation>태그 내에 또 다른 <navigation>이 있음을 확인할 수 있습니다. 이 nested graph는 sendMoneyGraph라는 Id를 가지고 있고 chooseRecipient라는 프레그먼트를 시작점으로 갖고 있습니다.
<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" app:startDestination="@id/mainFragment"> <fragment android:id="@+id/mainFragment" android:name="com.example.cashdog.cashdog.MainFragment" android:label="fragment_main" tools:layout="@layout/fragment_main" > <action android:id="@+id/action_mainFragment_to_chooseRecipient" app:destination="@id/sendMoneyGraph" /> <action android:id="@+id/action_mainFragment_to_viewBalanceFragment" app:destination="@id/viewBalanceFragment" /> </fragment> <fragment android:id="@+id/viewBalanceFragment" android:name="com.example.cashdog.cashdog.ViewBalanceFragment" android:label="fragment_view_balance" tools:layout="@layout/fragment_view_balance" /> <navigation android:id="@+id/sendMoneyGraph" app:startDestination="@id/chooseRecipient"> <fragment android:id="@+id/chooseRecipient" android:name="com.example.cashdog.cashdog.ChooseRecipient" android:label="fragment_choose_recipient" tools:layout="@layout/fragment_choose_recipient"> <action android:id="@+id/action_chooseRecipient_to_chooseAmountFragment" app:destination="@id/chooseAmountFragment" /> </fragment> <fragment android:id="@+id/chooseAmountFragment" android:name="com.example.cashdog.cashdog.ChooseAmountFragment" android:label="fragment_choose_amount" tools:layout="@layout/fragment_choose_amount" /> </navigation> </navigation>
- 코드내에서 root 그래프에서 nested graph로 연결된 액션의 리소스 아이디를 넘길수 있습니다.
Navigation.findNavController(view).navigate(R.id.action_mainFragment_to_sendMoneyGraph);
목적지 딥링크 생성하기
안드로이드에서 딥링크는 애플리케이션의 특정 목적지를 포인팅 하는 URI입니다. 이런 URI들은 사용자에게 어떤 일을 수행하기위해 특정 목적지로 보낼때 매우 유용합니다. 예를들면 빠르게 다른사람에게 송금하는 플로우를 앱으로 짤때 유용하죠.
목적지에 딥링크 적용하기
네비게이션 그래프에서 딥링크를 목적지에 적용하기 위해서는 다음의 절차를 따라주세용
- 그래프 에디터에서 딥링크를 사용하고 싶은 목적지를 선택합니다.
- Attribute panel의 딥링크 섹션에서 + 버튼을 누르면, Add Deep Link 다이얼로그 박스가 나타납니다.
- URI 필드에 URI를 적습니다. 예를 들면 ‘www.cash.com/sendmoeny’와 같이 말이죠
- http 와 https같은 scheme이 없는 URI의 경우, 예를들면, www.cashdog.com은 http://www.cashdog.com 그리고 https://www.cashdog.com으로 대응됩니다.
- {placeholder_name}와 같은 형식의 플레이스 홀더는 1개 이상의 문자열이 대치 될수 있습니다. 플레이스 홀더에서 String 형식의 값이 Bundle의 인자를 뽑기 위한 key값으로 쓸수 있습니다.
예를들면, 다음과 같습니다.http://www.example.com/users/{id}
→http://www.example.com/users/4
- * 와 같은 와일드카드는 0개 이상의 문자열로 사용할 수 있습니다.
- (선택사항) Auto Verify를 클릭하여 Google에 해당 URI를 소유 할 수 있는지 인증 받을수 있습니다. 자세한 내용은 Verify Android App Links를 참조하세요
- Add를 클릭합니다. 다음과 같은 연결 아이콘이 선택된 목적지 위에 표시 됩니다. 목적지가 딥링크를 포함하고 있다는 표시입니다.
- Text를 클릭하여 XML 뷰로 전환합니다. deep link 태그가 추가 된것을 볼 수 있습니다.
<deepLink app:uri="https://cashdog.com/sendmoney"/>
사용자가 딥링크 목적지로에서 백버튼을 클릭했다면, 애플리케이션 네비게이션 스택에 마지막으로 방문헀던 진입점으로 이동합니다.
딥링크용 인텐트 필터 추가하기
딥링크용 틴텐트 필터를 추가할 경우 반드시 manifest.xml에 추가해야합니다.
- 안드로이드 스튜디오 3.0 그리고 3.1 버전에서는 intent-filter를 수동으로 추가해야합니다. 다음을 참조하세요. Create Depp Links to App Content
- 안드로이드 스튜디오 3.2이상에서는 nav-graph 태그를 액티비티 태그내에 추가 할 수 있습니다.
<activity name=".MainActivity"> <nav-graph android:value="@navigation/main_nav" /> </activity>
<nav-graph>태그는 해당 네비게이션 그래프의 모든 딥링크들을 매니페스트 병합하는 빌드단계 골라내서 코드를 재생성 하게 된다.
목적지간의 화면전환 효과 생성하기
네비게이션 아키텍처 컴포넌트는 fade-in , fade-out과 같은 트랜지션효과와 함께 쉽게 화면을 전환하는 기능을 제공합니다.
트랜지션을 추가하려면 아래의 절차를 따라주세요.
- animation 리소스 파일을 생성합니다. 네비게이션 아키텍처 컴포넌트는 속성과 뷰 애니메이션을 지원합니다.
- 그래프에디터에서 트래지션 걸고 싶은 액션을 클릭합니다.
- Attributes panel의 Transitions섹션에서 Enter옆에 있는 드롭다운메뉴를 클릭합니다. 프로젝트에 포함된 트랜지션 목록이 나타납니다.
- 목적지 진입용 애니메이션을 선택합니다.
- Attributes panel의 Transitions섹션에서 Exit옆에 있는 드롭다운메뉴를 클릭합니다. 프로젝트에 포함된 트랜지션 목록이 나타납니다.
- 목적지 진출용 애니메이션을 선택합니다.
- Text탭을 클릭하여 XML뷰로 변환합니다. 액션태그내에 애니메이션이 적용된것을 확인 할 수 있습니다.
<fragment android:id="@+id/specifyAmountFragment" android:name="com.example.buybuddy.buybuddy.SpecifyAmountFragment" android:label="fragment_specify_amount" tools:layout="@layout/fragment_specify_amount"> <action android:id="@+id/confirmationAction" app:destination="@id/confirmationFragment" app:enterAnim="@anim/slide_in_right" app:exitAnim="@anim/slide_out_left" app:popEnterAnim="@anim/slide_in_left" app:popExitAnim="@anim/slide_out_right" /> </fragment>
0개의 댓글