android——Fragment

谷歌官方文檔的介紹:html

https://developer.android.com/guide/components/fragments.html#Designjava

Fragment 表示 Activity 中的行爲或用戶界面部分。您能夠將多個片斷組合在一個 Activity 中來構建多窗格 UI,以及在多個 Activity 中重複使用某個片斷。您能夠將片斷視爲 Activity 的模塊化組成部分,它具備本身的生命週期,能接收本身的輸入事件,而且您能夠在 Activity 運行時添加或移除片斷(有點像您能夠在不一樣 Activity 中重複使用的「子 Activity」)。android

片斷必須始終嵌入在 Activity 中,其生命週期直接受宿主 Activity 生命週期的影響。 例如,當 Activity 暫停時,其中的全部片斷也會暫停;當 Activity 被銷燬時,全部片斷也會被銷燬。 不過,當 Activity 正在運行(處於已恢復生命週期狀態)時,您能夠獨立操縱每一個片斷,如添加或移除它們。 當您執行此類片斷事務時,您也能夠將其添加到由 Activity 管理的返回棧 — Activity 中的每一個返回棧條目都是一條已發生片斷事務的記錄。 返回棧讓用戶能夠經過按返回按鈕撤消片斷事務(後退)。ide

當您將片斷做爲 Activity 佈局的一部分添加時,它存在於 Activity 視圖層次結構的某個 ViewGroup 內部,而且片斷會定義其本身的視圖佈局。您能夠經過在 Activity 的佈局文件中聲明片斷,將其做爲 <fragment> 元素插入您的 Activity 佈局中,或者經過將其添加到某個現有 ViewGroup,利用應用代碼進行插入。不過,片斷並不是必須成爲 Activity 佈局的一部分;您還能夠將沒有本身 UI 的片斷用做 Activity 的不可見工做線程。模塊化

 

1、使用Fragment的兩種方式佈局

一、在Activity的佈局中加入fragmentui

  這種方式就是在Activity的佈局中把fragment看成一個控件來使用,不過這等因而將視圖和Activity的視圖綁在一塊兒,在Activity的生命週期內沒法切換fragment。this

  先新建一個繼承Fragment的類,重寫onCreateView決定Fragemnt的佈局,onCreateView裏面還須要一個佈局文件,右鍵layout→new→file 建立一個fragment.xml的佈局文件  spa

<?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">

    <EditText
        android:id="@+id/crime_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/crime_tittle_hint"/>

</LinearLayout>

  這個佈局是怎樣,是無所謂的,只根據需求來編寫便可。線程

  而後在繼承Fragment的類裏,重寫onCreateView將這個加載這個佈局

public class Fragment1 extends Fragment {

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

調用LayoutInflater的inglate()方法加載佈局,第一個參數是佈局資源的ID,第二個參數是視圖的父視圖。

而後在活動的佈局文件中Activity中使用這個Fragment,就當和普通的View同樣

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

    <fragment
        android:id="@+id/id_fragment_content"
        android:name="xbt.exp22.Fragment1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</RelativeLayout>

 

二、在Activity的代碼中加入fragment

  這種能夠在運行時控制fragment能夠自行決定加載那一個fragment,也能夠移除,換一個fragment

修改活動的佈局,把以前的碎片view刪掉,加入一個按鈕和一個FrameLayout,給FrameLayout設置一個ID

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

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <FrameLayout
        android:id="@+id/fragment"
        android:layout_below="@id/button1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</RelativeLayout>

修改活動的代碼:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button1= (Button) findViewById(R.id.button1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                FragmentManager fragmentManager = getFragmentManager();
                FragmentTransaction transaction = fragmentManager.beginTransaction();
                transaction.replace(R.id.FrameLayout,new Fragment1());
                transaction.commit();
            }
        });
    }
}

按鈕響應的內容是:使用getFragmentManager();獲取FragmentManager,使用beginTransaction();開啓一個事務transaction,而後向容器添加或替換片斷,須要傳入容器的id和片斷,而後使用commit()提交事務。其中FragmentTransaction()的replace方法第一個參數是想要放片斷的佈局的id,第二個參數就是想要放入的片斷的一個對象。這樣就能實現點擊按鈕以後片斷纔出現。

這裏的添加碎片fragment還能夠這樣寫:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button1= (Button) findViewById(R.id.button1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                FragmentManager fragmentManager = getFragmentManager();
                fragmentManager.beginTransaction()
                            .add(R.id.FrameLayout,new Fragment1())
                            .commit();
            }
        });
    }
}

 

總的來講過程其實大致都是同樣的,

一、Activity使用FragmentManager來管理fragment隊列,

二、FragmentManager調用beginTransation()建立一個FragmentTransaction(),

三、調用add()或replace()告訴FragmentManager,fragment視圖應該出如今activity視圖的那個位置,使用那一個fragment。

四、最後提交事務調用commit()

 

2、將一個片斷替換成另外一個片斷:

須要新建一個fragment類和它的佈局:

fragment類Fragment2.class:

public class Fragment2 extends Fragment {
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View view =  inflater.inflate(R.layout.fragment2, container, false);
            return view;
        }
}

佈局:fragment2.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">

    <TextView
        android:id="@+id/crime_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="第二個片斷"/>

</LinearLayout>

活動的java代碼:

  Button button2 = (Button) findViewById(R.id.button2);
  button2.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
           FragmentManager fragmentManager = getFragmentManager();
           fragmentManager.beginTransaction()
               .replace(R.id.FrameLayout,new Fragment2())
               .addToBackStack(null)
               .commit();
            }
        });

新的Fragment替換在 R.id.fragment_container ID 所標識的佈局容器中的任何片斷(若有),經過調用 addToBackStack() 可將替換事務保存到返回棧,以便用戶可以經過按返回按鈕撤消事務並回退到上一片斷。

若是您向事務添加了多個更改(如又一個 add() 或 remove()),而且調用了 addToBackStack(),則在調用 commit() 前應用的全部更改都將做爲單一事務添加到返回棧,而且返回按鈕會將它們一併撤消。

向 FragmentTransaction 添加多個更改的順序可有可無,不過:

  • 必須最後調用 commit()
  • 若是要向同一容器添加多個片斷,則您添加片斷的順序將決定它們在視圖層次結構中的出現順序

若是沒有在執行移除片斷的事務時調用 addToBackStack(),則事務提交時該片斷會被銷燬,用戶將沒法回退到該片斷。 不過,若是您在刪除片斷時調用了 addToBackStack(),則系統會中止該片斷,並在用戶回退時將其恢復。

 

2、fragment的生命週期

圖片.Activity 生命週期對片斷生命週期的影響

 

片斷生命週期與管理 Activity 生命週期很類似。和 Activity 同樣,片斷也以三種狀態存在:

Resumed

  片斷在運行中的 Activity 中可見。

Paused

  另外一個 Activity 位於前臺並具備焦點,但此片斷所在的 Activity 仍然可見(前臺 Activity 部分透明,或未覆蓋整個屏幕)。

Stoped

  片斷不可見。宿主 Activity 已中止,或片斷已從 Activity 中移除,但已添加到返回棧。 中止片斷仍然處於活動狀態(系統會保留全部狀態和成員信息)。 不過,它對用戶再也不可見,若是 Activity 被終止,它也會被終止。

 

和Activity 同樣,假使 Activity 的進程被終止,在重建 Activity 時須要恢復片斷狀態,也可使用 Bundle 保留片斷的狀態。能夠在片斷的 onSaveInstanceState() 回調期間保存狀態,並可在 onCreate()onCreateView() 或 onActivityCreated() 期間恢復狀態。

Activity 生命週期與片斷生命週期之間的最顯著差別在於它們在其各自返回棧中的存儲方式。 默認狀況下,Activity 中止時會被放入由系統管理的 Activity 返回棧(也就是打開另外一個活動以後當前活動就會處於中止狀態,點擊返回按鈕後就會自動恢復)。不過,可是若是在執行移除片斷的事務執行期間不經過調用 addToBackStack() 顯式請求保存實例時,系統不會將片斷放入由宿主 Activity 管理的返回棧,也就是說按返回就不會恢復。

 

一個例子:新建一個擁有一個按鈕的SecondActivity,這個按鈕的響應是使用Intent啓動一個MainActivity, 將MainActivity中的兩個按鈕的響應修改成啓動一個SecondActivity和銷燬本活動,在MainActivity中靜態加載一個片斷,在該片斷中將器生命週期內的每個方法都重寫輸出日誌方法名字

活動的java代碼:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button1 = (Button) findViewById(R.id.button1);

        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });

        Button button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });
        Log.d("message","MainActivity:onCreate");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d("message","MainActivity:onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d("message","MainActivity:onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d("message","MainActivity:onPause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d("message","MainActivity:onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d("message","MainActivity:onDestroy");
    }
}

片斷的java代碼:

public class Fragment1 extends Fragment {

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Log.d("message","Fragment1:onAttach");
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("message","Fragment1:onCreate");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view =  inflater.inflate(R.layout.fragment, container, false);
        Log.d("message","Fragment1:onCreateView");
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.d("message","Fragment1:onActivityCreated");
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d("message","Fragment1:onStart");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d("message","Fragment1:onResume");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d("message","Fragment1:onPause");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d("message","Fragment1:onStop");
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.d("message","Fragment1:onDestroyView");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("message","Fragment1:onDestroy");

    }

    @Override
    public void onDetach() {
        super.onDetach();
        Log.d("message","Fragment1:onDetach");
    }
}

剛啓動應用程序時:

啓動SecondActivity:

在SecondActivity啓動一個MainActivity:

點擊返回到SecondActivity

再點擊返回

點擊第二個按鈕銷燬活動

以上就是片斷跟隨活動的生命週期狀態變化自身狀態隨之變化並調用相應方法的驗證。

相關文章
相關標籤/搜索