Android

AAC : navigation

Machine_웅 2022. 2. 21. 15:56
728x90
반응형

1. gradle ( Module ) 에 종속 항목 추가 

dependencies {
  def nav_version = "2.4.0"

  // Java language implementation
  implementation "androidx.navigation:navigation-fragment:$nav_version"
  implementation "androidx.navigation:navigation-ui:$nav_version"

  // Kotlin
  implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
  implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

  // Feature module Support
  implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"

  // Testing Navigation
  androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"

  // Jetpack Compose Integration
  implementation "androidx.navigation:navigation-compose:2.5.0-alpha01"
}




2. res 에 네비 그래프 생성
Project 창에서 res 디렉터리를 마우스 오른쪽 버튼으로 클릭하고
 New > Android Resource File을 선택합니다. New Resource File 대화상자가 나타납니다.

File name 필드에 'nav_graph'와 같은 이름을 입력합니다.

Resource type 드롭다운 목록에서 Navigation을 선택하고 OK를 클릭합니다.

3. 엑티비티에 NavHost 추가
탐색 호스트는 NavHost에서 파생되어야 합니다. 
탐색 구성요소의 기본 NavHost 구현인 NavHostFragment는 프래그먼트 대상의 교체를 처리합니다.


다음 내용을 참고하세요.

android:name 속성은 NavHost 구현의 클래스 이름을 포함합니다.
app:navGraph 속성은 NavHostFragment를 탐색 그래프와 연결합니다. 탐색 그래프는 사용자가 이동할 수 있는 이 NavHostFragment의 모든 대상을 지정합니다.
app:defaultNavHost="true" 속성을 사용하면 NavHostFragment가 시스템 뒤로 버튼을 가로챕니다. 하나의 NavHost만 기본값으로 지정할 수 있습니다. 동일한 레이아웃에 여러 호스트가 있다면(예: 창이 2개인 레이아웃) 한 호스트만 기본 NavHost로 지정해야 합니다.
또한 다음과 같은 방법으로 Layout Editor를 사용하여 NavHostFragment를 활동에 추가할 수 있습니다.

프로젝트 파일 목록에서 활동의 레이아웃 XML 파일을 더블클릭하여 Layout Editor에서 엽니다.
Palette 창 내에서 Containers 카테고리를 선택하거나 'NavHostFragment'를 검색합니다.
활동으로 NavHostFragment 뷰를 드래그합니다.
다음으로, 표시되는 Navigation Graphs 대화상자에서 대응하는 탐색 그래프를 선택하여 이 NavHostFragment와 연결하고 OK를 클릭합니다.


4. 네비 그래프에 대상을 추가 
탐색 편집기에서 New Destination 아이콘 을 클릭한 다음 Create new destination을 클릭합니다.

New Android Component 대화상자가 표시되면 프래그먼트를 만듭니다. 
프래그먼트에 관한 자세한 내용은 프래그먼트 문서를 참조하세요.

- Create new Destination 으로 프래그먼트 추가 


 

5.  대상의 구성 요소 

대상을 클릭하여 선택하고 Attributes 패널에서 다음 속성을 확인합니다.

  • Type 필드는 대상이 소스 코드에서 프래그먼트, 활동 또는 기타 맞춤 클래스로 구현되는지 여부를 나타냅니다.
  • Label 필드는 사용자가 읽을 수 있는 대상 이름을 포함합니다. NavGraph setupWithNavController()를 사용하여 Toolbar에 연결한 경우와 같이 UI에 이 필드 값이 표시될 수 있습니다. 이런 이유로 이 값에 리소스 문자열을 사용하는 것이 좋습니다.
  • ID 필드에는 코드에서 대상을 참조하는 데 사용되는 대상의 ID가 포함됩니다.
  • Class 드롭다운에는 대상과 연결된 클래스의 이름이 표시됩니다. 이 드롭다운을 클릭하면 연결된 클래스를 다른 대상 유형으로 변경할 수 있습니다.

Text 탭을 클릭하면 탐색 그래프의 XML 뷰를 확인할 수 있습니다. XML에는 아래와 같이 대상의 id, name, label  layout 속성이 포함되어 있습니다.

 

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    app:startDestination="@id/blankFragment">
    <fragment
        android:id="@+id/blankFragment"
        android:name="com.example.cashdog.cashdog.BlankFragment"
        android:label="@string/label_blank"
        tools:layout="@layout/fragment_blank" />
</navigation>

 

6. 시작 대상으로 화면 지정

  1. Design 탭에서 대상을 클릭하여 강조표시합니다.
  2. Assign start destination 버튼 을 클릭합니다. 또는 대상을 마우스 오른쪽 버튼으로 클릭하고 Set as Start Destination을 클릭합니다.

7. 대상으로 이동

 

대상으로 이동하는 것은 NavController 객체를 사용하여 실행되며 이 객체는 NavHost 내에서 앱 탐색을 관리합니다. 각 NavHost에는 해당하는 자체 NavController가 있습니다. 다음 메서드 중 하나를 사용하여 NavController를 검색할 수 있습니다.

Kotlin:

자바:

FragmentContainerView를 사용하여 NavHostFragment를 만들 때 또는 FragmentTransaction을 통해 NavHostFragment를 활동에 수동으로 추가할 경우 Navigation.findNavController(Activity, @IdRes int)를 통해 활동의 onCreate()에서 NavController를 검색하려고 하면 실패합니다. 대신 NavHostFragment에서 직접 NavController를 검색해야 합니다.

 

 

val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController


NavHostFragment navHostFragment =
        (NavHostFragment) supportFragmentManager.findFragmentById(R.id.nav_host_fragment);
NavController navController = navHostFragment.getNavController();

 

 

Safe Args를 사용하여 유형 안전성 보장

대상 간 이동을 위해 Safe Args Gradle 플러그인을 사용하는 것이 좋습니다.

이 플러그인은 대상 간 유형 안전 탐색 및 인수 전달을 사용 설정하는 간단한 객체 및 빌더 클래스를 생성합니다.

 

buildscript {
    repositories {
        google()
    }
    dependencies {
        def nav_version = "2.4.0"
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
    }
}

 

plugins {
  id 'androidx.navigation.safeargs'
}

 

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

AndroidX로 이전에 따라 gradle.properties 파일 android.useAndroidX=true가 있어야 합니다.

 

override fun onClick(view: View) {
    val action =
        SpecifyAmountFragmentDirections
            .actionSpecifyAmountFragmentToConfirmationFragment()
    view.findNavController().navigate(action)
}



@Override
public void onClick(View view) {
    NavDirections action =
        SpecifyAmountFragmentDirections
            .actionSpecifyAmountFragmentToConfirmationFragment();
    Navigation.findNavController(view).navigate(action);
}

 

 

 

이동 관련 

  //  뒤로가기   
              findNavController().navigateUp()
              findNavController().popBackStack()
              
  // 뒤로가면서 특정 페이지로 가기             
               findNavController().popBackStack(R.id.main_fragment, false)

 

이전의 (바로아래의 ) Destination(Fragment)가 호출된다.  (NavController.navigateUp() or NavController.popBackStack())

 

 

 

popUpTo 및 popUpToInclusive

app:popUpTo=Destination(Fragment)을 추가하면, 특정 Destination(Fragment)로 Pop하도록 Navigation에서 처리한다. 

또한 app:popUpToInclusive="true" 추가시, app:popUpTo에 지정된  Destination(Fragment)이 백스택에서도 제거된다. 

 

 

// 데이터 전달하면서 이동하기

// 전달하기
val bundle = bundleOf("clickData" to "data") // 데이터를 담는다 ( key value 형태 )
findNavController()
   .navigate(R.id.action_main_fragment_to_questBoardMain_fragment,bundle) // 여기에 담은 번들을 넣는다.
           
           
// 받기           
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
           var param1 = it.getSerializable("clickData") as String?
        }
}

 

 

Android) Navigation을 사용해 startActivityForResult 구현하기

출처: https://yoon-dailylife.tistory.com/88 [알면 쓸모있는 개발 지식]

fun Fragment.getNavigationResult(key: String = "result") = findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<String>(key) 
fun Fragment.setNavigationResult(result: String, key: String = "result") { findNavController().previousBackStackEntry?.savedStateHandle?.set(key, result) }

출처: https://yoon-dailylife.tistory.com/88 [알면 쓸모있는 개발 지식]

적용 예시

  override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        var view = inflater.inflate(R.layout.fragment_set_quset_fragment, container, false)

        var test = getNavigationResult()
        return view
    }
    
fun Fragment.getNavigationResult(key: String = "result") = findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<String>(key)
   fun initView(view:View){
        btn_test = view.findViewById(R.id.btn_test)
        btn_test.setOnClickListener{
            setNavigationResult("testReturn")
            findNavController().navigateUp()
        }
    }

    fun Fragment.setNavigationResult(result: String, key: String = "result") { findNavController().previousBackStackEntry?.savedStateHandle?.set(key, result) }

 

 

반응형

 

 

 

변형

  override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        var view = inflater.inflate(R.layout.fragment_set_quset_fragment, container, false)


        var test = getNavigationResult("result")
        Log.d("WLOG", "test : " + test!!.value.toString());
        
        var test2 : MutableLiveData<Any>? = getNavigationResult("listResult")
        var tmp : MutableList<String>? = test2?.value as MutableList<String> ?
        Log.d("WLOG", "test2 : " + tmp?.size);

        return view
    }
    
    
    fun Fragment.getNavigationResult(key : String): MutableLiveData<Any>? {
        return findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<Any>(key)
    }
 fun initView(view:View){
        btn_test = view.findViewById(R.id.btn_test)
        btn_test.setOnClickListener{
            setNavigationResult("testReturn","result")
            findNavController().navigateUp()
        }

        btn_test2 = view.findViewById(R.id.btn_test2)
        btn_test2.setOnClickListener {
           var test : MutableList<String> = mutableListOf("test","test1","test2")
            setNavigationResult(test,"listResult")
            findNavController().navigateUp()
        }
    }
    
     fun Fragment.setNavigationResult(result: Any, key:String){
        findNavController().previousBackStackEntry?.savedStateHandle?.set(key, result)
    }

 

728x90
반응형

'Android' 카테고리의 다른 글

android 조이스틱  (0) 2022.03.25
(스크랩 ) android animation 종류  (0) 2022.03.02
android ISP 연동 관련  (0) 2022.01.25
안드로이드 주소록 연락처 가져오기  (0) 2021.10.08
Android 비디오 재생하기 ( VideoView)  (0) 2021.09.10