본문 바로가기
Android Application/기초 사용법

안드로이드 네비게이션(navigation) 사용

by sdchjjj 2023. 3. 30.
728x90

안녕하세요.

이번 포스팅에서는 기본적인 안드로이드 네비게이션을 구현해 보겠습니다.

 

dependency를 추가합니다.

build.gradle(project)

buildscript {
    ext {
        nav_version = '2.5.3'
    }
    dependencies {
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
    }
}

 

build.gradle(:app)

plugins {
    ...
    id 'androidx.navigation.safeargs.kotlin'
    ...
}

dependencies {
    ...
    implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
    implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
    ...
}

 

프래그먼트 3개를 생성하겠습니다(figure1 참조).

figure1. create fragments

그리고 각각의 프래그먼트를 모두 아래와 같이 만들어 줍니다.

AFragment.kt

class AFragment : Fragment() {
    
    private var _binding: FragmentABinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentABinding.inflate(layoutInflater, container, false)
        return binding.root
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

 

BFragment.kt

class BFragment : Fragment() {

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

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentBBinding.inflate(layoutInflater, container, false)
        return binding.root
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

 

CFragment.kt

class CFragment : Fragment() {

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

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentCBinding.inflate(layoutInflater, container, false)
        return binding.root    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

 

 

위에서 사용된 view binding은 아래 포스트를 참고해 주세요.

https://it-of-fortune.tistory.com/21

 

안드로이드 ViewBinding(뷰바인딩) 구현

안녕하세요. 이번 포스팅에서는 안드로이드 프래그먼트에서의 뷰바인딩 구현을 진행해 보겠습니다. 언어: 코틀린 sdk vsersion - compile: 33 - min: 21 - target: 33 바인딩 진행 전 사전 준비 작업입니다.

it-of-fortune.tistory.com

 

xml은 각각 아래와 같이 구성해 줍니다.

fragment_a.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".fragments.AFragment">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="A 프래그먼트"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"/>

    <Button
        android:id="@+id/move_next"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="다음"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

 

fragment_b.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".fragments.BFragment">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="B 프래그먼트"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

    <Button
        android:id="@+id/move_next"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="다음"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

 

fragment_c.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".fragments.CFragment">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="C 프래그먼트"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

다음으로, res > navigation directory를 생성한 뒤 Navigation Resource File을 생성해 줍니다(figure2 참조).

저는 nav_main.xml 이름으로 생성했습니다.

figure2. create navigation resource file

 

생성을 마친 후 Design 탭에서 네비게이션에 사용할 프래그먼트를 추가합니다(figure3-1, 3-2 참조).

figure3-1. add fragment
figure3-2. add fragment

위 과정이 끝나면 추가된 fragment들의 preview가 보이게 됩니다(figure4 참조).

figure4. fragment preview

이제 navigation direction을 설정해 주겠습니다.

마우스 드래그로 간편하게 설정 가능합니다(figure5 참조).

figure5. navigation direction setting

위 세팅으로 A -> B, B -> C 이동 구현이 가능하게 되었습니다.

 

참고로 code부분은 자동으로 추가 / 수정됩니다.

위의 과정을 마치면 아래 코드가 자동으로 생성됩니다.

지금은 code 부분을 건드릴 필요는 없습니다.

nav_main.xml(code tab)

<?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_main"
    app:startDestination="@id/AFragment">
    <fragment
        android:id="@+id/AFragment"
        android:name="com.contents.laboratory.fragments.AFragment"
        android:label="fragment_a"
        tools:layout="@layout/fragment_a" >
        <action
            android:id="@+id/action_AFragment_to_BFragment"
            app:destination="@id/BFragment" />
    </fragment>
    <fragment
        android:id="@+id/BFragment"
        android:name="com.contents.laboratory.fragments.BFragment"
        android:label="fragment_b"
        tools:layout="@layout/fragment_b" >
        <action
            android:id="@+id/action_BFragment_to_CFragment"
            app:destination="@id/CFragment" />
    </fragment>
    <fragment
        android:id="@+id/CFragment"
        android:name="com.contents.laboratory.fragments.CFragment"
        android:label="fragment_c"
        tools:layout="@layout/fragment_c" />
</navigation>

 

이제 MainActivity에 navigation container를 추가하겠습니다.

아래와 같이 작성해 줍니다.

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:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_main" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

이제 프래그먼트의 이동을 구현하겠습니다.

AFragment.kt

class AFragment : Fragment() {

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

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentABinding.inflate(layoutInflater, container, false)
        binding.moveNext.setOnClickListener {
            navigateToBFragment()
        }
        return binding.root
    }

    private fun navigateToBFragment() {
        this@AFragment.findNavController().navigate(
            AFragmentDirections.actionAFragmentToBFragment()
        )
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

 

BFragment.kt

class BFragment : Fragment() {

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

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentBBinding.inflate(layoutInflater, container, false)
        binding.moveNext.setOnClickListener {
            navigateToCFragment()
        }
        return binding.root
    }

    private fun navigateToCFragment() {
        this@BFragment.findNavController().navigate(
            BFragmentDirections.actionBFragmentToCFragment()
        )
    }


    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

 

 CFragment는 바뀌는 것이 없습니다.

 

아래의 코드가 이동을 담당하는 부분입니다.

this@BFragment.findNavController().navigate(
    BFragmentDirections.actionBFragmentToCFragment()
)

 

에뮬레이터에서 실행해 보겠습니다.

figure6. run

정상적으로 동작합니다.

또한, back key 클릭 시 이전의 프래그먼트로 이동하는 것까지 확인 가능합니다.

 

이상 포스팅을 마치겠습니다.

 

감사합니다.

728x90

댓글