Android Studio教程07-Fragment的使用


1. Fragment是什么

  • fragment表示 Activity 中的行為或用戶界面部分。可以將多個片段組合在一個 Activity 中來構建多窗格 UI
  • fragment是activity的模塊化組成部分
  • fragemnt性質:
    • 有自己的生命周期
    • 可以接收輸入事件,並且可以在activity運行時添加或者刪除片段
    • fragment必須依附在activity中(Activity暫停,fragment暫停,銷毀也銷毀)
    • activity運行時,可以獨立操作每個片段,也可以在fragment和activity之間進行通信

1.1. 設計原理和實例

  • 新聞應用可以使用一個片段在左側顯示文章列表,使用另一個片段在右側顯示文章 — 兩個片段並排顯示在一個 Activity 中,每個片段都具有自己的一套生命周期回調方法,並各自處理自己的用戶輸入事件。 因此,用戶不需要使用一個 Activity 來選擇文章,然后使用另一個 Activity 來閱讀文章,而是可以在同一個 Activity 內選擇文章並進行閱讀

2. 創建fragment

通過創建Fragment子類

  • 創建fragment類
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.ViewGroup;

public class ArticleFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.article_view, container, false);
    }
}
  • 添加到activity布局中
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <fragment android:name="com.example.android.fragments.HeadlinesFragment"
              android:id="@+id/headlines_fragment"
              android:layout_weight="1"
              android:layout_width="0dp"
              android:layout_height="match_parent" />

    <fragment android:name="com.example.android.fragments.ArticleFragment"
              android:id="@+id/article_fragment"
              android:layout_weight="2"
              android:layout_width="0dp"
              android:layout_height="match_parent" />

</LinearLayout>
  • 在activity中調用該fragment
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.news_articles);
    }
}

2.1. fragment的生命周期

生命周期 含義 主要內容
onCreate() 系統會在創建片段時調用此方法 初始化組件
onCreateView() 系統會在片段首次繪制其用戶界面時調用此方法。 要想為您的片段繪制 UI
您從此方法中返回的 View 必須是片段布局的根視圖
onPause() 系統將此方法作為用戶離開片段的第一個信號(但並不總是意味着此片段會被銷毀)進行調用 確認在當前用戶會話結束后仍然有效的任何更改

2.2 添加用戶界面:融入到Activity中

  • 步驟1: 創建一個布局文件example_fragment.xml
  • 步驟2: 在fragment類中加載布局
public static class ExampleFragment extends Fragment {
  // container:您的片段布局將插入到的父 ViewGroup
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.example_fragment, container, false);
    }
}
  • 步驟3: 在activity中添加片段
    • 方法1:直接在布局文件中添加:當系統創建此 Activity 布局時,會實例化在布局中指定的每個片段,並為每個片段調用 onCreateView() 方法,以檢索每個片段的布局。
<?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:name="com.example.news.ArticleListFragment"
            android:id="@+id/list"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
    <fragment android:name="com.example.news.ArticleReaderFragment"
            android:id="@+id/viewer"
            android:layout_weight="2"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
</LinearLayout>
  • 方法2:通過編程添加
// 必須使用 FragmentTransaction 中的 API
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// 使用 add() 方法添加一個片段,指定要添加的片段以及將其插入哪個視圖
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
// 調用 commit() 以使更改生效
fragmentTransaction.commit();

3. 管理fragment:FragmentManager

FragmentManager的執行操作包括:

  • 通過 findFragmentById()(對於在 Activity 布局中提供 UI 的片段)或 findFragmentByTag()(對於提供或不提供 UI 的片段)獲取 Activity 中存在的片段。
  • 通過 popBackStack()(模擬用戶發出的返回命令)將片段從返回棧中彈出。
  • 通過 addOnBackStackChangedListener() 注冊一個偵聽返回棧變化的偵聽器。

3.1. 執行片段事務

  • Activity 中使用片段的一大優點是,可以根據用戶行為通過它們執行添加、移除、替換以及其他操作。也稱為事務
  • 可以將每個事務保存到由 Activity 管理的返回棧內,從而讓用戶能夠回退片段更改(類似於回退 Activity)。
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack 在返回棧中保留先前狀態
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// Commit the transaction
transaction.commit();

3.2. 與Activity通信

  • 片段可以通過getActivity() 訪問 Activity 實例,並輕松地執行在 Activity 布局中查找視圖等任務。
  • Activity 也可以使用 findFragmentById()findFragmentByTag(),通過從 FragmentManager 獲取對 Fragment 的引用來調用片段中的方法
// fragment - > activity
View listView = getActivity().findViewById(R.id.list);
// activity - > fragment  
ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);

(1) 創建對Activity的事件回調

  • 在片段內定義一個回調接口,並要求宿主 Activity 實現它。 當 Activity 通過該接口收到回調時,可以根據需要與布局中的其他片段共享這些信息。
  • 一個新聞應用的 Activity 有兩個片段 — 一個用於顯示文章列表(片段 A),另一個用於顯示文章(片段 B)— 那么片段 A 必須在列表項被選定后告知 Activity,以便它告知片段 B 顯示該文章。
//fragment定義接口
public static class FragmentA extends ListFragment {
    ...
    // Container Activity must implement this interface
    public interface OnArticleSelectedListener {
        public void onArticleSelected(Uri articleUri);
    }
    ...

    OnArticleSelectedListener mListener;
    ...
    // 確保宿主 Activity 實現此接口
    // 通過轉換傳遞到 onAttach() 中的 Activity 來實例化 OnArticleSelectedListener 的實例
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnArticleSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
        }
    }
    // 列表點擊事件
    OnArticleSelectedListener mListener;
    ...
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        // Append the clicked item's row ID with the content provider Uri
        Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id);
        // Send the event and Uri to the host activity
        mListener.onArticleSelected(noteUri);
    }
    ...
}

4. fragment與activity的生命周期關系

  • Activity 的每次生命周期回調都會引發每個片段的類似回調。例如,當 Activity 收到 onPause() 時,Activity 中的每個片段也會收到 onPause()。

5. 在Activity中動態添加fragment

  • 如需執行添加或移除片段等事務,您必須使用 FragmentManager 創建 FragmentTransaction,后者將提供添加、移除、替換片段以及執行其他片段事務所需的 API。
  • 如果您的 Activity 允許移除和替換片段,應在 Activity 的 onCreate() 方法執行期間為 Activity 添加初始片段。
  1. 采用以下方法為之前的布局添加片段:
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.news_articles);

        // Check that the activity is using the layout version with
        // the fragment_container FrameLayout
        if (findViewById(R.id.fragment_container) != null) {

            // However, if we're being restored from a previous state,
            // then we don't need to do anything and should return or else
            // we could end up with overlapping fragments.
            if (savedInstanceState != null) {
                return;
            }

            // Create a new Fragment to be placed in the activity layout
            HeadlinesFragment firstFragment = new HeadlinesFragment();

            // In case this activity was started with special instructions from an
            // Intent, pass the Intent's extras to the fragment as arguments
            firstFragment.setArguments(getIntent().getExtras());

            // Add the fragment to the 'fragment_container' FrameLayout
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, firstFragment).commit();
        }
    }
}

由於該片段已在運行時被添加到 FrameLayout 容器,可以從該 Activity 中移除該片段,並將其替換為其他片段。

  1. 替換片段:
// Create fragment and give it an argument specifying the article it should show
ArticleFragment newFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// Commit the transaction
transaction.commit();

6. 實例,新聞頁面

https://blog.csdn.net/zhaoyanga14/article/details/52166491


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM