Android入門之Fragment嵌套Fragment的用法詳解
從現(xiàn)實(shí)需求來(lái)看場(chǎng)景
我們經(jīng)常會(huì)在現(xiàn)實(shí)需求中碰到這樣的場(chǎng)景,如下圖所示。
一個(gè)手機(jī)APP的首頁(yè),一般在布局時(shí)會(huì)有:
- 永久固定區(qū);
- 一級(jí)聯(lián)動(dòng)區(qū);
- 二級(jí)(多級(jí))聯(lián)動(dòng)區(qū);
如果是一級(jí)聯(lián)動(dòng)區(qū)域,它跟隨著固定區(qū)域的功能按鈕點(diǎn)擊而不斷變化這個(gè)還好理解一些。煩是煩在二級(jí)(甚至多級(jí)聯(lián)動(dòng))如我圖中所標(biāo)出的深藍(lán)色部分,深藍(lán)色部分有一排功能按鈕,然后當(dāng)用戶在點(diǎn)擊這些按鈕時(shí)下部的Fragment也在跟隨著頂部的功能按鈕(頁(yè)簽)的點(diǎn)而變化著不同的內(nèi)容。
而。。。更復(fù)雜的是每一個(gè)頁(yè)簽的點(diǎn)擊時(shí),在本Fragment里還有二級(jí)按鈕(圓型),而在點(diǎn)擊這些二級(jí)按鈕時(shí),本身內(nèi)部還有一堆孫子Fragment的內(nèi)容也在發(fā)生著變化。
我們來(lái)看一個(gè)實(shí)際生產(chǎn)界面的例子你們就可以感受到上述我描述的場(chǎng)景了。
這邊頂部的按鈕為一級(jí)Fragment,它跟隨著下部的按鈕聯(lián)動(dòng)。
而這邊用紅色方框框起來(lái)的區(qū)域就是我說(shuō)的,它需要被嵌在一級(jí)Fragment里的。
比如說(shuō)點(diǎn)擊“排行榜”下部顯示的內(nèi)容和點(diǎn)擊“推薦”是完全不一樣的。
現(xiàn)在再來(lái)看一塊子區(qū)域:下部的“擼寵吸寵”,這部分也竟然被業(yè)務(wù)提出了要可以切換比如說(shuō)有一個(gè)按鈕叫“換一批”的需求。因此,這邊又是一個(gè)個(gè)的“三行四列”,“單行三列”,“2行單列”的孫子fragment。
Fragment的嵌套
首先我們說(shuō)嵌套Fragment調(diào)用這種用法是合理的,也是存在的。在現(xiàn)實(shí)中應(yīng)用到的場(chǎng)景實(shí)在是太多太多。問(wèn)題是很多初學(xué)者在使用時(shí),就直接在Fragment嵌套時(shí)當(dāng)Fragment應(yīng)用在Activity里一樣那樣用了。甚至運(yùn)行時(shí)由于Log輸出過(guò)多疏忽了一些報(bào)錯(cuò),結(jié)果呢在有些開發(fā)機(jī)上運(yùn)行的好好的而實(shí)際在一些真機(jī)上或者是換了一臺(tái)開發(fā)機(jī)如:windows換mac或者是mac換windows后,報(bào)了一堆本來(lái)不會(huì)報(bào)的錯(cuò)而根本無(wú)從入手。
這就是Fragment沒有完全學(xué)好其原理,特別是其生命周期。所以這邊我們給出正確的Fragment嵌套的用法。
就拿上例來(lái)說(shuō),我們外層有一個(gè)fg_content.xml,在fg_content.xml里我們嵌了多個(gè)孫子Fragment。此處:
- pet_the_cat(擼貓)
- must_read_list(必讀)
- recommend_item_list(推薦)
以及后面我們還會(huì)增加一些孫子Fragment,它們都從屬于fg_content.xml。
來(lái)看下面代碼。
fg_content.xml
<?xml version="1.0" encoding="utf-8"?> <layout 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"> <!--綁定數(shù)據(jù)--> <data> <variable name="viewModel" type="com.mkyuan.aset.mall.android.home.HomeContentViewModel" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/bg_white" android:orientation="vertical" android:clipChildren="false" android:showDividers="end"> <com.google.android.material.tabs.TabLayout android:id="@+id/tl" android:layout_width="match_parent" android:layout_height="30dp" android:background="@color/white" app:tabIndicatorColor="@color/tab_indicator_color" app:tabMaxWidth="200dp" app:tabMinWidth="100dp" app:tabMode="scrollable" app:tabSelectedTextColor="@color/black" app:tabTextAppearance="@style/MyCustomTabText" app:tabTextColor="@color/black" /> <com.youth.banner.Banner android:id="@+id/ad_banner" android:layout_width="match_parent" android:layout_height="100dp" android:gravity="center" app:banner_loop_time="2000" app:banner_radius="10dp" /> <FrameLayout android:id="@+id/fg_recommend" android:layout_width="match_parent" android:layout_height="80dp" android:layout_gravity="center_horizontal" android:layout_marginTop="5dp" /> <ImageView android:layout_width="match_parent" android:layout_height="1dp" android:background="#ECECEC" /> <LinearLayout android:layout_width="match_parent" android:layout_height="30dp" android:background="@drawable/layout_gray_background" android:orientation="horizontal"> <ImageView android:layout_width="24dp" android:layout_height="24dp" android:layout_gravity="top" android:scaleType="fitStart" android:src="@mipmap/newest_1"></ImageView> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="top" android:layout_marginLeft="10dp" android:includeFontPadding="false" android:text="同人活動(dòng)最新點(diǎn)亮詞條:[魔道祖師]" android:textColor="@color/black" /> </LinearLayout> <androidx.viewpager.widget.ViewPager android:id="@+id/vpMustRead" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:layout_width="300dp" android:layout_height="200dp" android:layout_gravity="top" android:clipChildren="false"> </androidx.viewpager.widget.ViewPager> <FrameLayout android:id="@+id/fg_nearbystore" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="5dp" /> <FrameLayout android:id="@+id/fg_petthecat" android:layout_width="match_parent" android:layout_height="150dp" android:layout_gravity="center_horizontal" android:layout_marginTop="5dp" /> </LinearLayout> </layout>
注意此處的:<FrameLayout android:id="@+id/fg_petthecat"這邊就是用來(lái)顯示孫子Fragment-pet_the_cat.xml的。
于是我們來(lái)看pet_the_cat.xml。
pet_the_cat.xml
它是用一個(gè)Fragment來(lái)加載的。
先來(lái)看它的前端layout。
pet_the_cat.xml的layout
<?xml version="1.0" encoding="utf-8"?> <layout 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"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:padding="0dp" android:text="擼寵吸寵" android:textColor="@color/black" android:textSize="14dp" android:textStyle="bold" /> <GridView android:id="@+id/grid_petthecat" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:horizontalSpacing="5px" android:numColumns="3" android:stretchMode="columnWidth" android:verticalSpacing="5px" /> </LinearLayout> </layout>
而這個(gè)pet_the_cat里要用到Adapter即擼寵吸寵的“具體內(nèi)容了”。我們下面順便再來(lái)看pet_cat_detail.xml
pet_cat_detail.xml
<?xml version="1.0" encoding="utf-8"?> <layout 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"> <data> <variable name="petCatBean" type="com.mkyuan.aset.mall.android.home.petthecat.PetTheCatBean"/> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ImageView android:id="@+id/ivPetCatImg" android:layout_width="90dp" android:layout_height="90dp" android:layout_gravity="center" android:scaleType="fitStart" app:petImgUrl="@{petCatBean.pegImg}" /> <TextView android:id="@+id/tvPetCatDescr" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="top" android:includeFontPadding="false" android:padding="0dp" android:text="@{petCatBean.descrText}" android:textColor="@color/black" android:textSize="14dp" android:textStyle="bold" /> <TextView android:id="@+id/tvPetCatPrice" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="top" android:includeFontPadding="false" android:padding="0dp" android:text="@{petCatBean.price}" android:textColor="@color/custom_red" android:textSize="12dp" android:textStyle="bold" /> </LinearLayout> </layout>
知道了樣式文件后關(guān)鍵我們來(lái)看在fg_content里如何套入這個(gè)pet_the_cat的layout的。
pet_the_cat的后端代碼-FragmentPetTheCat.java
package com.mkyuan.aset.mall.android.home.petthecat; import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.GridView; import androidx.databinding.DataBindingUtil; import androidx.fragment.app.Fragment; import com.mkyuan.aset.mall.android.BR; import com.mkyuan.aset.mall.android.R; import com.mkyuan.aset.mall.android.databinding.PetTheCatBinding; import com.mkyuan.aset.mall.android.home.DatabindingGridAdapter; import com.mkyuan.aset.mall.android.util.AsetMallConstants; import java.util.ArrayList; import java.util.List; public class FragmentPetTheCat extends Fragment { protected static final String TAG = "AsetMall"; private Context ctx; //private Banner adBanner; private GridView petCatGridView; private PetTheCatBinding dataBinding; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ctx = this.getActivity(); dataBinding = DataBindingUtil.inflate(inflater, R.layout.pet_the_cat, container, false); petCatGridView = dataBinding.gridPetthecat; Log.i(TAG, ">>>>>FragmentPetTheCat->get dataBinding"); initPetTheCatDataList(); return dataBinding.getRoot(); } private void initPetTheCatDataList() { List<PetTheCatBean> list = new ArrayList<PetTheCatBean>(); list.add(new PetTheCatBean(AsetMallConstants.CDN_URL + "/img/petthecat/pet_the_cat_1.jpg", "羊陀上門擼你", "23")); list.add(new PetTheCatBean(AsetMallConstants.CDN_URL + "/img/petthecat/pet_the_cat_2.jpg", "吸松鼠要么?", "128")); list.add(new PetTheCatBean(AsetMallConstants.CDN_URL + "/img/petthecat/pet_the_cat_3.png", "寄養(yǎng)傻狗7天", "500")); DatabindingGridAdapter<PetTheCatBean> adapter = new DatabindingGridAdapter<PetTheCatBean>(ctx, R.layout.pet_cat_detail, list, BR.petCatBean); petCatGridView.setAdapter(adapter); } }
我們這邊可以看到,這個(gè)Fragment通過(guò)我們?cè)谥癕VVM與ListView課程內(nèi)使用到的那個(gè)“萬(wàn)能DataBinding Adapter“了。它把pet_cat_detail加載到了一個(gè)1行3列的GridView里進(jìn)行顯示。
現(xiàn)在我們就來(lái)看在fg_content里,怎么顯示這個(gè)子Fragment。
fg_content layout所屬的Fragment Java端代碼
在fg_content里加載子Fragment-FragmentPetTheCat需要注意的地方
fg_content的后端Java代碼為FragmentContent.
private FgContentBinding dataBinding; private FragmentManager fManager; private Fragment fragmentRecommend; private Fragment fragmentNearbyStore; private Fragment fragmentPetTheCat; dataBinding = DataBindingUtil.inflate(inflater, R.layout.fg_content, container, false); fManager = getChildFragmentManager(); if (fragmentPetTheCat == null) { fragmentPetTheCat = new FragmentPetTheCat(); fTransaction.add(R.id.fg_petthecat, fragmentPetTheCat); } fTransaction.show(fragmentPetTheCat); fTransaction.commit();
這邊我們可以看到有這么一行,特別關(guān)鍵,要敲黑板了:
fManager = getChildFragmentManager();而不是我們?cè)贔ragment使用那一課里使用的:fManager = getFragmentManager();。
這是因?yàn)槲覀円短鬃覨ragment,因此對(duì)于子Fragment來(lái)說(shuō)它的parent可不一樣,很多人正是在這邊煩了錯(cuò)。
接著我們回到fg_content的孫子Fragment-pet_the_cat.xml的后端代碼-FragmentPetTheCat.java 。
從FragmentPetTheCata.java里加載完數(shù)據(jù)后如何返回到FragmentContent
在FragmentPetTheCat.java的public View onCreateView最后return你必須使用以下寫法:
return dataBinding.getRoot();//這邊要用dataBind.getRoot()返回的view再返回activity,因?yàn)榇颂幏荕ainActivity
即:子Fragment向父Fragment返回view時(shí)你已經(jīng)不能再用
Android入門第47天-Fragment的基本使用中以下這樣的寫法了,是錯(cuò)誤的:
return view;
正確的寫法為:
return dataBinding.getRoot();
以上就是Android入門之Fragment嵌套Fragment的用法詳解的詳細(xì)內(nèi)容,更多關(guān)于Android Fragment嵌套Fragment的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android編程實(shí)現(xiàn)文件瀏覽功能的方法【類似于FileDialog的功能】
這篇文章主要介紹了Android編程實(shí)現(xiàn)文件瀏覽功能的方法,可實(shí)現(xiàn)類似于FileDialog的功能,涉及Android針對(duì)文件與目錄操作的相關(guān)技巧,需要的朋友可以參考下2016-11-11TextView顯示文本控件兩種方法 TextView顯示link的方法
這篇文章主要為大家詳細(xì)介紹了TextView顯示文本控件兩種方法,TextView顯示link的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08Flutter學(xué)習(xí)之SliverList和SliverGird的使用詳解
Sliver的組件一般都用在CustomScrollView中,除了SliverAppBar之外,我們還可以為CustomScrollView添加List或者Grid來(lái)實(shí)現(xiàn)更加復(fù)雜的組合效果。本文就來(lái)聊聊SliverList和SliverGird的使用吧2023-02-02深入解讀Android的Volley庫(kù)的功能結(jié)構(gòu)
這篇文章主要介紹了Android的Volley開發(fā)框架的功能結(jié)構(gòu),Volley是Android開發(fā)中網(wǎng)絡(luò)部分的一大利器,包含很多HTTP協(xié)議通信的相關(guān)操作,需要的朋友可以參考下2016-05-05Android控件之ImageView用法實(shí)例分析
這篇文章主要介紹了Android控件之ImageView用法,以實(shí)例形式較為詳細(xì)的分析了ImageView控件用于顯示圖片的使用方法,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09Android Studio 創(chuàng)建自定義控件的方法
這篇文章主要介紹了Android Studio 創(chuàng)建自定義控件的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06Android用tabhost實(shí)現(xiàn) 界面切換,每個(gè)界面為一個(gè)獨(dú)立的activity操作
這篇文章主要介紹了Android用tabhost實(shí)現(xiàn) 界面切換,每個(gè)界面為一個(gè)獨(dú)立的activity操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09Android通過(guò)交互實(shí)現(xiàn)貝塞爾曲線的繪制
本篇我們將介紹簡(jiǎn)單的交互式繪圖,通過(guò)獲取觸控位置來(lái)設(shè)定貝塞爾曲線的控制點(diǎn),從而實(shí)現(xiàn)交互式繪制曲線,感興趣的小伙伴可以了解一下2022-05-05