07-碎片的使用

  • 什么是碎片

    碎片是一種可以嵌入在Activity當(dāng)中的UI片段汽抚,它能讓程序更加合理和充分的利用大屏幕空間传货。因此在平板上應(yīng)用非常廣泛柳譬。

1.碎片的簡單實用

使用碎片搭建一個簡單靜態(tài)界面

第一步:創(chuàng)建左邊碎片界面布局

添加一個水平居中的按鈕

<?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:id="@+id/left_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="LeftButton"
        />
</LinearLayout>

第二步:創(chuàng)建右邊碎片界面布局

添加一個背景顏色為綠色的布局,并加入一個標(biāo)簽

<?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"
    android:background="#00ff00">

    <TextView
        android:textSize="20sp"
        android:text="這是右邊的碎片"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>

</LinearLayout>

第三步:創(chuàng)建LeftFragment類

讓LeftFragment類繼承自support-v4庫中的Fragment類症概。

package com.example.anwser_mac.fragmenttest;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by anwser_mac on 2017/4/6.
 */

public class LeftFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //重寫onCreateView方法钢猛,然后通過infalte()方法將剛才定義的left_fragment布局加載進來
        View view = inflater.inflate(R.layout.left_fragmen, container, false);
        return view;
    }
}

第四步:創(chuàng)建RightFragment類

同第三步

package com.example.anwser_mac.fragmenttest;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by anwser_mac on 2017/4/6.
 */

public class RightFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.right_fragment, container, false);
        return view;
    }
}

第五步:修改activity_main.xml中的代碼

將創(chuàng)建的碎片,加入到界面布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/left_fragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:name="com.example.anwser_mac.fragmenttest.LeftFragment"
        android:layout_weight="1"/>

    <fragment
        android:id="@+id/right_fragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:name="com.example.anwser_mac.fragmenttest.RightFragment"
        android:layout_weight="1"/>

</LinearLayout>
  • 運行結(jié)果如下
2017-04-06_13-58-21.png

![Uploading 2017-04-06_17-24-28_256277.gif . . .]

2.動態(tài)添加碎片

碎片真正強大之處在于它可以在程序運行時動態(tài)地添加到活動當(dāng)中。根據(jù)具體的情況添加碎片酪耕,可以將程序界面定制得更加多樣化。

第一步:在1項目的基礎(chǔ)上再創(chuàng)建一個碎片用來切換顯示

<?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:id="@+id/another_textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textSize="20sp"
        android:text="這是右邊的另一個碎片"/>

</LinearLayout>

第二步:創(chuàng)建對應(yīng)的Fragment類

package com.example.anwser_mac.fragmenttest;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by anwser_mac on 2017/4/6.
 */

public class AnotherRightFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.another_right_fragment, container, false);
        return view;
    }
}

第三步: 修改界面布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/left_fragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:name="com.example.anwser_mac.fragmenttest.LeftFragment"
        android:layout_weight="1"/>

    <FrameLayout
        android:id="@+id/right_layout"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1">

    </FrameLayout>
</LinearLayout>

第四步:修改Activity的代碼如下

package com.example.anwser_mac.fragmenttest;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_layout);
        //給按鈕添加一個點擊事件
        Button button = (Button) findViewById(R.id.left_button);
        button.setOnClickListener(this);
        replaceFragment(new RightFragment());
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {

            case R.id.left_button:
                TextView textView = (TextView) findViewById(R.id.right_textview);
                //判斷哪個碎片需要進行切換
                if (textView != null) {
                    replaceFragment(new AnotherRightFragment());
                } else {
                    replaceFragment(new RightFragment());
                }
        }
    }

    ///切換右邊顯示的碎片
    //fragment : 要切換的碎片
    private void replaceFragment(Fragment fragment) {

        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction tansaction = fragmentManager.beginTransaction();
        tansaction.replace(R.id.right_layout, fragment);
        tansaction.commit();
    }
}

  • 運行效果如下:
2017-04-06_17-24-28.gif

綜上轨淌,動態(tài)添加碎片可以分為以下5個步驟

  1. 創(chuàng)建待添加的碎片實例迂烁。
  2. 獲取FragmentManager(在活動中可以直接通過調(diào)用getSupportFragmentManager()方法得到)
  3. 開啟一個事務(wù),通過調(diào)用beginTransaction()方法開啟递鹉。
  4. 向容器內(nèi)添加或替換碎片盟步,一般使用replace()方法實現(xiàn),需要傳入容器的id和待添加的碎片實例躏结。

3. 在碎片中模擬返回棧

在前面的練習(xí)中已經(jīng)實現(xiàn)了動態(tài)添加返回棧却盘,但是當(dāng)切換了幾次之后,按下back鍵程序會直接退出媳拴。所以如果需要給碎片提供一個返回棧的效果黄橘,需要調(diào)用FragmentTransaction中提供的addToBackStack()方法,可以用于將一個事務(wù)添加到返回棧中屈溉。

    ///切換右邊顯示的碎片
    //fragment : 要切換的碎片
    private void replaceFragment(Fragment fragment) {

        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction tansaction = fragmentManager.beginTransaction();
        tansaction.replace(R.id.right_layout, fragment);
        tansaction.addToBackStack(null);
        tansaction.commit();
    }

4.碎片和活動之間進行通信

  1. 在活動中調(diào)用碎片中的方法

    通過FragmentManager提供的findFragmentById()方法塞关,獲得碎片實例,從而調(diào)用碎片中的方法

    RightFragment rightFragment = (RightFragment) getFragmentManager().findFragmentById(R.id.right_fragment);
    
  2. 在碎片中調(diào)用活動中的方法

在碎片中可以通過調(diào)用getActivity()方法來得到和當(dāng)前碎片相關(guān)聯(lián)的活動實例

```

MainActiviy activity = (MainActivity) getActivity;


####5.碎片的生命周期
> 碎片和活動一樣都有自己的生命周期

1. **運行狀態(tài)** 

 >當(dāng)一個碎片時可見的子巾,并且它所關(guān)聯(lián)的活動正處于運行狀態(tài)時描孟,該碎片也處于運行狀態(tài)驶睦。
 
2. 暫停狀態(tài)

 > 當(dāng)一個活動進入暫停狀態(tài)時(由于另一個未沾滿屏幕的活動被添加到了棧頂),與它相關(guān)聯(lián)的可見碎片就會進入到暫停狀態(tài)匿醒。
 
3. 停止?fàn)顟B(tài)
 > 當(dāng)一個活動進入停止?fàn)顟B(tài)時场航,與它相關(guān)聯(lián)的碎片就會進入到停止?fàn)顟B(tài),通過調(diào)用FragmentTransaction的remove()廉羔、replace()方法將碎片從活動中移除溉痢;或者在事務(wù)提交前調(diào)用了addToBackStack()方法,這時的碎片也會進入到停止?fàn)顟B(tài)憋他,總的來說孩饼。進入停止?fàn)顟B(tài)的碎片對用戶來說時完全不可見的。有可能會被系統(tǒng)回收竹挡。
 
4. 銷毀狀態(tài)
 > 當(dāng)活動被銷毀時镀娶,與它相關(guān)聯(lián)的碎片就會進入到銷毀狀態(tài)【竞保或者通過調(diào)用FragmentTransaction的remove()梯码、replace()方法將碎片從活動中移除、也或者在事務(wù)提交前調(diào)用了addToBackStack()方法好啰。
 
#####5.1碎片的狀態(tài)回調(diào)

1. onAttach() 

 >當(dāng)碎片和活動建立關(guān)聯(lián)的時候調(diào)用轩娶。
2. onCreateView()
 > 為碎片創(chuàng)建視圖(加載布局)時調(diào)用
3. onActivityCreated()
 > 確保與碎片相關(guān)聯(lián)的活動一定已經(jīng)創(chuàng)建完畢的時候調(diào)用。
4. onDestroyView()
 > 當(dāng)與碎片關(guān)聯(lián)的視圖被移除的時候調(diào)用框往。
5. onDetach()
 > 當(dāng)碎片和活動解除關(guān)聯(lián)的時候調(diào)用鳄抒。
 
- 下圖展示了,添加碎片時椰弊,活動級碎片的回調(diào)順序
 
![2017-04-06_16-25-38.png](http://upload-images.jianshu.io/upload_images/2897594-d0b4537c76f4b7de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

- 》另外還有一點需要注意的是:在碎片中也
可以通過onSaveInstanceState()方法來保存數(shù)據(jù)许溅。

----

####6.動態(tài)加載布局的技巧

6.1 使用限定符 
 
 > 通常在平板中采用的是雙頁模式,在手機采用的是單頁模式秉版,限定符的作用就是系統(tǒng)根據(jù)屏幕的大小贤重,來加載不同的界面布局文件。從而達到自動分頁的效果

第一步:如下圖所示沐飘,創(chuàng)建一個根activity布局文件同名的large布局文件


![2017-04-06_17-41-38.png](http://upload-images.jianshu.io/upload_images/2897594-42a38627ff6e80d3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

第二步:寫入在平板下的布局代碼
   
   
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">

<fragment
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:name="com.example.anwser_mac.fragmenttest.LeftFragment"
    android:id="@+id/left_fragment"/>

<FrameLayout
    android:id="@+id/right_layout"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"/>

<!--<fragment-->
    <!--android:layout_width="0dp"-->
    <!--android:layout_height="match_parent"-->
    <!--android:layout_weight="1"-->
    <!--android:name="com.example.anwser_mac.fragmenttest.RightFragment"-->
    <!--android:id="@+id/right_fragment"/>-->

</LinearLayout>


第三步: 同時也要記得將原來的界面布局改為單頁的界面布局游桩。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">

<fragment
    android:id="@+id/left_fragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="com.example.anwser_mac.fragmenttest.LeftFragment"/>
    <!--android:layout_weight="1"/>-->

<!--<FrameLayout-->
    <!--android:id="@+id/right_layout"-->
    <!--android:layout_width="0dp"-->
    <!--android:layout_height="match_parent"-->
    <!--android:layout_weight="1">-->

<!--</FrameLayout>-->

</LinearLayout>

- 在不同設(shè)備下運行效果分別如下牲迫。

![
![Uploading 2017-04-06_17-34-42_845768.png . . .]
](http://upload-images.jianshu.io/upload_images/2897594-83b233c3e75f01ad.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


- 下圖是一些常見的限定符耐朴,圖片來自《第一行代碼》

![2017-04-06_17-34-42.png](http://upload-images.jianshu.io/upload_images/2897594-9d74d989ae814fda.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


6.2 使用最小寬度限定符
>最小寬度限定符允許我們對屏幕的寬度制定一個最小值(以dp為單位),然后以這個最小值為臨界點盹憎,屏幕寬度大于這個值的設(shè)備就加載一個布局筛峭。屏幕寬度小于這個值就加載另一個布局。

- 如下圖所示陪每,新建一個**layout_sw600dp**的文件影晓,在這個文件中搭建布局镰吵。也就意味著當(dāng)屏幕寬度大于600dp的時候會加載這個文件;當(dāng)屏幕小于600dp的時候默認(rèn)加載main_layout文件挂签。


![2017-04-06_17-41-38.png](http://upload-images.jianshu.io/upload_images/2897594-df915cdedfc841ed.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末疤祭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子饵婆,更是在濱河造成了極大的恐慌勺馆,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侨核,死亡現(xiàn)場離奇詭異草穆,居然都是意外死亡,警方通過查閱死者的電腦和手機搓译,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門悲柱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人些己,你說我怎么就攤上這事豌鸡。” “怎么了轴总?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵直颅,是天一觀的道長。 經(jīng)常有香客問我怀樟,道長功偿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任往堡,我火速辦了婚禮械荷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘虑灰。我一直安慰自己吨瞎,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布穆咐。 她就那樣靜靜地躺著颤诀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪对湃。 梳的紋絲不亂的頭發(fā)上崖叫,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天,我揣著相機與錄音拍柒,去河邊找鬼心傀。 笑死,一個胖子當(dāng)著我的面吹牛拆讯,可吹牛的內(nèi)容都是我干的脂男。 我是一名探鬼主播养叛,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼宰翅!你這毒婦竟也來了弃甥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤汁讼,失蹤者是張志新(化名)和其女友劉穎潘飘,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掉缺,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡卜录,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了眶明。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片艰毒。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖搜囱,靈堂內(nèi)的尸體忽然破棺而出丑瞧,到底是詐尸還是另有隱情,我是刑警寧澤蜀肘,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布绊汹,位于F島的核電站,受9級特大地震影響扮宠,放射性物質(zhì)發(fā)生泄漏西乖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一坛增、第九天 我趴在偏房一處隱蔽的房頂上張望获雕。 院中可真熱鬧,春花似錦收捣、人聲如沸届案。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽楣颠。三九已至,卻和暖如春咐蚯,著一層夾襖步出監(jiān)牢的瞬間童漩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工仓蛆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留睁冬,地道東北人挎春。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓看疙,卻偏偏與公主長得像豆拨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子能庆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容