본문 바로가기
Android/Errors

Navigation Drawer Activity에서 Fragment 전환

by JuHy_ 2020. 4. 20.

문제점

NavigationView는 NavHostFragment라는 fragment 하나를 놓고 내용물을 바꾸면서 작동한다.

여기에 FragmentManager를 통해 transaction으로 add 또는 replace하여 fragment를 변경하려 했음.

fragment가 바뀌긴 했으나 fragment가 남아있거나 기존 NavHostFragment를 불러오지 못하는 등 문제가 생김.

 

해결 방법

Navigation은 Destination과 Action으로 구성된다.

Destination은 말 그대로 목적지로 fragment를 의미하고,

Action은 fragment 간 이동을 말한다.

 

결론은, navigation 파일에 이동할 fragment를 추가한 뒤 action을 정의하니 깔끔하게 동작.

 

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

    <fragment
        android:id="@+id/nav_movielist"
        android:name="com.juhy.cinemaheaven.MovieList.MovieListFragment"
        android:label="@string/menu_movielist"
        tools:layout="@layout/fragment_movielist" >
        <action
            android:id="@+id/action_nav_movielist_to_nav_moviedetail"
            app:destination="@id/nav_moviedetail" />
    </fragment>

    <fragment
        android:id="@+id/nav_moviedetail"
        android:name="com.juhy.cinemaheaven.MovieDetail.MovieDetailFragment"
        android:label="@string/menu_moviedetail"
        tools:layout="@layout/fragment_moviedetail" />

    <fragment
        android:id="@+id/nav_movieapi"
        android:name="com.juhy.cinemaheaven.MovieAPI.MovieApiFragment"
        android:label="@string/menu_movieapi"
        tools:layout="@layout/fragment_movieapi" />

    <fragment
        android:id="@+id/nav_reservation"
        android:name="com.juhy.cinemaheaven.Reservation.ReservationFragment"
        android:label="@string/menu_reservation"
        tools:layout="@layout/fragment_reservation" />

    <fragment
        android:id="@+id/nav_settings"
        android:name="com.juhy.cinemaheaven.Settings.SettingsFragment"
        android:label="@string/menu_settings"
        tools:layout="@layout/fragment_settings" />

</navigation>

이동할 fragment인 MovieDetailFragment를 추가한 뒤,

출발할 fragment 내부에 action 태그를 추가하여 destination을 MovieDetailFragment로 설정.

번거롭다면 UI에서 fragment 가장자리의 점을 드래그하여 선을 연결하면 자동으로 생성됨.

 

public void moveToDetail(){
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    navController.navigate(R.id.action_nav_movielist_to_nav_moviedetail);
}

NavigationHost가 올라가있는 액티비티에 메소드를 만들어주었다.

Action을 수행하는 것을 NavController의 navigate() 함수에 action id를 넣어주면 된다.

 

Button button = rootView.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        MainActivity activity = (MainActivity) getActivity();
        activity.moveToDetail();
    }
});

그리고 만들어둔 메소드를 fragment에서 버튼을 클릭 시 호출하여 이동하도록 구현하였다.