Fragment碎片的基本使用(手机平板需要更好地兼容)
碎片(Fragment)是一種可以嵌入在活動當中的UI片段,它能讓程序更加合理和充分地利用大屏幕的控件,因而在平板上應用得非常廣泛。碎片其實與活動十分相似,同樣都能包含布局,也同樣擁有著自己的生命周期。你甚至可以將碎片理解成一個迷你型的活動,雖然這個迷你型的活動有可能和普通的活動是一樣大的。接下來我們來了解下Fragment的具體使用。
新建一個FragmentTest項目,并且創建好一個平板模擬器,Android版本就8.0吧,雖然已經有9.0版本了,但是我發現個別平板模擬器無法自適應重力感應。
創建平板的步驟:
1.點擊AVD Manager(AndroidVirtualDevice Manager)
2.點擊左下角的Create Virtual Device...
3.選擇Tablet,尺寸就選擇一個8.86寸的吧
4.下面是選擇一個Android設備的版本,這里如果你沒有就需要下載一下,我選擇的是8.1版本的
5.然后下一步下一步就創建好了
6.啟動模擬器
具體請看圖解:
這就把Android平板模擬器給創建好了。
我們準備先寫一個最簡單的碎片示例來練一練手,在一個活動當中添加兩個碎片,并且讓這兩個碎片平分活動空間。
新建一個左側碎片布局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>這個布局很簡單,只是放置了一個Button按鈕,并且讓它水平居中。然后新建右側碎片布局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>可以看到,我們將這個布局的背景色設置成了綠色,并放置了一個TextView用于顯示一段文本。
接著新建一個LeftFragment類,并讓它繼承自Fragment。注意,這里可能會有兩個不同包下的Fragment供你選擇,一個是系統內置的android.app.Fragment,一個是support-v4庫中的android.support.v4.app.Fragment。這里我強烈建議你使用support-v4庫(注意是support-v4)中的Fragment,因為它可以讓碎片在所有Android系統版本中保持功能一致性。比如說在Fragment中嵌套使用Fragment,這個功能是在Android4.2系統中才開始支持的,如果你使用的是系統內置的Fragment,那么很遺憾,4.2系統之前的設備運行你的程序就會崩潰。而使用support-v4庫中的Fragment就不會出現這個問題,只要你保證使用的是最新的support-v4庫就可以了。另外,我們并不需要在build.gradle文件中添加support-v4庫依賴,因為build.gradle文件已經添加了appcompat-v7庫的依賴,而這個庫會將support-v4庫也一起引入進來。
現在編寫一下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;} }這里僅僅是重寫了Fragment的onCreateView()方法,然后在這個方法通過LayoutInflater的inflate()方法將剛才定義的left_fragment布局動態加載進來,整個方法簡單明了。接著我們用同樣的方法再新建一個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;} }接下來修改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>效果圖:
正如我們所期待的一樣,兩個碎片平分了整個活動的布局。不過這個例子實在是太簡單了,在真正的項目中很難有什么實際的作用,因此我們馬上來看一看關于碎片更加高級的使用技巧。
動態添加碎片:
碎片真正強大之處在于,它可以在程序運行時動態地添加到活動當中。根據具體情況來動態地添加碎片,你就可以將程序界面定制得更加多樣化。
新建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>這個布局文件的代碼和right_fragment.xml中的代碼基本相同,只是將背景色改成了黃色,并將顯示的文字改了改。然后新建AnotherRightFragment.java作為另一個右側碎片,代碼如下所示:
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;} }代碼同樣非常簡單,在onCreateView()方法中加載了剛剛創建的another_right_fragment布局。這樣我們就準備好了另外一個碎片,接下來看一下如何將它動態地添加到活動當中。
修改activity_main.xml代碼(刪除右邊的<fragment/>標簽,添加一個<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>可以看到,現在將右側碎片替換成了一個FrameLayout中,這是Android中最簡單的一種布局,所有的控件默認都會擺放在布局的左上角。由于這里僅需要在布局里放入一個碎片,不需要任何定位,因此非常適合使用FrameLayout。
下面我們將在代碼中向FrameLayout里添加內容,從而實現動態添加碎片的功能。修改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();}}可以看到,首先我們給左側碎片中的按鈕注冊了一個點擊事件,然后調用了我們自定義的一個replaceFragment()方法動態添加了RightFragment這個碎片。當點擊左側碎片中的按鈕時,又會調用replaceFragment()方法將右側碎片替換成AnotherRightFragment。結合replaceFragment()方法中的代碼可以看出,動態添加碎片主要分為以下幾個步驟:
步驟1:創建待添加的碎片實例
步驟2:創建FragmentManager(碎片管理器),通過getSupportFragmentManager()這個方法得到。
步驟3:開啟一個FragmentTransaction事務,通過beginTransaction()方法開啟
步驟4:向容器內添加或替換碎片,一般使用replace()方法實現,需要傳入容器的id和待添加的碎片實例。
步驟5:提交事務,調用commit()方法來完成。
這樣就完成了活動中動態添加碎片的功能,重新運行一下程序。
實現效果圖:
點擊btn按鈕:
?
在碎片中模擬返回棧
一行代碼:
fragmentTransaction.addToBackStack(null);//接收一個名字用于描述返回棧的狀態。
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);//接收一個名字用于描述返回棧的狀態。fragmentTransaction.commit();}}這樣就可以在點擊btn按鈕之后,點擊手機back按鈕就可以將碎片返回,再點擊btn按鈕,它又可以出來,就像返回棧中壓棧、出棧一樣。
?
碎片和活動之間進行通信:
雖然碎片都是嵌入在活動中顯示的,可是實際上它們的關系并沒有那么親密。你可以看出,碎片和活動都是各自存在于一個獨立的類當中的,它們之間并沒有那么明顯的方式來直接進行通信。如果想要在活動中調用碎片里的方法,或者在碎片中調用活動里的方法,應該如何實現呢?
為了方便碎片和活動之間進行通信,FragmentManager提供了一個類似于findViewById()的方法,專門用于從布局文件中獲取碎片的實例,代碼如下所示:
Activity中獲取Fragment實例:
RightFragment right=(RightFragment) getSupportFragmentManager().findFragmentById(R.id.right_fragment);
調用FragmentManager的findFragmentById()方法,可以在活動中得到相應碎片的實例,然后就能輕松地調用碎片里的方法了。
Fragment中調用Activity實例:
MainActivity activity=(MainActivity) getActivity();?
?
?
?
?
?
?
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的Fragment碎片的基本使用(手机平板需要更好地兼容)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 编写精美的聊天界面(左边显示接收消息,右
- 下一篇: 13薪要满一年才发吗 没有干满一年能不能