핀수로그
  • 바텀 네비게이션 추가하기, 프로토타입 만들기
    2022년 03월 20일 22시 58분 50초에 업로드 된 글입니다.
    작성자: 핀수
    728x90
    반응형

    목차

      프로토타입을 만들었다

       

      여기 에서 만들었다

      기존의 날씨와 옷차림 안내 기능과 더불어 간단한 기록을 통해서...

      나중에 요긴하게 쓸 수 있지 않을까 하는 생각에...

      (개인적인 생각으로는 '이 날씨에 이렇게 입었는데 괜찮았더라~' 하는 정도로 쓰고 싶었다.)

      간단한 기록을 남길 수 있는 기능을 추가하기로 했다.

      당연한 수순으로 화면이 늘어나고 바텀 네비게이션을 사용하기로 했다.

       

      Android BackStack

      참고 : https://medium.com/harrythegreat/android-navigation-component-%EA%B0%9C%EB%85%90%EA%B3%BC-%ED%8A%9C%ED%86%A0%EB%A6%AC%EC%96%BC-1-5ac6ac081643

       

      Android Navigation Component 개념과 튜토리얼 — 1

      Jetpack과 함께 소개된 안드로이드 네비게이션은 기존 정말 복잡하고 난해하고 코드를 스파게티로 만들어줬던 Fragment와 Activity간 구현을 심플하고 안정적으로 이동할 수 있도록 도와주는 컴포넌

      medium.com

      LIFO (Last In First Out) 구조

      시작하기

      참고한 링크 (출처)

      Android Navigation Component 개념과 튜토리얼 - 1

      • 프로젝트 수준의 bulid.gradle
      buildscript {
          repositories {
              google()
              mavenCentral()
          }
          dependencies {
              classpath "com.android.tools.build:gradle:4.2.2"
              def nav_version = "2.3.5"
              classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
          }
      }
      
      • 앱 수준의 build.gradle
      plugins {
          id 'com.android.application'
          id 'androidx.navigation.safeargs'
      }
      ...
      
      dependencies {
          ...
      
          def nav_version = "2.3.5"
          // Java language implementation
          implementation "androidx.navigation:navigation-fragment:$nav_version"
          implementation "androidx.navigation:navigation-ui:$nav_version"
          // Jetpack Compose Integration
          implementation "androidx.navigation:navigation-compose:"
          // Feature module Support
          implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"
          // Testing Navigation
          androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"
      }
      

      Fragment 만들기

      프레그먼트 세개를 만들고 화면은 TextView로 각자 이름을 적어주고 확연한 구분을 위해

      배경색을 달리해줬다.

      그리고 각 버튼을 달아주었음.

      아주 간단하게 만들었다

      Activity Navigation Controller 구현

      <androidx.appcompat.widget.LinearLayoutCompat
          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"
          android:orientation="vertical"
          tools:context=".MainActivity">
      
          <fragment
              android:id="@+id/nav_host"
              android:name="androidx.navigation.fragment.NavHostFragment"
              android:layout_width="match_parent"
              android:layout_height="0dp"
              android:layout_weight="1"
              app:defaultNavHost="true"
              app:layout_constraintEnd_toEndOf="parent"
              app:layout_constraintTop_toTopOf="parent"
              app:navGraph="@navigation/nav_main" />
      
      </androidx.appcompat.widget.LinearLayoutCompat>

      💡 android:name="androidx.navigation.fragment.NavHostFragment"

       

      • 어떤 NavHost 가 구현될지를 정의

      💡 app:defaultNavHost="true"

      • true → 현재 구현되는 Activity 에서의 뒤로 가기 버튼이 우리가 구현한 Navigation 에 맞게 동작

      Navigation 리소스 만들기

      💡 app:navGraph="@navigation/nav_main"

      • 우리가 사용할 네비게이션 리소스
      • res > navigation 폴더를 만든다.
      • New Destination 을 클릭해 fragment를 추가 해준다
      • First 위에 있는 홈 아이콘이 startDestination 을 의미

      in Java

      MainActivity.java 에는 어떤 코드도 없이 다음과 같이 구현이 가능한 것을 알 수 있다.

      public class FirstFragment extends Fragment {
          @Override
          public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                   Bundle savedInstanceState) {
              // Inflate the layout for this fragment
              View view = inflater.inflate(R.layout.fragment_first, container, false);
      
              view.findViewById(R.id.button).setOnClickListener(v->{
                  Navigation.findNavController(view).navigate(R.id.action_firstFragment_to_secondFragment);
              });
              return view;
          }
      }
      

      BottomNavigation 구현하기

      menu 생성

      <?xml version="1.0" encoding="utf-8"?>
      <menu xmlns:android="http://schemas.android.com/apk/res/android">
      
          <item
              android:id="@+id/firstFragment"
              android:icon="@drawable/ic_home"
              android:title="home"/>
      
      
          <item
              android:id="@+id/secondFragment"
              android:icon="@drawable/ic_add"
              android:title="add"/>
      
          <item
              android:id="@+id/thirdFragment"
              android:icon="@drawable/ic_search"
              android:title="search"/>
      
      </menu>

      • id 값은 각각 구현하려는 fragment 들의 id 값을 넣어주어야함
      • navigation 화면에서의 값들을 기준으로 함 (얘네와 맞춰줘야 한다는 의미인듯)

      activity_main.xml

      <?xml version="1.0" encoding="utf-8"?>
      <androidx.appcompat.widget.LinearLayoutCompat
          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"
          android:orientation="vertical"
          tools:context=".MainActivity">
      
          <fragment
              android:id="@+id/nav_host"
              android:name="androidx.navigation.fragment.NavHostFragment"
              android:layout_width="match_parent"
              android:layout_height="0dp"
              android:layout_weight="1"
              app:defaultNavHost="true"
              app:layout_constraintEnd_toEndOf="parent"
              app:layout_constraintTop_toTopOf="parent"
              app:navGraph="@navigation/nav_main" />
      
          <com.google.android.material.bottomnavigation.BottomNavigationView
              android:id="@+id/bottomNav"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              app:menu="@menu/menu_nav"/>
      
      </androidx.appcompat.widget.LinearLayoutCompat>

      Activity 세팅

      public class MainActivity extends AppCompatActivity {
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              BottomNavigationView bottomNav = findViewById(R.id.bottomNav);
      
              NavController navController = Navigation.findNavController(this, R.id.nav_host);
              NavigationUI.setupWithNavController(bottomNav, navController);
          }
      }
      

      💡 NavigationUI.setupWithNavController

      • view 와 navController 를 인자로 받아 view를 navController 에 맞게 구현해줌
      • 이 과정에서 bottomNavigation 에서 menu 값의 id와 fragment 목적지가 자동으로 맵핑 된다

      ♨︎ troubleShooting

      코틀린으로 해당 작업 진행 중 NavigationUI 는 보이지 않았다..

      그리고 당연히 해당 메소드 또한 (setupWithNavController) 별짓을 다해도 찾을 수 없었다

      implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
      

      이게 없어서...................코틀린과 자바의 괴리란.....^^............

      NavController

      • NavController 는 우리가 만든 NavGraph 에 맞게 NavHost 안이 구현되도록 도와주는 오브젝트

      버튼과 바텀 네비게이션 모두 잘 맵핑 되어 작동하는 것을 알 수 있다

      Action과 Argment

      • nav_main 으로 돌아가서 아무 프래그먼트를 클릭하면 좌측에 다음과 같은 창이 나온다

      Argments

      • 말 그대로 각각의 화면에서 인자로 받는 값
      • Array 와 Optional (Nullable) 타입 뿐 아니라 enum, Parceable 도 가능
      • 예전처럼 Bundle 에 putString, putInt 할 필요가 없다
      • 만약 스택에 쌓였던 이전 Fragment 들이 메모리에서 정리된다면
      • 인자로 받은 Argment 를 기준으로 다시 생성된다

      Actions

      • 네비게이션이 어떻게 움직일지에 대한 Action 값
      • To Destination : 현재 화면에서 다른 화면으로 이동
      • To Self : 자기 자신으로 이동
      • Return To Source : popBackstack 시 사용될 액션
      • Global : 어떤 화면에서든 현재 화면으로 이동할 때의 액션
      728x90
      반응형
      댓글