안드로이드 UI를 개발할때 Activity 기반에서 Fragment기반으로 개발한지도 상당한 시간이 흘렀습니다..

지금까진 Fragment를 Activity에 붙이기 위해선 FragmentManager 를 이용하여 replace 또는 add를 해야만 했습니다.

예를 들면 아래와 같습니다.

FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fragment_id, CustomFragment(), "tag_name");
ft.commitAllowingStateLoss();
fm.executePendingTransactions();

시간이 흐르면서 안드로이드도 많은 발전을 했는데, 그중 하나가 NavHostFragment를 통한 네비게이션 입니다.

 

안드로이드 스튜디오를 통해서 NavHostFragment 코드를 보면 Fragment를 상속하고 있고 NavHost 인터페이스를 구현하고 있습니다.

NavHost 는 내부적으로 아래와 같은 인터페이스 함수를 가지고 있습니다.

public interface NavHost {

    /**
     * Returns the {@link NavController navigation controller} for this navigation host.
     *
     * @return this host's navigation controller
     */
    @NonNull
    NavController getNavController();
}

그럼 실전에서 어떻게 구현이 가능한지 확인해 보겠습니다.

자세한 사항은 아래 링크를 통해서 확인하시면 됩니다.

developer.android.com/guide/navigation/navigation-getting-started?hl=ko

 

1. xml을 통하여 fragment 또는 FragmentContainerView 선언

<?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"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <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>

fragment와 FragmentContainerView 의 차이는 z-ordering를 처리할수 있느냐에 있습니다.

자세한 내용은 아래 링크를 통해서 확인하시면 됩니다.

developer.android.com/reference/androidx/fragment/app/FragmentContainerView

 

FragmentContainerView  |  Android 개발자  |  Android Developers

From class android.view.ViewGroup void addChildrenForAccessibility(ArrayList arg0) void addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo arg0, String arg1, Bundle arg2) void addFocusables(ArrayList arg0, int arg1, int arg2) void addKeyboardNavigat

developer.android.com

2. FragmentContainerView 에서 선언한 nav_graph 작성

<?xml version="1.0" encoding="utf-8"?>
<navigation android:id="@+id/nav_graph"
    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"
    app:startDestination="@+id/nav_xxx_start">

    <fragment
        android:id="@+id/nav_xxx_start"
        android:name="com.aaa.bbb.ccc.CustomFragment"
        android:label="main fragment"
        tools:layout="@layout/fragment_start_layout" />

    <fragment
        android:id="@+id/nav_webview"
        android:name="com.aaa.bbb.ccc..WebViewFragment"
        android:label="webview fragment"
        tools:layout="@layout/fragment_webview" />
</navigation>

위에서 보면 navigation tag의 app:startDestination 속성이 있는데 이걸 처음 실행할 fragment id로 설정해 줍니다.

각 fragment에는 name속성에 : Fragment 이름, layout속성에는 해당 프레그먼트의 layout id를 넣어줍니다.

 

3. 실제 네비게이션

findNavController(R.id.nav_host_fragment).navigate(R.id.nav_xxx_start)

findNavController의 id는 NavHostFragment 의 id를 사용하고 뒤의 navigate에서는 실제로 움직일 프레그먼트의 id를 넣어줍니다.

만약 argument를 같이 넣어줄 필요가 있으면 아래와 같이 Bundle을 추가해 줍니다.

val bundle = Bundle().apply {
	putInt(EXTRA_TYPE, position)
}

findNavController(R.id.nav_host_fragment).navigate(R.id.id_want_to_go, bundle)

findNavController 를 사용하면 기본적으로 fragment가 중복 적재됩니다. 다시 말하면 같은 프레그먼트를 호출하면 같은 프레그먼트가 적재되고, backkey를 통해서 하나씩 빠지게 됩니다. 만약 이런 처리를 방어하기 위해서는 아래와 같이 navigation option 처리를 하면 됩니다.

val bundle = Bundle().apply {
	putInt(EXTRA_TYPE, position)
}
val navOption = NavOptions.Builder().setLaunchSingleTop(true).build()
findNavController(R.id.nav_host_fragment).navigate(R.id.id_want_to_go, bundle, navOption)

 잘만 활용하면 기존 방식보다 훨씬 짧은 코드로 쉽게 앱개발을 할수 있을것 같습니다.

'프로그래밍 > 안드로이드' 카테고리의 다른 글

app-ads.txt 처리하는 방법  (0) 2020.02.13
Custom view cycle.  (0) 2016.12.14
Stop watch  (0) 2016.11.29
안드로이드 광고 모듈  (0) 2016.11.25
Glide에서 디스크 캐쉬 사용하지 않게 하는 방법  (0) 2016.09.28
by Invincible Cooler 2020. 12. 1. 11:38
| 1 |