📜 TIL

[Android] Navigation으로 Fragment간 이동을 편리하게 만들어주기

둥굴둥굴둥굴레차 2023. 3. 1. 11:18

Fragment에서 Fragment로 이동에 용이한 Navigation라이브러리 적용시켜보기

→ 해당 라이브러리를 사용하는 방법이 다소 어려워 이 영상을 시청하고 그대로 따라하면서 익혀보았다.

-> 결과물 부터 보고 싶다면 글 제일 아랫 부분으로 이동!

 

Navigation적용하는 이유

  1. 내가 현재 만들고있는 앱은 Single Activity - Multiple Fragments구조이기 때문에 Fragment탐색을 돕는 것에 초점이 맞춰져있는 Navigation라이브러리를 적용하는 것이 좋다
  2. 화면 전환 시 Fragment tansaction을 다루지 않아도 된다.
  3. 화면 전환 시에 필요한 Back/Up 동작을 기본적으로 지원하기 때문에 수고로움을 줄여준다.

 

Navigation을 구성하는 요소

  1. NavHost
    • NavController를 가지고 있는 컨테이너
  2. NavController
    • NavGraph를 다루는 곳
  3. NavGraph
    • Destination 목록을 가지고 있음
    • XML로 작성된다

 

Navigation적용하기

 

우선 해당 라이브러리에 관한 gradle세팅부터 시작!

Navigation Component에 대한 dependencies를 추가해주자.

 

// Module level build.gradle

dependencies {
	...

	implementation("androidx.navigation:navigation-fragment-ktx:2.5.3")
	implementation("androidx.navigation:navigation-ui-ktx:2.5.3")
	
	...
}

 

 

그리고 Safe args Plugin을 추가하자.

 

// Project level build.gradle

buildscript {
    ext.nav_version = "2.3.0"
    dependencies {
        classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.3.0")
    }
}

 

// Module level build.gradle

plugins {
    id 'androidx.navigation.safeargs'
}

💡 만약 Safe Args플러그인이 제대로 세팅되지 않으면, ~FragmentDirections 이 제대로 만들어지지 않는다.

  • NavDirections는 Activity 실행과 비교하면 Intent와 비슷히다.
  • NavDirections는 개발자가 직접 작성하는 것은 아니고, Navigation에 의해 자동 생성되는 클래스다.

 

activity_main.xml에 NavHostFragment를 지정해주자

FragmentContainerView: Activity에서 Fragment를 호스팅하는 일반적인 패턴 중 하나

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">

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


</androidx.constraintlayout.widget.ConstraintLayout>
  • app:defaultNavHost="true" : fragment이동 했을 때 back버튼을 누르면 다시 되돌아올 수 있도록 만들어 준다
  • app:navGraph="@navigation/nav_graph" : nav_graph.xml에 지정된 startDestination이다.
    • nav_graph는 아직 생성이 안된상태! 이제 생성해주러 가자~

 

Navigation을 총괄하기 위한 nav_graph.xml파일을 만들자

 

주의 : layout폴더에서 우클릭 하여 만드는 것이 아니라 최상위 폴더인 res폴더에서 우클릭하여 xml파일 만들어야 한다!

이때 Resource type을 Navigation으로 지정하자!

 

그러면 다음과 같은 파일이 생성된다.

<?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"
    android:id="@+id/nav_graph">

</navigation>

 

 

이제 Fragment와 해당 Fragment의 xml을 생성하자.

HomeFragment.kt 그리고 fragment_home.xml 생성

 

그리고 nav_graph.xml로 돌아가서 생성한 Fragment를 추가해주자!

 

그런데 위와 같이 이미지가 잘 뜨지 않는걸 확인할 수 있다.

 

만약 이를 수정해주고 싶다면 fragment_home.xml로 돌아가서 fragment태그에 다음의 속성을 추가해주자.

tools:layout="@layout/fragment_home"

 

 

이제 fragment를 클릭하여 추가해주자!

그러면 이와 같이 집 모양의 아이콘이 붙으며 추가되는걸 확인할 수 있다.

 

이는 제일 처음 추가되었기 때문에 바로 Starting Destination으로 지정된 것이다.

(만약 Starting Destination을 바꾸고 싶다면 상단 바에 있는 집 모양 아이콘을 클릭하여 전환시키면 된다.)

 

 

두 번째 Fragment를 생성해주고 nav_graph.xml에 추가

 

 

action을 만들어주기 위해 다음과 같이 연결

 

 

만들어진 action태그에 슬라이드 액션 추가해주기

<action
    android:id="@+id/action_homeFragment_to_loginFragment"
    app:destination="@id/loginFragment"
    app:popEnterAnim="@anim/slide_in_left"
    app:popExitAnim="@anim/slide_out_right"
    app:enterAnim="@anim/slide_in_right"
    app:exitAnim="@anim/slide_out_left"/>

 

 

nav_graph.xml 전체코드

<?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/nav_graph"
    app:startDestination="@id/homeFragment">

    <fragment
        android:id="@+id/homeFragment"
        android:name="org.techtown.navigatorfunction.HomeFragment"
        android:label="fragment_home"
        tools:layout="@layout/fragment_home"
        >
        <action
            android:id="@+id/action_homeFragment_to_loginFragment"
            app:destination="@id/loginFragment"
            app:popEnterAnim="@anim/slide_in_left"
            app:popExitAnim="@anim/slide_out_right"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"/>
    </fragment>
    <fragment
        android:id="@+id/loginFragment"
        android:name="org.techtown.navigatorfunction.LoginFragment"
        android:label="fragment_login"
        tools:layout="@layout/fragment_login"
        />
</navigation>

 

HomeFragment.kt로 가서 버튼을 눌렀을 때의 동작을 구현

onCreateView를 사용하여 반드시 view를 생성 및 return해주어야 한다

onViewCreated를 사용하여 setOnClickListener구현

 

HomeFragment.kt 전체코드

class HomeFragment: Fragment() {

    private var _binding: FragmentHomeBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentHomeBinding.inflate(inflater, container, false)

        return binding.root

}

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        binding.buttonLogin.setOnClickListener{

val action = HomeFragmentDirections.actionHomeFragmentToLoginFragment()
findNavController().navigate(action)

}



}

}

 

 

결과물

느낀 점 🤔

Fragment에서 Fragment로 이동할 수 있게 해주는 Navigator에 대해 학습해보았다.

처음엔 이리저리 검색만 해보았는데 전혀 감이 잡히지 않았었다.

그러던 중 Youtube로 설명해주는 강의를 찾았는데, 역시나 영상으로 확인하니 훨씬 쉽게 다가왔다.

그런데 해당 개념을 내 프로젝트에 바로 적용하려니 자꾸만 헷갈리고 어디서부터 건들여야할지 또 고민이었다.

그래서 그냥 아예 Navigator를 공부하기 위한 용도로 Android프로젝트를 새로 생성해서 학습하였다.

그랬더니 훨씬 보기도 쉽고 학습하기 수월하였다.

앞으로도 이렇게해야지!

 

 


 

제 글이 당신에게 도움이 되었길 바랍니다.

추가적인 질문은 언제든지 환영해요.

 

인상깊게 보셨다면 아래 광고 한 번만 클릭해주세요! 정말 큰 힘이 됩니다~! 🤠