主要是在練習:
Jetpack Navigation Component in One Video
Android Navigation 學習筆記(一) 基礎使用
整理
Navigation非常方便,所以就先嘗試一個activity,多個fragment。
popUpTo應該會常用到,目前用到就是,如果相機突然沒有相機權限,就先回到permissionsFragment要權限,取得權限後再回到相機,但是這時候相機按返回鍵又會回到permissionsFragment,所以需要:
app:popUpTo="@id/permissionsFragment"
app:popUpToInclusive="true"
帳號如果要登出,就會回到登入頁面,然後其他頁面按返回鍵,要回到桌面(關掉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
如何修改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
Avoiding Android navigation IllegalArgumentException in NavController
這個問題好像是因為按鈕連按兩次?就是重複了兩次navigate到某一個fragment
解決方法-->參考解答1:
用.currentDestination檢查現在是不是在當前fragment:
.currentDestination
fragment的setContentView:
android-fragments - Android: Fragment: setContentView的替代品
How to return to Previous Fragment by clicking back(Not Hardware back button)?
Navigation.findNavController(requireActivity(), R.id.nav_host_fragment).popBackStack()
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);
}
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。
在特定的fragment,橫豎屏問題:
解答2:
Allow rotation/landscape in one fragment
Why getContext() in fragment sometimes returns null?
Fragment: getContext vs requireContext
Handling Orientation Changes on Android
測試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)
Android Context完全解析,你所不知道的Context的各种细节