從0系統(tǒng)學(xué)Android--4.1探究碎片

從0系統(tǒng)學(xué)Android--4.1探究碎片

image

image

本系列文章目錄更多精品文章分類

本系列持續(xù)更新中.... 初級(jí)階段內(nèi)容參考《第一行代碼》

第四章:手機(jī)平板要兼顧--探究碎片

平板電腦和手機(jī)最大的區(qū)別就在于屏幕的大小,一般手機(jī)的屏幕大小會(huì)在 3 英寸到 6 英寸之間,而一般平板電腦屏幕大小會(huì)在 7 英寸到 10 英寸之間。屏幕大小差距過(guò)大會(huì)導(dǎo)致同樣的界面視覺(jué)效果有很大的差異。

為了兼顧手機(jī)和平板開(kāi)發(fā),Android 3.0 引入了碎片的概念,可以讓界面在平板上更好的展示。

4.1 碎片是什么

碎片(Fragment)是一種可以嵌入到 Activity 中的 UI 片段,讓程序更加合理和充分利用屏幕的空間。它和 Activity 很像,同樣都能包含布局,同樣有生命周期。

如何利用平板的屏幕空間呢?比如我們要開(kāi)發(fā)一個(gè)新聞?lì)惖?APP。在手機(jī)端可以是這樣的。

image

可以是如果在平板上也這樣設(shè)計(jì),那么新聞標(biāo)題列表就會(huì)給拉伸的很長(zhǎng),而新聞的標(biāo)題一般都不會(huì)太長(zhǎng),這樣設(shè)計(jì)就會(huì)導(dǎo)致頁(yè)面不合理。

image

因此,更好的設(shè)計(jì)方案是將新聞列表和新聞詳細(xì)內(nèi)容界面放到兩個(gè)碎片中,然后在同一 Activity 中引入這兩個(gè)碎片,這樣屏幕空間就充分利用起來(lái)了。

image

4.2 碎片的使用方式

首先我們先創(chuàng)建一個(gè)平板的模擬器,準(zhǔn)備好后新建一個(gè)包用于碎片化的練習(xí)。

4.2.1 碎片的簡(jiǎn)單用法

寫一個(gè)最簡(jiǎn)單的碎片示例,在一個(gè) Activity 中添加兩個(gè)碎片,并讓這兩個(gè)碎片平方 Activity 空間。

  1. 新建一個(gè)左側(cè)碎片布局 left_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        android:layout_gravity="center_horizontal"
        android:id="@+id/bt"/>
</LinearLayout>
  1. 新建一個(gè)右側(cè)碎片布局right_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FF0000"
    android:orientation="vertical">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textSize="20sp"
        android:text="This is right Fragment"/>
</LinearLayout>
  1. 新建 LeftFragment 類,讓他繼承 Fragment,F(xiàn)ragment 可能會(huì)有兩個(gè)不同的包,建議使用支持庫(kù)中的 Fragment,因?yàn)樗梢宰?Fragment 在所有的 Android 系統(tǒng)版本中保持功能一致性。比如在 Fragment 中嵌套 Fragment ,如果你使用的是系統(tǒng)內(nèi)置的 Fragment 則在 Android 4.2 系統(tǒng)之前的設(shè)備上運(yùn)行程序會(huì)崩潰。
public class LeftFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.left_fragment, container, false);
        return view;
        
    }
}
  1. 同樣的方法再創(chuàng)建一個(gè) RightFragment
public class RightFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.left_fragment, container, false);
        return view;

    }
}
  1. 修改 fragmentbaseuse_activity 代碼
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">
    <fragment
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:name="com.example.firstcode.fourth_chapter.LeftFragment"
        android:id="@+id/fg_left"/>
    <fragment
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:name="com.example.firstcode.fourth_chapter.RightFragment"
        android:id="@+id/fg_right"/>

</LinearLayout>

這里使用了 <fragment> 標(biāo)簽在布局中添加碎片,然后在標(biāo)簽中通過(guò) android:name 屬性來(lái)指明要添加的碎片的類名,注意一定要把包名加上。

運(yùn)行結(jié)果:

image

4.2.2 動(dòng)態(tài)添加碎片

在上一節(jié)中我們學(xué)習(xí)了如何在布局中添加碎片,下面我們來(lái)學(xué)習(xí)如何用代碼動(dòng)態(tài)的添加碎片。

新建一個(gè) another_right_fragment

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFF00"
    android:orientation="vertical">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textSize="20sp"
        android:text="another fragment"/>
</LinearLayout>

里面代碼基本相同,只是更該了一下背景顏色,用來(lái)區(qū)分。

再新建一個(gè) Fragement

public class AnotherRightFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.another_right_fragment, container, false);
        return view;

    }
}

修改主頁(yè)面的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">
    <fragment
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:name="com.example.firstcode.fourth_chapter.LeftFragment"
        android:id="@+id/fg_left"/>
   <!-- <fragment
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:name="com.example.firstcode.fourth_chapter.RightFragment"
        android:id="@+id/fg_right"/>-->
    <FrameLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:id="@+id/framelayout"/>

</LinearLayout>

<fragment>替換成了 FrameLayout ,F(xiàn)ragmentLayout 是 Android 中最簡(jiǎn)單的一種布局,所有的控件默認(rèn)會(huì)擺放在布局的左上角。這里僅需要放入一個(gè)碎片,不需要任何定位,因此非常適合使用 FrameLayout

下面在代碼中向 FrameLayout 中添加內(nèi)容,從而實(shí)現(xiàn)動(dòng)態(tài)添加碎片的功能。

public class FragmentBaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragmentbase);
        Button button = findViewById(R.id.bt);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                replaceFragment(new AnotherRightFragment());
            }
        });
        replaceFragment(new RightFragment());

    }

    private void replaceFragment(Fragment fragment){
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.framelayout,fragment);
        fragmentTransaction.commit();
    }
}

首先給左側(cè)碎片中的按鈕注冊(cè)了點(diǎn)擊事件,然后調(diào)用了 replaceFragment() 方法動(dòng)態(tài)的添加了 RightFragment 這個(gè)碎片。當(dāng)點(diǎn)擊左側(cè)按鈕的時(shí)候,就會(huì)觸發(fā) replaceFragment() 這個(gè)方法。

動(dòng)態(tài)添加碎片主要分為 5 步:

  1. 創(chuàng)建待添加的碎片
  2. 獲取 FrgmentManager ,FragmentManager是一個(gè)抽象類,在 Activity 中通過(guò) getSupportFragmentManager() 方法來(lái)獲取。
  3. 開(kāi)啟一個(gè)事務(wù),通過(guò)調(diào)用 beginTransaction() 方法開(kāi)啟
  4. 向容器中添加或者替換掉已經(jīng)添加的碎片,一般使用 replace() 就可以了。
  5. 提交事務(wù),調(diào)用 commit() 方法來(lái)完成。

這樣就完成了。

4.2.3 在碎片中模擬返回棧

在上一小節(jié)中已經(jīng)學(xué)習(xí)了如何動(dòng)態(tài)添加碎片,不過(guò)當(dāng)我們按下 Back 鍵程序就直接退出了,如何實(shí)現(xiàn)類似于返回棧的效果,當(dāng)按下 back 鍵的時(shí)候返回到上一個(gè)碎片呢?

FragmentTransaction 中提供了一個(gè) addToBackStack() 方法,可以用于將一個(gè)事務(wù)添加到返回棧中。

    private void replaceFragment(Fragment fragment){
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

        fragmentTransaction.replace(R.id.framelayout,fragment);
        // 可以接受一個(gè)名字用于描述返回棧的狀態(tài),一般傳入 null 即可 會(huì)將這個(gè) Fragment 添加到棧中
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();
    }

這樣再運(yùn)行程序,你會(huì)發(fā)現(xiàn)按下 Back 后程序沒(méi)有立馬退出,而是先退出了 Fragment,等 Fragment 界面也消失了,再按下 back 才會(huì)退出。

4.2.4 碎片和活動(dòng)之間進(jìn)行通信

為了方便碎片和活動(dòng)之間進(jìn)行通信,F(xiàn)ragmentManager 提供了一個(gè)類似于 findViewById() 的方法,專門用于從布局文件中獲取碎片的實(shí)例。

RightFragment rightFragment = (RightFragment)getSupportFragmentManager().findFragmentById(R.id.right_fragment)

這個(gè)方法是適用于在布局中通過(guò)<fragment>靜態(tài)添加 Fragment 的情況,如果是動(dòng)態(tài)的,就直接 new Fragment() 了。

那么如何在碎片中調(diào)用 Activity 呢?其實(shí)每個(gè)碎片中都可以通過(guò)調(diào)用 getActivity() 方法來(lái)得到和當(dāng)前碎片相關(guān)聯(lián)的 Activity 實(shí)例。

那么碎片與碎片直接如何通信呢?

思路:首先在一個(gè)碎片中可以得到與之關(guān)聯(lián)的 Activity,然后通過(guò)這個(gè) Activity 再去獲取另外一個(gè)碎片實(shí)例就可以了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本篇文章主要介紹以下幾個(gè)知識(shí)點(diǎn):碎片 fragment 的用法;碎片 fragment 的生命周期;動(dòng)態(tài)加載布局的...
    開(kāi)心wonderful閱讀 1,532評(píng)論 3 7
  • 碎片是什么 碎片 (Fragment) 是一種可以嵌入在 Activity 當(dāng)中的 UI 片段,它能讓程序更加合理...
    墨櫛楓閱讀 1,140評(píng)論 0 1
  • 平板電腦和手機(jī)最大的區(qū)別就是屏幕的大小不同,一般手機(jī)屏幕的大小會(huì)在3英寸到6英寸之間,而一般平板電腦屏幕的大小會(huì)在...
    付凱強(qiáng)閱讀 890評(píng)論 0 0
  • Fragment,翻譯為碎片、片段,Android 在 Android 3.0(API 11 )中引入了Fragm...
    RumbleTsc閱讀 3,119評(píng)論 10 52
  • 《Android Fragment完全解析,關(guān)于碎片你所需知道的一切》 我們都知道,Android上的界面展示都是...
    cxm11閱讀 2,347評(píng)論 2 19

友情鏈接更多精彩內(nèi)容