Android學習之路-基礎知識-Fragement(1)

碎片是什麼

碎片(Fragment)是一種可以嵌在活動當中的UI片段,它能讓程序更加合理和充分地利用大屏幕空間,因而在平板上應用得非常廣泛。我們在編寫平板app時,爲了更好的利用平板的大屏優勢,會把閱讀列表放在左邊,而詳細內容放在右邊,這也是和手機只顯示列表,只有點擊列表會進入詳細頁面不同的地方,顯示效果如圖:
怎麼實現這個效果呢,廢話不多說,開始正題~

碎片的使用方式

初步接觸碎片

新建一個FragmentTest項目,這是一個最簡單的碎片實例。在一個活動中添加兩個碎片,並且讓這兩個碎片平分活動空間。
(1)在res/layout下新建一個left_fragment.xml。代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Button"
        />

</LinearLayout>

佈局文件中只放了一個水平居中的按鈕button。
(2)在res/layout下再新建一個right_fragment.xml文件。代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:background="#00FF00"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <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>
佈局文件中只有一個TextView,顯示一句話“This is right fragment”,然後背景顏色是綠色。
(3)在java/com.XXX(你自己的包名).fragmenttest下新建LeftFragment類,其繼承android.support.v4.app下的Fragment類(此處查看第一行代碼第二版P145頁 有詳細介紹)。代碼如下:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by Deiatg on 2017/3/4.
 */

public class LeftFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        //能動態地加載佈局的函數inflate()
        View view = inflater.inflate(R.layout.left_fragment, container, false);
        return view;
    }
}

這裏僅僅重寫了Fragment類中的onCreateView()方法,這個方法的作用就是使用LayoutInflater的inflate()類將剛纔定義好的left_fragment.xml動態加載進來。用同樣的方法創建一份RightFragment類,代碼如下:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by Deiatg on 2017/3/4.
 */

public class RightFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        //能動態地加載佈局的函數inflate()
        View view = inflater.inflate(R.layout.right_fragment, container, false);
        return view;
    }
}
代碼基本相同,我們繼續。
(4)修改activity_main中的代碼:
<?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:name="com.open_open.fragmenttest.LeftFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"/>

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

</LinearLayout>

代碼將兩個碎片一左一右放入主佈局中,注意的是要將fragment的完整包名放在android:name中。

之後運行程序就能得到一個含有兩個碎片的app了。

動態添加碎片

在之前的代碼基礎上繼續完善。
(1)新建another_right_fragment.xml文件,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:background="#FFFF00"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textSize="20sp"
        android:text="This is another right fragment"/>

</LinearLayout>

跟right_fragment.xml基本完全一樣,只是背景顏色變成了黃色。
(2)建立AnotherRightFragment類,代碼如下:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by Deiatg on 2017/3/4.
 */

public class AnotherRightFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        //能動態地加載佈局的函數inflate()
        View view = inflater.inflate(R.layout.another_right_fragment, container, false);
        return view;
    }
}

代碼同樣很簡單,在onCreateView()方法中加載剛纔創建好的another_right_fragment.xml文件。這就準備好了另一個碎片,之後我們看一下如何將其動態地添加到活動中。
(3)修改activity_main.xml文件,代碼如下:
<?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:name="com.open_open.fragmenttest.LeftFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        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>

可以看到,將右側碎片替換成了一個FrameLayout,爲什麼這麼做呢?其實這樣做是因爲我們想要在活動里加載多個Fragment,那麼就不能再主佈局中將fragment寫死,而是隻放一個FrameLayout,然後通過在MainActivity裏的相關方法對FrameLayout裏的內容進行替換,這樣就達到了我們的目的。於是下一個動作就是修改MainActivity。
(4)修改MainActivity,代碼如下:
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 implements View.OnClickListener{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(this);
        repalceFragment(new RightFragment());
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                repalceFragment(new AnotherRightFragment());
                break;
            default:
                break;
        }
    }

    private void repalceFragment (Fragment fragment) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.right_layout, fragment);
        transaction.commit();
    }
}
代碼中MainActivity類實現了OnClickListener接口,這裏可以參考我的另一篇文章:鏈接 。代碼中首先我們給左側碎片中的button按鈕註冊了一個點擊事件,只有點擊這個按鈕就會調用我們自定義的方法repalceFragment(),這個方法能夠當前佈局替換一個新的碎片。點擊按鈕將右側碎片換成另一個碎片。結合replaeFragment()方法的代碼可以看到,動態添加碎片分爲五步。
(1)創建待添加的碎片實例;
(2)獲取FragmentManager, 在活動中可以 直接通過調用getSupportFragmentManager()方法得到;
(3)開啓一個事務,通過調用beginTransaction()方法開啓;
(4)向容器內添加或者替換碎片,一般使用replace()方法實現,需要傳入容器的id和待添加的碎片實例;
(5)提交事務,調用commit()方法完成。
這樣就完成了在活動中動態添加碎片的活動,重新運行程序,點擊按鈕就會發現屏幕右側發生改變。

在碎片中模擬返回棧

也就是當有多個碎片都被動態添加,我們在調用了它們之後不想按返回鍵直接退出程序,而是逐個返回碎片,最後退出程序。想達到這種類似棧的返回操作其實很簡單,FragmentTransaction中提供了一個addToBackStack()方法,可以用於講一個事務添加到返回站中,修改代碼:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
     ……
    private void repalceFragment (Fragment fragment) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.right_layout, fragment);
        transaction.addToBackStack(null);
        transaction.commit();
    }
}
我們在事務提交之前調用了FragmentTransaction的addToBackStack()方法,它可以接收一個名字用於描述返回棧的狀態,一般傳入null即可。重新運行程序,我們發現,在碎片中模擬返回棧這個功能我們完成了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章