天天看點

Android:Fragment(碎片)的簡單使用,Fragment的生命周期

簡介

是從Android3.0開始新增的概念, 意為碎片,
而且是因為專門為平闆設計的

用來組建Activity界面的局部子產品, 
也可以說一個Actiivty界面可以由多個Fragment組成

其行為與Activity很相似, 有自己對應的View, 
它有自己的生命周期,接收自己的輸入事件,你可以添加或移除從運作中的activity
一個fragment必須總是嵌入在一個activity中,
同時fragment的生命周期受activity的影響
本質上會産生一個FrameLayout,它加載的布局為其子布局/View      
比如之前在手機顯示一個清單,我們點選一下會進入詳情頁面
但是現在就不一樣了,平闆出來後,螢幕很大,我們沒有必要在
那麼大的螢幕顯示一條資料,現在我們使用fragment将螢幕分成兩部分
一部分顯示清單資料,另外一部分顯示詳情資料      

android-support-v4.jar

這個jar包是幹嘛的呢?
  它是google提供的能相容到api4(1.6)的相容jar包
  在Android3.x加入了很多的API,但是在2.x和1.x的jar包裡面
  不支援3.x的API,那麼google就将它們抽取出來,然後是項目中
  使用這個jar,那麼項目在打包的時候就會将這個jar也打包到項目裡面
  那麼在低版本的手機也可以使用新的API,實作相容性

這個android-support-v4.jar裡面有兩個重要的類:      

API

Fragment
  View onCreateView()
  onActivityCreate() 當Activity建立好
  getActivity()
  setArguments()
  getArgument()
ListFragment
  setListAdapter(adapter)
  onListItemClick()
  getFragmentManager()
FragmentActivity
  getSupportFragmentManager()
FragmentManager
  beginTransacation()
FragmentTransacation
  add(), replace(), remove(),commit()
  addToBackStack()      

使用

Fragment的靜态加載

定義Fragment的子類, 并在onCreateView()中加載一個布局檔案
在布局檔案中通過<fragment>指定指定自定義Fragment
Activity必須繼承于FragmentActivity      
package com.jane.fragment;

import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class MyFragment1 extends Fragment
{

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState)
  {

    // 加載布局得到View對象并傳回

    // 建立一個視圖對象, 設定資料并傳回
    TextView textView = new TextView(getActivity());
    textView.setText("fragment11111");
    textView.setBackgroundColor(Color.RED);

    return textView;
  }
}      
package com.jane.fragment;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class MyFragment2 extends Fragment
{

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState)
  {

    // 加載布局得到View對象并傳回

    // 建立一個視圖對象, 設定資料并傳回
    TextView textView = new TextView(getActivity());
    textView.setText("fragment22222");

    return textView;
  }
}      
package com.jane.fragment;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;

/*
 * 測試使用Fragment(靜态加載)
 * 1. 定義Fragment的子類, 并加載一個布局檔案
 *  2. 在布局檔案中通過<fragment>指定指定自定義Fragment
 *  3. 我們的Activity必須繼承于FragmentActivity
 *  每個Fragment本質上都會生成一個FrameLayout, 它加載的布局為其子布局
 */
public class MainActivity extends FragmentActivity
{

  public MainActivity()
  {
    Log.e("TAG", "MainActivity()..");
  }

  @Override
  protected void onCreate(Bundle savedInstanceState)
  {
    Log.e("TAG", "MainActivity onCreate()..");
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
  }
}      
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" 
    android:orientation="horizontal">

    <fragment
        android:name="com.jane.fragment.MyFragment1"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent" />

    <fragment
        android:name="com.jane.fragment.MyFragment2"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent" />

</LinearLayout>      

Fragment的動态加載

package com.jane.fragment;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.View;

/**
 * 測試使用Fragment(動态使用) 
 * 1. 使用FragmentManager和FragmentTransaction動态使用一個Fragment 
 * 2. 方式: 
 *     add(viewId, fragment): 将fragment的視圖添加為指定視圖的子視圖(加在原有子視圖的後面)
 *     replace(viewId, fragment): 将fragment的視圖添加為指定視圖的子視圖(先remove原有的子視圖)
 *     remove(fragment) : 将fragment的視圖移除
 */
public class MainActivity extends FragmentActivity
{

  public MainActivity()
  {
    Log.e("TAG", "MainActivity()..");
  }

  @Override
  protected void onCreate(Bundle savedInstanceState)
  {
    Log.e("TAG", "MainActivity onCreate()..");
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // 建立Fragment對象
    MyFragment1 fragment1 = new MyFragment1();
    // 得到FragmentManager
    FragmentManager manager = getSupportFragmentManager();
    // 得到FragmentTransacation
    FragmentTransaction transaction = manager.beginTransaction();
    // 添加Fragment對象并送出
    transaction.add(R.id.ll_main_container, fragment1).commit();
  }

  private MyFragment2 fragment2;

  public void showFragment2(View v)
  {
    // 建立Fragment對象
    fragment2 = new MyFragment2();
    // 得到FragmentManager
    FragmentManager manager = getSupportFragmentManager();
    // 得到FragmentTransacation
    FragmentTransaction transaction = manager.beginTransaction();

    // 将目前操作添加到回退棧, 這樣點選back回到上一個狀态
    transaction.addToBackStack(null);

    // 替換Fragment對象并送出
    transaction.replace(R.id.ll_main_container, fragment2).commit();
  }

  public void deleteFragment2(View v)
  {

    // 得到FragmentManager
    FragmentManager manager = getSupportFragmentManager();
    // 得到FragmentTransacation
    FragmentTransaction transaction = manager.beginTransaction();
    // 移除Fragment對象并送出
    transaction.remove(fragment2).commit();
  }
}      
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="showFragment2"
            android:text="顯示fragment2" />

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="deleteFragment2"
            android:text="移除fragment2" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/ll_main_container"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal" >
    </LinearLayout>

</LinearLayout>      

Fragment的生命周期

測試
/*
  添加Fragment對象顯示
    onAttach()-->onCreate()-->onCreateView()-->onActivityCreated()-->onstart()-->onResume()
  home到桌面
    onPause()-->onStop()
  回到應用
    onStart()-->onResume()
  replace為其它Fragment
    onPause()-->onStop()-->onDestroyView()
  傳回到本身的Fragment
    onCreateView()-->onActivityCreated()-->onstart()-->onResume()
  退出應用
    onPause()-->onstop()-->onDestroyView()-->onDestroy()-->onDetach()
 */      

模仿平闆樣子

首先準備好資料      
package com.jane.fragment;

public class DataUtils
{
  public static final String[] TITLES =
  { "title1", "title2", "title3", "title4", "title5" };
  public static final String[] DETAILS =
  { "This is title1", "This is title2", "This is title3", "This is title4",
      "This is title5" };
}      
然後是主界面      
package com.jane.fragment;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity
{

  @Override
  protected void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
  }
}      
<?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" >

    <fragment
        android:name="com.jane.fragment.TitleListFragment"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent" />

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

</LinearLayout>      
然後是主界面需要的主題顯示清單      
package com.jane.fragment;

import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;

/**
 * 用來顯示标題的清單
 */
public class TitleListFragment extends ListFragment
{

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState)
  {
    return super.onCreateView(inflater, container, savedInstanceState);
  }

  @Override
  public void onActivityCreated(Bundle savedInstanceState)
  {
    super.onActivityCreated(savedInstanceState);

    // 設定ListView為單選模式
    getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);

    // 給listView設定adapter顯示清單
    setListAdapter(new ArrayAdapter<String>(getActivity(),
        R.layout.list_item, DataUtils.TITLES));

    // 預設選中第一個item
    getListView().setItemChecked(0, true);
    // 顯示第一個詳情
    showDetail(0);
  }

  @Override
  public void onListItemClick(ListView l, View v, int position, long id)
  {
    showDetail(position);
  }

  /**
   * 顯示指定下标的詳情
   * @param position
   */
  private void showDetail(int position)
  {
    // 建立DetailFragment
    DetailFragment fragment = new DetailFragment();
    // 将對應的詳情資料攜帶過去
    Bundle args = new Bundle();
    args.putString("DETAIL", DataUtils.DETAILS[position]);
    fragment.setArguments(args);
    // 将其替換到id為fl_main_container的容器布局中
    getFragmentManager().beginTransaction()
        .replace(R.id.fl_main_container, fragment).commit();
  }
}      
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:paddingTop="5dp"
    android:paddingBottom="5dp"
    android:textSize="18sp"
    android:gravity="center"
    android:text="标題"
    android:background="?android:attr/activatedBackgroundIndicator">
    <!-- android:background="?android:attr/activatedBackgroundIndicator"
        這行是用來讓選擇項變色的
     -->
</TextView>      
然後是詳情的Fragment      
package com.jane.fragment;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**
 * 顯示詳情的Fragment
 */
public class DetailFragment extends Fragment
{

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState)
  {
    TextView textView = new TextView(getActivity());
    // 取出儲存的資料
    String detail = getArguments().getString("DETAIL");
    // 設定
    textView.setText(detail);
    return textView;
  }
}