<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【從零開始擼一個App】Fragment和導(dǎo)航中的使用

      Fragment簡介

      Fragment自從Android 3.0引入開始,剛接觸的同學(xué)會把它與Activity的關(guān)系類比于html片段和html頁面的關(guān)系,其實是不準(zhǔn)確的。前者更多的是組件的概念,需要在運行時有一套管理機制;而后者側(cè)重于布局編寫階段,Android中復(fù)用布局我們一般使用<include layout="@layout/xxx"/>標(biāo)簽。

      Fragment實例由Activity的FragmentManager管理,其生命周期和Activity一樣,都不是由開發(fā)人員而是由系統(tǒng)維護的。自然而然的,每當(dāng)它們被重建時,系統(tǒng)只會去調(diào)用它們的無參構(gòu)造器,帶參構(gòu)造器會被無視。那如果要在它們創(chuàng)建時傳入初始化數(shù)據(jù)咋辦呢?這也是為什么會有Bundle這個玩意兒的存在,就是用于開發(fā)人員存取相關(guān)數(shù)據(jù),如下所示:

      /**
       * Use the [ThumbnailsFragment.newInstance] factory method to
       * create an instance of this fragment.
       */
      class ThumbnailsFragment() : Fragment() {
          private var albumTag: String? = null
      
          companion object {
              @JvmStatic
              fun newInstance(albumTag: String?) =
                  ThumbnailsFragment().apply {
                      arguments = Bundle().apply {
                          putString("albumTag", albumTag)
                      }
                  }
          }
      
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              arguments?.let {
                  albumTag = it.getString("albumTag")
              }
          }
          
          /*other code*/
      }
      

      arguments由FragmentManager維護(跨fragment生命周期),可參看Android解惑 - 為什么要用Fragment.setArguments(Bundle bundle)來傳遞參數(shù)

      底部導(dǎo)航欄切換Fragment

      效果如下

      BottomNavigationView

      底部是BottomNavigationView組件,各個菜單在另外xml中定義,然后通過app:menu="xxx"指定。此處菜單定義如下

      <?xml version="1.0" encoding="utf-8"?>
      <menu xmlns:android="http://schemas.android.com/apk/res/android">
      
          <item
              android:id="@+id/navigation_home"
              android:icon="@drawable/ic_home_black_24dp"
              android:title="@string/title_home" />
      
          <item
              android:id="@+id/navigation_dashboard"
              android:icon="@drawable/ic_dashboard_black_24dp"
              android:title="@string/title_dashboard" />
      
          <item
              android:id="@+id/navigation_notifications"
              android:icon="@drawable/ic_notifications_black_24dp"
              android:title="@string/title_notifications" />
      
      </menu>
      

      然后在代碼中設(shè)置BottomNavigationView.setOnNavigationItemSelectedListener,判斷當(dāng)前選中的菜單項,手動切換Fragment,需要用到FragmentTransaction。如下示例

          override fun onClick(view: View?) {
              val trans = activity.supportFragmentManager.beginTransaction()
              val fragments = activity.supportFragmentManager.fragments
              fragments.forEach {
                  if (it.isVisible) {
                      trans.hide(it) //隱藏當(dāng)前顯示的fragment
                  }
              }
              val tag = (view as TextView).text.toString()
              val thumbnailsFragment = ThumbnailsFragment.newInstance(tag)
              //fragment_main_container就是居中的那塊區(qū)域,用于顯示各個fragment
              trans.add(R.id.fragment_main_container, thumbnailsFragment, tag)
              trans.show(thumbnailsFragment)
              trans.addToBackStack(null) //將本次操作入棧
              trans.commitAllowingStateLoss() //提交
          }
      

      注意addToBackStack方法,該方法是為了實現(xiàn)回退時——用戶按返回按鈕或程序執(zhí)行回退(配合popBackStack)——界面能返回到本次操作前的狀態(tài)。也可指定tag,在跨[多次]操作回退時有用。注意此處入棧的是操作信息,而非fragment。

      BottomNavigationView也可搭配ViewPager使用,但回退操作依然需要另外實現(xiàn)。

      上述手動控制Fragment的切換太麻煩。2018 I/O大會上,Google隆重推出一個新的架構(gòu)組件:Navigation。它提供了多Fragment之間的轉(zhuǎn)場、棧管理。在抽屜式/底部/頂部導(dǎo)航欄的需求中都可以使用這個組件。

      使用:在res目錄下新建navigation文件夾,然后新建一個navigation graph設(shè)為bottom_navigation:

      <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"
          android:id="@+id/mobile_navigation"
          app:startDestination="@+id/navigation_home">
      
          <fragment
              android:id="@+id/navigation_home"
              android:name="com.eixout.presearchapplication.ui.home.HomeFragment"
              android:label="@string/title_home"
              tools:layout="@layout/fragment_home" />
      
          <fragment
              android:id="@+id/navigation_dashboard"
              android:name="com.eixout.presearchapplication.ui.dashboard.DashboardFragment"
              android:label="@string/title_dashboard"
              tools:layout="@layout/fragment_dashboard" />
      
          <fragment
              android:id="@+id/navigation_notifications"
              android:name="com.eixout.presearchapplication.ui.notifications.NotificationsFragment"
              android:label="@string/title_notifications"
              tools:layout="@layout/fragment_notifications" />
      </navigation>
      

      注意每個fragment的id要和之前定義的menu的id保持一致。可以設(shè)置轉(zhuǎn)場動畫,還可以設(shè)置每個fragment跳轉(zhuǎn)的目標(biāo)(destination),目標(biāo)可以是 Activity或Fragment,也可以自定義。

      然后在Activity布局文件中添加一個Fragment,設(shè)置name屬性為android:name="androidx.navigation.fragment.NavHostFragment"。在傳統(tǒng)的單Activity多Fragment場景中,我們往往需要為Activity添加一個FrameLayout作為Fragment的容器。在Navigation中HavHostFragment就是Fragment的容器(HavHostFragment繼承了NavHost。The NavHost interface enables destinations to be swapped in and out.),其中設(shè)置app:navGraph="@navigation/bottom_navigation"使之與navigation graph建立聯(lián)系。

          <fragment
              android:id="@+id/nav_host_fragment"
              android:name="androidx.navigation.fragment.NavHostFragment"        
              app:defaultNavHost="true"
              app:navGraph="@navigation/bottom_navigation"
              other_config="..." />
      

      app:defaultNavHost: If set to true, the navigation host will intercept the Back button.

      最后將導(dǎo)航欄與Navigation關(guān)聯(lián)

      val navController = findNavController(R.id.nav_host_fragment)
      bottomNavigationView.setupWithNavController(navController)
      

      如此便大功告成了。

      如果不依賴導(dǎo)航欄,而是手動跳轉(zhuǎn),則可以使用NavController的相關(guān)方法,比如在Activity里navController.navigate(actionId)

      問題

      Navigation和FragmentTransaction方式最好不要同時使用,它倆的返回堆棧似乎不是同一個,回退時會有問題。不能同時使用還使得下面兩個問題不好解決。

      1. 使用Navigation,F(xiàn)ragment可以相互跳轉(zhuǎn)沒問題,但狀態(tài)丟失了。比如A下滑一定距離后跳轉(zhuǎn)到B,B回退到A,A的下滑狀態(tài)丟失,仍是從頭部開始顯示。

      2. 每次點擊BottomNavigationView的菜單項,對應(yīng)的Fragment會recreate,這其實不是我們想要的,我們預(yù)期的應(yīng)該是Fragment第一次創(chuàng)建后就一直復(fù)用,既保留了當(dāng)前狀態(tài)也不會對后端造成不必要的調(diào)用。

      如果使用FragmentTransaction很好處理,只要緩存一個Fragment集合即可(若要保留Fragment的狀態(tài),比如滑動位置,可以使用supportFragmentManager.saveFragmentInstanceState(fragment)fragment.setInitialSavedState(savedState)加載,也可以使用hide/show(fragment)的方式),但用了Navigation后就沒辦法了。可以看看Navigation, Saving fragment state評論區(qū)的吐槽,里面也有臨時的一些解決方案(不實用)。

      FragmentTransaction本身也有對狀態(tài)信息的處理考量,參看commit(), commitNow()和commitAllowingStateLoss()

      參考資料

      嵌套Fragment的使用及常見錯誤
      Fragment 生命周期和使用
      BottonNavigationView+Fragment切換toolbar標(biāo)題欄
      手把手教你使用Android官方組件Navigation
      Playing with Navigation Architecture Components
      The Navigation Architecture Component Tutorial: Getting Started
      Handle Complex Navigation Flow with Single-Activity Architecture and Android Jetpack’s Navigation component
      導(dǎo)航到目的地-popUpTo 和 popUpToInclusive
      Difference between add(), replace(), and addToBackStack()

      posted @ 2021-02-20 14:40  萊布尼茨  閱讀(2826)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 亚洲乱码国产乱码精品精大量 | 成年美女黄网站色大片免费看| 香蕉久久久久久av成人| 成人网站免费观看永久视频下载| 国产午夜91福利一区二区| 國产AV天堂| 各种少妇wbb撒尿| 国产性三级高清在线观看| 国产永久免费高清在线| 象山县| 国精品人妻无码一区免费视频电影| 99亚洲男女激情在线观看| 久久一卡二卡三卡四卡| 亚洲一久久久久久久久| 久久中文字幕一区二区| 日土县| 日韩美女一区二区三区视频| 国产精品视频午夜福利| 国产浮力第一页草草影院| 国产精品一区在线蜜臀| 国产精品点击进入在线影院高清| 美女黄18以下禁止观看| 日韩狼人精品在线观看| 人妻夜夜爽天天爽三区丁香花 | 亚洲日本韩国欧美云霸高清| 色五月丁香五月综合五月4438| 香港日本三级亚洲三级| 新建县| 国产精品久久久久鬼色| 人人妻人人澡人人爽不卡视频| 蜜桃无码一区二区三区| 国产精品线在线精品| 国产成人精品无码免费看| 国色天香成人一区二区| 国产精品色一区二区三区| 精品久久久中文字幕一区| A毛片终身免费观看网站| 国产精品一区二区日韩精品| 日韩精品亚洲精品第一页| 欧美xxxxhd高清| 亚洲欧洲av人一区二区|