Android入門之Fragment嵌套Fragment的用法詳解
從現(xiàn)實需求來看場景
我們經(jīng)常會在現(xiàn)實需求中碰到這樣的場景,如下圖所示。

一個手機(jī)APP的首頁,一般在布局時會有:
- 永久固定區(qū);
- 一級聯(lián)動區(qū);
- 二級(多級)聯(lián)動區(qū);
如果是一級聯(lián)動區(qū)域,它跟隨著固定區(qū)域的功能按鈕點擊而不斷變化這個還好理解一些。煩是煩在二級(甚至多級聯(lián)動)如我圖中所標(biāo)出的深藍(lán)色部分,深藍(lán)色部分有一排功能按鈕,然后當(dāng)用戶在點擊這些按鈕時下部的Fragment也在跟隨著頂部的功能按鈕(頁簽)的點而變化著不同的內(nèi)容。
而。。。更復(fù)雜的是每一個頁簽的點擊時,在本Fragment里還有二級按鈕(圓型),而在點擊這些二級按鈕時,本身內(nèi)部還有一堆孫子Fragment的內(nèi)容也在發(fā)生著變化。
我們來看一個實際生產(chǎn)界面的例子你們就可以感受到上述我描述的場景了。

這邊頂部的按鈕為一級Fragment,它跟隨著下部的按鈕聯(lián)動。
而這邊用紅色方框框起來的區(qū)域就是我說的,它需要被嵌在一級Fragment里的。
比如說點擊“排行榜”下部顯示的內(nèi)容和點擊“推薦”是完全不一樣的。
現(xiàn)在再來看一塊子區(qū)域:下部的“擼寵吸寵”,這部分也竟然被業(yè)務(wù)提出了要可以切換比如說有一個按鈕叫“換一批”的需求。因此,這邊又是一個個的“三行四列”,“單行三列”,“2行單列”的孫子fragment。

Fragment的嵌套
首先我們說嵌套Fragment調(diào)用這種用法是合理的,也是存在的。在現(xiàn)實中應(yīng)用到的場景實在是太多太多。問題是很多初學(xué)者在使用時,就直接在Fragment嵌套時當(dāng)Fragment應(yīng)用在Activity里一樣那樣用了。甚至運行時由于Log輸出過多疏忽了一些報錯,結(jié)果呢在有些開發(fā)機(jī)上運行的好好的而實際在一些真機(jī)上或者是換了一臺開發(fā)機(jī)如:windows換mac或者是mac換windows后,報了一堆本來不會報的錯而根本無從入手。
這就是Fragment沒有完全學(xué)好其原理,特別是其生命周期。所以這邊我們給出正確的Fragment嵌套的用法。

就拿上例來說,我們外層有一個fg_content.xml,在fg_content.xml里我們嵌了多個孫子Fragment。此處:
- pet_the_cat(擼貓)
- must_read_list(必讀)
- recommend_item_list(推薦)
以及后面我們還會增加一些孫子Fragment,它們都從屬于fg_content.xml。
來看下面代碼。
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="同人活動最新點亮詞條:[魔道祖師]"
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"這邊就是用來顯示孫子Fragment-pet_the_cat.xml的。
于是我們來看pet_the_cat.xml。
pet_the_cat.xml
它是用一個Fragment來加載的。
先來看它的前端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>而這個pet_the_cat里要用到Adapter即擼寵吸寵的“具體內(nè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)鍵我們來看在fg_content里如何套入這個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);
}
}我們這邊可以看到,這個Fragment通過我們在之前MVVM與ListView課程內(nèi)使用到的那個“萬能DataBinding Adapter“了。它把pet_cat_detail加載到了一個1行3列的GridView里進(jìn)行顯示。
現(xiàn)在我們就來看在fg_content里,怎么顯示這個子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();而不是我們在Fragment使用那一課里使用的:fManager = getFragmentManager();。
這是因為我們要嵌套子Fragment,因此對于子Fragment來說它的parent可不一樣,很多人正是在這邊煩了錯。
接著我們回到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,因為此處非MainActivity
即:子Fragment向父Fragment返回view時你已經(jīng)不能再用
Android入門第47天-Fragment的基本使用中以下這樣的寫法了,是錯誤的:
return view;
正確的寫法為:
return dataBinding.getRoot();
以上就是Android入門之Fragment嵌套Fragment的用法詳解的詳細(xì)內(nèi)容,更多關(guān)于Android Fragment嵌套Fragment的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android中Glide加載圖片并實現(xiàn)圖片緩存
本篇文章主要介紹了Android中Glide加載圖片并實現(xiàn)圖片緩存,這里和大家簡單的分享一下Glide的使用方法以及緩存 ,有興趣的可以了解一下。2017-03-03
Android實現(xiàn)仿網(wǎng)易新聞的頂部導(dǎo)航指示器
這篇文章主要介紹了Android實現(xiàn)仿網(wǎng)易新聞的頂部導(dǎo)航指示器的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-08-08
Android設(shè)置PreferenceCategory背景顏色的方法
這篇文章主要介紹了Android設(shè)置PreferenceCategory背景顏色的方法,涉及Android設(shè)置背景色的技巧,需要的朋友可以參考下2015-05-05
Flutter?Animation實現(xiàn)縮放和滑動動畫效果
這篇文章主要為大家詳細(xì)介紹了Flutter?Animation實現(xiàn)縮放和滑動動畫效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03
Flutter持久化存儲之?dāng)?shù)據(jù)庫存儲(sqflite)詳解
這篇文章主要給大家介紹了關(guān)于Flutter持久化存儲之?dāng)?shù)據(jù)庫存儲的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者使用Flutter具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03
android使用DataBinding來設(shè)置空狀態(tài)
本篇文章主要介紹了android使用DataBinding來設(shè)置空狀態(tài),具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-03-03
Flutter進(jìn)階之實現(xiàn)動畫效果(五)
這篇文章主要為大家詳細(xì)介紹了Flutter進(jìn)階之實現(xiàn)動畫效果的第五篇,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-08-08
安卓(Android)聊天機(jī)器人實現(xiàn)代碼分享
這是一個安卓智能聊天機(jī)器人的源碼,采用了仿微信的風(fēng)格設(shè)計,調(diào)用的是圖靈機(jī)器人的API,能夠?qū)崿F(xiàn)智能聊天、講故事、講笑話、查天氣、查公交等豐富的功能2015-11-11

