Fragment碎片的基本使用(手机平板需要更好地兼容)
碎片(Fragment)是一種可以嵌入在活動(dòng)當(dāng)中的UI片段,它能讓程序更加合理和充分地利用大屏幕的控件,因而在平板上應(yīng)用得非常廣泛。碎片其實(shí)與活動(dòng)十分相似,同樣都能包含布局,也同樣擁有著自己的生命周期。你甚至可以將碎片理解成一個(gè)迷你型的活動(dòng),雖然這個(gè)迷你型的活動(dòng)有可能和普通的活動(dòng)是一樣大的。接下來(lái)我們來(lái)了解下Fragment的具體使用。
新建一個(gè)FragmentTest項(xiàng)目,并且創(chuàng)建好一個(gè)平板模擬器,Android版本就8.0吧,雖然已經(jīng)有9.0版本了,但是我發(fā)現(xiàn)個(gè)別平板模擬器無(wú)法自適應(yīng)重力感應(yīng)。
創(chuàng)建平板的步驟:
1.點(diǎn)擊AVD Manager(AndroidVirtualDevice Manager)
2.點(diǎn)擊左下角的Create Virtual Device...
3.選擇Tablet,尺寸就選擇一個(gè)8.86寸的吧
4.下面是選擇一個(gè)Android設(shè)備的版本,這里如果你沒(méi)有就需要下載一下,我選擇的是8.1版本的
5.然后下一步下一步就創(chuàng)建好了
6.啟動(dòng)模擬器
具體請(qǐng)看圖解:
這就把Android平板模擬器給創(chuàng)建好了。
我們準(zhǔn)備先寫(xiě)一個(gè)最簡(jiǎn)單的碎片示例來(lái)練一練手,在一個(gè)活動(dòng)當(dāng)中添加兩個(gè)碎片,并且讓這兩個(gè)碎片平分活動(dòng)空間。
新建一個(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"><Buttonandroid:id="@+id/btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:text="btn"android:textAllCaps="false" /></LinearLayout>這個(gè)布局很簡(jiǎn)單,只是放置了一個(gè)Button按鈕,并且讓它水平居中。然后新建右側(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="#00ff00"android:orientation="vertical"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:text="This is right fragment"android:textSize="20sp" /></LinearLayout>可以看到,我們將這個(gè)布局的背景色設(shè)置成了綠色,并放置了一個(gè)TextView用于顯示一段文本。
接著新建一個(gè)LeftFragment類,并讓它繼承自Fragment。注意,這里可能會(huì)有兩個(gè)不同包下的Fragment供你選擇,一個(gè)是系統(tǒng)內(nèi)置的android.app.Fragment,一個(gè)是support-v4庫(kù)中的android.support.v4.app.Fragment。這里我強(qiáng)烈建議你使用support-v4庫(kù)(注意是support-v4)中的Fragment,因?yàn)樗梢宰屗槠谒蠥ndroid系統(tǒng)版本中保持功能一致性。比如說(shuō)在Fragment中嵌套使用Fragment,這個(gè)功能是在Android4.2系統(tǒng)中才開(kāi)始支持的,如果你使用的是系統(tǒng)內(nèi)置的Fragment,那么很遺憾,4.2系統(tǒng)之前的設(shè)備運(yùn)行你的程序就會(huì)崩潰。而使用support-v4庫(kù)中的Fragment就不會(huì)出現(xiàn)這個(gè)問(wèn)題,只要你保證使用的是最新的support-v4庫(kù)就可以了。另外,我們并不需要在build.gradle文件中添加support-v4庫(kù)依賴,因?yàn)閎uild.gradle文件已經(jīng)添加了appcompat-v7庫(kù)的依賴,而這個(gè)庫(kù)會(huì)將support-v4庫(kù)也一起引入進(jìn)來(lái)。
現(xiàn)在編寫(xiě)一下LeftFragment中的代碼,如下所示:
package com.example.administrator.fragmenttest;import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup;public class LeftFragment extends Fragment {@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.left_fragment, container, false);return view;} }這里僅僅是重寫(xiě)了Fragment的onCreateView()方法,然后在這個(gè)方法通過(guò)LayoutInflater的inflate()方法將剛才定義的left_fragment布局動(dòng)態(tài)加載進(jìn)來(lái),整個(gè)方法簡(jiǎn)單明了。接著我們用同樣的方法再新建一個(gè)RightFragment,代碼如下所示:
package com.example.administrator.fragmenttest;import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup;public class RightFragment extends Fragment {@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.right_fragment, container, false);return view;} }接下來(lái)修改activity_main.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="horizontal"><fragmentandroid:id="@+id/left_fragment"android:name="com.example.administrator.fragmenttest.LeftFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1" /><fragmentandroid:id="@+id/right_fragment"android:name="com.example.administrator.fragmenttest.RightFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1" /> </LinearLayout>效果圖:
正如我們所期待的一樣,兩個(gè)碎片平分了整個(gè)活動(dòng)的布局。不過(guò)這個(gè)例子實(shí)在是太簡(jiǎn)單了,在真正的項(xiàng)目中很難有什么實(shí)際的作用,因此我們馬上來(lái)看一看關(guān)于碎片更加高級(jí)的使用技巧。
動(dòng)態(tài)添加碎片:
碎片真正強(qiáng)大之處在于,它可以在程序運(yùn)行時(shí)動(dòng)態(tài)地添加到活動(dòng)當(dāng)中。根據(jù)具體情況來(lái)動(dòng)態(tài)地添加碎片,你就可以將程序界面定制得更加多樣化。
新建another_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="#ffff00"android:orientation="vertical"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:text="This is another right fragment"android:textSize="20sp" /></LinearLayout>這個(gè)布局文件的代碼和right_fragment.xml中的代碼基本相同,只是將背景色改成了黃色,并將顯示的文字改了改。然后新建AnotherRightFragment.java作為另一個(gè)右側(cè)碎片,代碼如下所示:
package com.example.administrator.fragmenttest;import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup;public class AnotherRightFragment extends Fragment {@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.another_right_fragment, container, false);return view;} }代碼同樣非常簡(jiǎn)單,在onCreateView()方法中加載了剛剛創(chuàng)建的another_right_fragment布局。這樣我們就準(zhǔn)備好了另外一個(gè)碎片,接下來(lái)看一下如何將它動(dòng)態(tài)地添加到活動(dòng)當(dāng)中。
修改activity_main.xml代碼(刪除右邊的<fragment/>標(biāo)簽,添加一個(gè)<FrameLayout/>):
<?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"><fragmentandroid:id="@+id/left_fragment"android:name="com.example.administrator.fragmenttest.LeftFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1" /><FrameLayoutandroid:id="@+id/right_layout"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1" /></LinearLayout>可以看到,現(xiàn)在將右側(cè)碎片替換成了一個(gè)FrameLayout中,這是Android中最簡(jiǎn)單的一種布局,所有的控件默認(rèn)都會(huì)擺放在布局的左上角。由于這里僅需要在布局里放入一個(gè)碎片,不需要任何定位,因此非常適合使用FrameLayout。
下面我們將在代碼中向FrameLayout里添加內(nèi)容,從而實(shí)現(xiàn)動(dòng)態(tài)添加碎片的功能。修改MainActivity中的代碼,如下所示:
package com.example.administrator.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;public class MainActivity extends AppCompatActivity {private Button btn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();}private void initView() {btn = (Button) findViewById(R.id.btn);}@Overrideprotected void onResume() {super.onResume();btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {replaceFragment(new AnotherRightFragment());//替換布局文件}});}private void replaceFragment(Fragment fragment) {FragmentManager fragmentManager = getSupportFragmentManager();FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();fragmentTransaction.replace(R.id.right_layout, fragment);fragmentTransaction.commit();}}可以看到,首先我們給左側(cè)碎片中的按鈕注冊(cè)了一個(gè)點(diǎn)擊事件,然后調(diào)用了我們自定義的一個(gè)replaceFragment()方法動(dòng)態(tài)添加了RightFragment這個(gè)碎片。當(dāng)點(diǎn)擊左側(cè)碎片中的按鈕時(shí),又會(huì)調(diào)用replaceFragment()方法將右側(cè)碎片替換成AnotherRightFragment。結(jié)合replaceFragment()方法中的代碼可以看出,動(dòng)態(tài)添加碎片主要分為以下幾個(gè)步驟:
步驟1:創(chuàng)建待添加的碎片實(shí)例
步驟2:創(chuàng)建FragmentManager(碎片管理器),通過(guò)getSupportFragmentManager()這個(gè)方法得到。
步驟3:開(kāi)啟一個(gè)FragmentTransaction事務(wù),通過(guò)beginTransaction()方法開(kāi)啟
步驟4:向容器內(nèi)添加或替換碎片,一般使用replace()方法實(shí)現(xiàn),需要傳入容器的id和待添加的碎片實(shí)例。
步驟5:提交事務(wù),調(diào)用commit()方法來(lái)完成。
這樣就完成了活動(dòng)中動(dòng)態(tài)添加碎片的功能,重新運(yùn)行一下程序。
實(shí)現(xiàn)效果圖:
點(diǎn)擊btn按鈕:
?
在碎片中模擬返回棧
一行代碼:
fragmentTransaction.addToBackStack(null);//接收一個(gè)名字用于描述返回棧的狀態(tài)。
MainActivity.java代碼:
package com.example.administrator.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;public class MainActivity extends AppCompatActivity {private Button btn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();}private void initView() {btn = (Button) findViewById(R.id.btn);}@Overrideprotected void onResume() {super.onResume();btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {replaceFragment(new AnotherRightFragment());//替換布局文件}});}private void replaceFragment(Fragment fragment) {FragmentManager fragmentManager = getSupportFragmentManager();FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();fragmentTransaction.replace(R.id.right_layout, fragment);fragmentTransaction.addToBackStack(null);//接收一個(gè)名字用于描述返回棧的狀態(tài)。fragmentTransaction.commit();}}這樣就可以在點(diǎn)擊btn按鈕之后,點(diǎn)擊手機(jī)back按鈕就可以將碎片返回,再點(diǎn)擊btn按鈕,它又可以出來(lái),就像返回棧中壓棧、出棧一樣。
?
碎片和活動(dòng)之間進(jìn)行通信:
雖然碎片都是嵌入在活動(dòng)中顯示的,可是實(shí)際上它們的關(guān)系并沒(méi)有那么親密。你可以看出,碎片和活動(dòng)都是各自存在于一個(gè)獨(dú)立的類當(dāng)中的,它們之間并沒(méi)有那么明顯的方式來(lái)直接進(jìn)行通信。如果想要在活動(dòng)中調(diào)用碎片里的方法,或者在碎片中調(diào)用活動(dòng)里的方法,應(yīng)該如何實(shí)現(xiàn)呢?
為了方便碎片和活動(dòng)之間進(jìn)行通信,FragmentManager提供了一個(gè)類似于findViewById()的方法,專門(mén)用于從布局文件中獲取碎片的實(shí)例,代碼如下所示:
Activity中獲取Fragment實(shí)例:
RightFragment right=(RightFragment) getSupportFragmentManager().findFragmentById(R.id.right_fragment);
調(diào)用FragmentManager的findFragmentById()方法,可以在活動(dòng)中得到相應(yīng)碎片的實(shí)例,然后就能輕松地調(diào)用碎片里的方法了。
Fragment中調(diào)用Activity實(shí)例:
MainActivity activity=(MainActivity) getActivity();?
?
?
?
?
?
?
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的Fragment碎片的基本使用(手机平板需要更好地兼容)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 编写精美的聊天界面(左边显示接收消息,右
- 下一篇: 13薪要满一年才发吗 没有干满一年能不能