Create a Fragment Class
- 如何創(chuàng)建一個(gè)Fragment
- 繼承Fragment類并覆蓋關(guān)鍵的生命周期方法柳弄,和操作activity差不多吮铭。
- 唯一的不同就是你需要在Fragment中使用onCreateView()方法去加載布局。
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);
}
}
Add a Fragment to an Activity using XML
- 這里是一個(gè)將兩個(gè)fragment添加到一個(gè)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中
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);
}
}
Note:
- 如果你使用的是v7 appcompat library屁商,你的activity需要繼承APPCompatActivity,它是FragmentActivity的一個(gè)子類。
- 當(dāng)你的使用在layout XML File中定義Fragment這一方式添加fragment時(shí)营勤,你不能在運(yùn)行時(shí)移除fragment。如何你想在用戶交互的時(shí)候替換fragment壹罚,你必須在activity第一次啟動(dòng)時(shí)添加fragment葛作。
Buildinga Flexible UI
我們需要在的布局中使用重復(fù)的fragment,可根據(jù)屏幕尺寸的不同進(jìn)行適配猖凛。比如在手機(jī)上可能只能顯示一個(gè)fragment赂蠢,而在平板電腦上需要并排顯示兩個(gè)fragment。
利用FragmentManager類提供的方法辨泳,你就可以在運(yùn)行時(shí)添加虱岂、刪除和替換Activity中的Fragment,為用戶提供一種動(dòng)態(tài)的體驗(yàn)菠红。
Fragment added at runtime to Activity
- 如果你想添加或移除Fragment和其他事物第岖,你必須使用FragmentManager創(chuàng)建一個(gè)FragmentTransaction筹陵,這是一個(gè)可以添加吃靠、刪除和替換Fragment和其他事物的Fragemnt API。
- 在處理Fragment(特別是在運(yùn)行時(shí)添加Fragment)時(shí)碰声,請謹(jǐn)記以下重要規(guī)則:必須在布局中為 Fragment 提供 View 容器,以便保存 Fragment 的布局烫饼。
- 要用一個(gè)Fragment替換另一個(gè)Fragment猎塞,Activity的布局中需要包含一個(gè)作為Fragment容器的空FrameLayout。
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
- 在Activity內(nèi)部杠纵,使用Support Library API調(diào)用getSupportFragmentManager()以獲取FragmentManager荠耽,然后調(diào)用beginTransaction()創(chuàng)建FragmentTransaction,同時(shí)調(diào)用add()添加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);
// 確認(rèn) Activity 使用的布局版本包含
// fragment_container FrameLayout
if (findViewById(R.id.fragment_container) != null) {
// 不過铝量,如果我們要從先前的狀態(tài)還原,
// 則無需執(zhí)行任何操作而應(yīng)返回
// 否則就會(huì)得到重疊的 Fragment 银亲。
if (savedInstanceState != null) {
return;
}
// 創(chuàng)建一個(gè)要放入 Activity 布局中的新 Fragment
HeadlinesFragment firstFragment = new HeadlinesFragment();
// 如果此 Activity 是通過 Intent 發(fā)出的特殊指令來啟動(dòng)的慢叨,
// 請將該 Intent 的 extras 以參數(shù)形式傳遞給該 Fragment
firstFragment.setArguments(getIntent().getExtras());
// 將該 Fragment 添加到“fragment_container”FrameLayout 中
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();
}
}
}
用一個(gè) Fragment 替換另一個(gè) Fragment
- 替換Fragment的步驟和添加Fragment的步驟差不多,只不過add()換成replace()
- 當(dāng)你執(zhí)行替換或移除 Fragment 等 Fragment 事務(wù)時(shí)务蝠,最好能讓用戶向后導(dǎo)航和“撤消”所做更改拍谐。要通過 Fragment 事務(wù)允許用戶向后導(dǎo)航,你必須調(diào)用 addToBackStack()馏段,然后再執(zhí)行 FragmentTransaction轩拨。
- 當(dāng)你移除或替換 Fragment 并向返回堆棧添加事務(wù)時(shí),已移除的 Fragment 會(huì)停止(而不是銷毀)院喜。如果用戶向后導(dǎo)航亡蓉,還原該 Fragment,它會(huì)重新啟動(dòng)喷舀。如果你沒有向返回堆棧添加事務(wù)砍濒,那么該 Fragment 在移除或替換時(shí)就會(huì)被銷毀。
// 創(chuàng)建 Fragment 并為其添加一個(gè)參數(shù)硫麻,用來指定應(yīng)顯示的文章
ArticleFragment newFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// 將 fragment_container View 中的內(nèi)容替換為此 Fragment 爸邢,
// 然后將該事務(wù)添加到返回堆棧,以便用戶可以向后導(dǎo)航
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// 執(zhí)行事務(wù)
transaction.commit();
Communication with Other Fragment
- Fragment無法直接與Fragment通信庶香,但是可以通過Activity進(jìn)行通信甲棍。
Define an Interface
為了讓Fragment和Activity通信需要一下幾步:
- 在Fragment中定義一個(gè)接口,并且在Activity中實(shí)現(xiàn)這個(gè)接口
- Fragment在onAttach()方法中捕獲接口的實(shí)現(xiàn)
- 調(diào)用接口方法與activity進(jìn)行通信
這里是一個(gè)Fragment和Activity通信的例子
public class HeadlinesFragment extends ListFragment {
OnHeadlineSelectedListener mCallback;
// Container Activity must implement this interface
public interface OnHeadlineSelectedListener {
public void onArticleSelected(int position);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (OnHeadlineSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
...
}
現(xiàn)在Fragment通過調(diào)用onArticleSelected()方法(或者interface中其他的方法)就可以傳遞messages給activity了赶掖。
例如,以下Fragment中的方法當(dāng)用戶點(diǎn)擊一個(gè)菜單項(xiàng)時(shí)被調(diào)用七扰。fragment通過回調(diào)接口傳遞事件給父級activity奢赂。
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Send the event to the host activity
mCallback.onArticleSelected(position);
}
Implement the Interface
為了接收到來自fragment的事件,activity必須實(shí)現(xiàn)定義在Fragment的接口颈走。
public static class MainActivity extends Activity
implements HeadlinesFragment.OnHeadlineSelectedListener{
...
public void onArticleSelected(int position) {
// The user selected the headline of an article from the HeadlinesFragment
// Do something here to display that article
}
}
Deliver a Message to a Fragment
activity可以通過findFragmentById獲取Fragment實(shí)例膳灶,然后直接調(diào)用fragment的public方法。
舉個(gè)例子,假如上述的例子中的activity包含另一個(gè)fragment用于顯示item指定的回調(diào)方法中返回的數(shù)據(jù)轧钓。這樣序厉,activity可以將回調(diào)方法中收到的數(shù)據(jù)傳遞到其他的fragment中,并顯示出來毕箍。
public static class MainActivity extends Activity
implements HeadlinesFragment.OnHeadlineSelectedListener{
...
public void onArticleSelected(int position) {
// The user selected the headline of an article from the HeadlinesFragment
// Do something here to display that article
ArticleFragment articleFrag = (ArticleFragment)
getSupportFragmentManager().findFragmentById(R.id.article_fragment);
if (articleFrag != null) {
// If article frag is available, we're in two-pane layout...
// Call a method in the ArticleFragment to update its content
articleFrag.updateArticleView(position);
} else {
// Otherwise, we're in the one-pane layout and must swap frags...
// Create fragment and give it an argument for the selected article
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();
}
}
}