iT邦幫忙

第 11 屆 iThome 鐵人賽

1
自我挑戰組

練習程式系列 第 36

Android,Navigation

主要是在練習:
Jetpack Navigation Component in One Video
Android Navigation 學習筆記(一) 基礎使用
整理

1

Navigation非常方便,所以就先嘗試一個activity,多個fragment。
popUpTo應該會常用到,目前用到就是,如果相機突然沒有相機權限,就先回到permissionsFragment要權限,取得權限後再回到相機,但是這時候相機按返回鍵又會回到permissionsFragment,所以需要:

app:popUpTo="@id/permissionsFragment"
app:popUpToInclusive="true"

2

帳號如果要登出,就會回到登入頁面,然後其他頁面按返回鍵,要回到桌面(關掉app),不能回到原本有帳號的畫面。
使用navController,先清空Fragment(從特定的fragment),再到loginFragment(登入頁面)

var navController= findNavController(this,R.id.host_fragment)
navController.popBackStack(R.id.otherFragment, true) //從otherFragment(包含)到 當前的fragment  都會去掉 // 目前不知道,要怎麼直接全部清空,好像只能透過指定一個fragment
navController.navigate(R.id.loginFragment)

參考:How to clear navigation Stack after navigating to another fragment in Android
解答3

3

如何修改fragment的標題列(toolbar)?
在特定的fragment,改變activity的標題列(toolbar)?
參考:2 different ways to inflate menu for Toolbar inside Activity and Fragment

在Navigation,目前是一個activity,多個fragment。所以標題列的修改在MainActivity修改就好了,不用寫在個別fragement:
參考:android hide toolbar in specific fragment
解答四(不過好像只是讓toolbar消失而已,還要在試試能不能換另一個toolbar):

.addOnDestinationChangedListener

4

Avoiding Android navigation IllegalArgumentException in NavController
這個問題好像是因為按鈕連按兩次?就是重複了兩次navigate到某一個fragment
解決方法-->參考解答1:
用.currentDestination檢查現在是不是在當前fragment:

.currentDestination

5

fragment的setContentView:
android-fragments - Android: Fragment: setContentView的替代品

6

如何用一個按鈕,點擊之後,回到上一個fragment?(不是直接點手機的返回鍵)

How to return to Previous Fragment by clicking back(Not Hardware back button)?

Navigation.findNavController(requireActivity(), R.id.nav_host_fragment).popBackStack()

7

如何在Fragment使用activity的toolbar(標題列)???

toolbar(標題列)就是app最上面那塊,menu就是toolbar裡放的東西

toolbar menu item click in fragments
解答2:(後來不用 這個方法: onPrepareOptionsMenu 和 menu?.clear();。
改用-->toolbar.inflateMenu(R.menu.menu_layout ) 參考如何在Toolbar使用Menu(kotlin)How to hide NavigationIcon on toolbar)
一 fragment implements interface:

implements Toolbar.OnMenuItemClickListener

二 然後再activity修改,讓Fragment的toolbar(標題列)的畫面(menu)消失:
覆寫onPrepareOptionsMenu
使用menu?.clear();

override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
        var navController= findNavController(this,R.id.nav_host_fragment)
        //這個Listener是fragment換成另一個fragment會觸發的Listener,destination就是改變後的fragment,//所以可以在mainActivity寫這個方法,來處理像是:不同的fragment時,不同的畫面之類的
        navController.addOnDestinationChangedListener(NavController.OnDestinationChangedListener { controller, destination, arguments ->
            if (destination.id == R.id.Fragment) {
                //先清空,不然menu會一直疊加
                menu?.clear();
            }
            else {
                //先清空,不然menu會一直疊加
                menu?.clear();
                getMenuInflater().inflate(R.menu.all_menu, menu);
                //toolbar顯示畫面
                toolbar.setVisibility(View.VISIBLE)
                // toolbar點擊menu事件:
                toolbar.setOnMenuItemClickListener {
                    if (it.itemId == R.id.menu_logout) { //menu的登出按鈕
                        Toast.makeText(this, "登出", Toast.LENGTH_LONG).show()
                        navController.popBackStack(R.id.loginFragment, true)
                        navController.navigate(R.id.loginFragment)
                    }
                    true
                }
                return@OnDestinationChangedListener
            }
        })
        return super.onCreateOptionsMenu(menu);
}

後來找到:不用使用avtivity的toolbar

navigationview with different toolbar for each fragment
步驟
1 在特定fragment,也自己放一個toolbar到xml檔,
2 然後mainActivity透navController.addOnDestinationChangedListener隱藏activity的toolbar,
3 在fragment裡顯示fragment自己的toolbar。
4 特定的fragment在自己處理自己的toolbar,不用使用avtivity的toolbar。

8

在特定的fragment,橫豎屏問題:
解答2:
Allow rotation/landscape in one fragment

9

Why getContext() in fragment sometimes returns null?

Fragment: getContext vs requireContext

10

Handling Orientation Changes on Android

Fragment recreates twice

11

測試fragment生命週期:
測試:進fragment到離fragment會是:

onAttach -- > onCreate --> onCreateView -- > onViewCreated
--> onStart() -- > onResume() -- >onPause() -- >
onStop() -- >onDestroyView

因為fragment只有關掉畫面,事實上還存在 ,所以現在在另一個fragment旋轉畫面 ,會是:

onDestroy() -- > onDetach() -- >onAttach -- > onCreate

如果在原本的fragment裡 oncreate 加上 retainInstance = true ,在另一個fragment選轉畫面 ,會是(相對起來會順很多):

onDetach() -- >onAttach 

在回到原本的 fragment 會是 :

onCreateView -- > onViewCreated -- > onStart() -- >onResume()

之前會把鎖畫面寫在onCreate,是沒有用的 ,要寫在onCreateView:

requireActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
requireActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED)

單純旋轉畫面會是:

onPause() -- > onStop() -- > onDestroyView() -- >
onDestroy() -- > onDetach() -- > onAttach() - >
onCreate -- >onCreateView -- > onViewCreated -- >
onStart() -- >  onResume()

在 oncreate 寫了 retainInstance = true , 在旋轉會是(少了onDestroy()和onCreate() ) :

onPause() -- > onStop() -- > onDestroyView -- >
onDetach() -- > onAttach -- >onCreateView -- >
onViewCreated -- >  onStart() -- >  onResume()

視窗縮小:

onPause() -- > onStop() -- >onStart() -- >onResume()

關於retainInstance,不是很懂:
Understanding Fragment's setRetainInstance(boolean)

12

Android Context完全解析,你所不知道的Context的各种细节


上一篇
WEB 筆記
下一篇
C# 筆記
系列文
練習程式37
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
阿展展展
iT邦好手 1 級 ‧ 2020-02-19 22:43:28

恭喜完賽!!

謝謝

我要留言

立即登入留言