일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 프로그래머스 알고리즘
- 막내의막무가내 플러터
- 막내의 막무가내
- 막내의막무가내 코틀린
- 2022년 6월 일상
- 부스트코스
- 막내의막무가내 코볼 COBOL
- 프래그먼트
- 막무가내
- 주택가 잠실새내
- 막내의막무가내 코틀린 안드로이드
- 막내의막무가내 알고리즘
- Fragment
- 안드로이드
- 부스트코스에이스
- 막내의막무가내 안드로이드 코틀린
- 막내의막무가내 SQL
- 안드로이드 sunflower
- 막내의막무가내 프로그래밍
- 안드로이드 Sunflower 스터디
- 막내의막무가내 플러터 flutter
- 주엽역 생활맥주
- 막내의막무가내 rxjava
- 막내의막무가내
- 막내의막무가내 목표 및 회고
- 막내의 막무가내 알고리즘
- flutter network call
- 막내의막무가내 안드로이드 에러 해결
- 막내의막무가내 안드로이드
- 막내의막무가내 일상
- Today
- Total
막내의 막무가내 프로그래밍 & 일상
[안드로이드] Jetpack Navigation Fragment to Fragment direction (젯팩 네비게이션 프래그먼트 화면 전환) + 값 주고받는 방법 본문
[안드로이드] Jetpack Navigation Fragment to Fragment direction (젯팩 네비게이션 프래그먼트 화면 전환) + 값 주고받는 방법
막무가내막내 2020. 6. 26. 17:49
[2021-04-13 업데이트]
이전에 Jetpack Navigation에 이어서 <action> 태그를 사용하여 프래그먼트끼리 화면전환하는 것을 프로젝트에 적용해봤습니다.
먼저 원리 및 <태그> 등 자세한 설명은 제가 쓰지 않고 밑 사이트들에 잘나와있으므로 참고용으로 남깁니다.
https://developer.android.com/guide/navigation/navigation-navigate?hl=ko
https://developer.android.com/guide/navigation/navigation-getting-started
https://beomseok95.tistory.com/190
https://brunch.co.kr/@oemilk/210
[1. gradle 추가]
app 수준 gradle
// navigation
implementation 'androidx.navigation:navigation-fragment-ktx:2.2.2'
implementation 'androidx.navigation:navigation-ui-ktx:2.2.2'
apply plugin: 'kotlin-kapt'
apply plugin: "androidx.navigation.safeargs"
맨 밑에거 추가(project 수준 gradle)
dependencies {
classpath 'com.android.tools.build:gradle:3.6.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.2.0'
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.0-rc01"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
[2. Fragment 생성]
전 바텀네비게이션이 적용된 상태에서 바텀네비게이션에 종속되어있는 프래그먼트에서 다른 프래그먼트를 띄워줄 용도로 사용했습니다.
HomeFragment -> SearchFragment 로 이동할 것 입니다.
HomeFragment 입니다.
package com.mtjin.nomoneytrip.views.home
import androidx.lifecycle.Observer
import androidx.navigation.NavDirections
import androidx.navigation.fragment.findNavController
import com.mtjin.nomoneytrip.R
import com.mtjin.nomoneytrip.base.BaseFragment
import com.mtjin.nomoneytrip.databinding.FragmentHomeBinding
import org.koin.androidx.viewmodel.ext.android.viewModel
class HomeFragment : BaseFragment<FragmentHomeBinding>(R.layout.fragment_home) {
private val viewModel: HomeViewModel by viewModel()
override fun init() {
binding.vm = viewModel
initViewModelCallback()
}
private fun initViewModelCallback() {
with(viewModel) {
goSearch.observe(this@HomeFragment, Observer {
val direction: NavDirections =
HomeFragmentDirections.actionBottomNav1ToSearchFragment()
findNavController().navigate(direction)
})
}
}
}
SearchFragment 입니다.
package com.mtjin.nomoneytrip.views.search
import com.mtjin.nomoneytrip.R
import com.mtjin.nomoneytrip.base.BaseFragment
import com.mtjin.nomoneytrip.databinding.FragmentSearchBinding
class SearchFragment : BaseFragment<FragmentSearchBinding>(R.layout.fragment_search) {
override fun init() {
}
}
[3. 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"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="@id/bottom_nav_1">
<fragment
android:id="@+id/bottom_nav_1"
android:name="com.mtjin.nomoneytrip.views.home.HomeFragment"
android:label="BottomNavFragment1"
tools:layout="@layout/fragment_home">
<action
android:id="@+id/action_bottom_nav_1_to_search_fragment"
app:destination="@id/search_fragment"
app:launchSingleTop="true" />
</fragment>
<fragment
android:id="@+id/bottom_nav_2"
android:name="com.mtjin.nomoneytrip.views.community.CommunityFragment"
android:label="BottomNavFragment2"
tools:layout="@layout/fragment_community" />
<fragment
android:id="@+id/bottom_nav_3"
android:name="com.mtjin.nomoneytrip.views.ticketoff.TicketOffFragment"
android:label="BottomNavFragment3"
tools:layout="@layout/fragment_ticket_off" />
<fragment
android:id="@+id/bottom_nav_4"
android:name="com.mtjin.nomoneytrip.views.profile.ProfileFragment"
android:label="BottomNavFragment4"
tools:layout="@layout/fragment_profile" />
<fragment
android:id="@+id/search_fragment"
android:name="com.mtjin.nomoneytrip.views.search.SearchFragment"
android:label="SearchFragment"
tools:layout="@layout/fragment_search" />
</navigation>
네비게이션에서 코드나 UI툴로 목적지를 정해주면됩니다. 인자 전달도 필요할 경우 <argument> 도 설정 가능하고 딥링크 기능도 있습니다. 이외에 다양한 옵션도(global , 백스택 등) 설정가능한데 해당 부분들은 맨위의 참고사이트에 가면 볼 수 있습니다.
저는 일단 프래그먼트 전환용으로만 사용했으므로 <action> 태그만 설정했고 singleTop 을 설정해주었습니다.
[프로젝트 진행하면서 arguments 나 global, popUpTo, popUpToIncursive, 트랜잭션애니메이션 등 다른 옵션들도 사용할텐데 지금은 사용할 이유가 없어 안했습니다. 상단 참고사이트가면 자세히 알 수 있습니다.
간단하게만 설명하면 다음과 같습니다.]
한 대상에서 다른 대상으로 이동할 때 대상을 팝하려면 app:popUpTo 속성을 연결된 <action> 요소에 추가합니다. app:popUpTo는 navigate() 호출의 일부로 백 스택에서 몇 개의 대상을 팝하도록 탐색 라이브러리에 알려줍니다. 속성값은 스택에 남아 있어야 하는 가장 최근 대상의 ID입니다.
또한, app:popUpToInclusive="true"를 포함하여 app:popUpTo에 지정된 대상이 백 스택에서 삭제될 수도 있다는 것을 나타낼 수도 있습니다.
HomeFragment -> SearchFragment
이렇게 네비게이션 설정을 하고 클린 후 빌드하면 데이터바인딩 할때처럼 다음과 같이 클래스를 자동으로 만들어줍니다. ( 꼭 빌드를 해주어야합니다 주의!!)
val direction: NavDirections =
HomeFragmentDirections.actionBottomNav1ToSearchFragment()
[4. HomeFragment에 이동하는 코드 추가]
HomeFragment 코드입니다.
navigation 설정에 의해 HomeFragmentDirections 라는 코드를 자동으로 만들어주었고 <action> 태그 아이디 값에 맞게 actionBottomNav1ToSearchFragment() 라는 메소드도 만들어주었습니다.
만약 arguments 가 있다면 매개변수를 인자로 넘깁니다. 그리고 받는쪽에서도 arguments 를 받는 코드가 있게될겁니다.
이동관련된 정보 NavDircetions 를 정했다면
findNavController().navigate(direction) 로 해당 정보를 실행합니다.
자세한 사용법은 가장 상단에 첨부한 참고사이트 참고!
package com.mtjin.nomoneytrip.views.home
import androidx.lifecycle.Observer
import androidx.navigation.NavDirections
import androidx.navigation.fragment.findNavController
import com.mtjin.nomoneytrip.R
import com.mtjin.nomoneytrip.base.BaseFragment
import com.mtjin.nomoneytrip.databinding.FragmentHomeBinding
import org.koin.androidx.viewmodel.ext.android.viewModel
class HomeFragment : BaseFragment<FragmentHomeBinding>(R.layout.fragment_home) {
private val viewModel: HomeViewModel by viewModel()
override fun init() {
binding.vm = viewModel
initViewModelCallback()
}
private fun initViewModelCallback() {
with(viewModel) {
goSearch.observe(this@HomeFragment, Observer {
val direction: NavDirections =
HomeFragmentDirections.actionBottomNav1ToSearchFragment()
findNavController().navigate(direction)
})
}
}
}
이렇게 하면 이제 프래그먼트에서 프래그먼트로 전환이 가능해집니다.
그리고 저는 goSearch 를 SingleLiveEvent를 사용하였는데 MutableLiveData 사용시 무한 옵저빙이되어 네비게이션을 활용한 프래그먼트 화면전환에 에러사항이 생길 수 있으니 주의해야합니다. (제가 그렇게 삽질했거든요..ㅋㅋㅋ)
백스택 관리와 유지보수면에서 유용한 것 같습니다 ㅎㅎ
간단하게 한 것들을 참고용으로 포스팅해보았는데요. 다른 기능 사용시 추가로 더 남겨보도록 하겠습니다.
[2020-08-29 업데이트]
추가로 프래그먼트 이동하면서 값을 주고받을때는 다음과 같이 action과 arguments 를 설정하시면 됩니다.
String 값을 주고받는 예시입니다.
<fragment
android:id="@+id/search_fragment"
android:name="com.mtjin.nomoneytrip.views.search.SearchFragment"
android:label="SearchFragment"
tools:layout="@layout/fragment_search" >
<action
android:id="@+id/action_search_fragment_to_localpage_fragment"
app:destination="@id/localpage_fragment"
app:launchSingleTop="true" />
</fragment>
<fragment
android:id="@+id/localpage_fragment"
android:name="com.mtjin.nomoneytrip.views.localpage.LocalPageFragment"
android:label="LocalPageFragment"
tools:layout="@layout/fragment_local_page" >
<argument
android:name="local"
app:argType="string" />
</fragment>
[Sender]
findNavController().navigate(
SearchFragmentDirections.actionSearchFragmentToLocalpageFragment(local)
)
[Receiver]
val safeArgs: LocalPageFragmentArgs by navArgs()
safeArgs.local
댓글과 공감은 큰 힘이 됩니다. 감사합니다!!
'안드로이드 > 코틀린 & 아키텍처 & Recent' 카테고리의 다른 글
[안드로이드] 안드로이드 ViewPager2 적용 (feat. Viewpager number indicator) (2) | 2020.06.30 |
---|---|
[안드로이드] Jetpack Navigation Fragment 전환시 BottomNavigationView 숨기는 방법 (0) | 2020.06.27 |
[안드로이드] 안드로이드 BottomNavigationView icon 설정 해결 (8) | 2020.06.26 |
[안드로이드] 안드로이드 카카오톡 로그인 구현 및 MVVM 적용 (feat. SingleLiveEvent) (0) | 2020.06.22 |
[안드로이드] ViewModel 에서 context 필요로 할 때 해결방법 (0) | 2020.06.22 |