Fragment表現(xiàn)Activity中用戶界面的一個(gè)行為或者是一部分。你可以在一個(gè)單獨(dú)的activity上把多個(gè)fragment組合成為一個(gè)多區(qū)域的UI,并且可以在多個(gè)activity中再使用。你可以認(rèn)為fragment是activity的一個(gè)模塊零件,它有自己的生命周期,接收它自己的輸入事件,并且可以在activity運(yùn)行時(shí)添加或者刪除。
Fragment必須總是被嵌入到一個(gè)activity之中,并且fragment的生命周期直接受其宿主activity的生命周期的影響。例如,一旦activity被暫停,它里面所有的fragment也被暫停,一旦activity被銷毀,它里面所有的fragment也被銷毀。然而,當(dāng)activity正在運(yùn)行時(shí)(處于resumed的生命周期狀態(tài)),你可以單獨(dú)的操控每個(gè)fragment,比如添加或者刪除。當(dāng)你執(zhí)行這樣一項(xiàng)事務(wù)時(shí),可以將它添加到后臺(tái)的一個(gè)棧中,這個(gè)棧由activity管理著——activity里面的每個(gè)后臺(tái)棧內(nèi)容實(shí)體是fragment發(fā)生過(guò)的一條事務(wù)記錄。這個(gè)后臺(tái)棧允許用戶通過(guò)按BACK鍵回退一項(xiàng)fragment事務(wù)(往后導(dǎo)航)。
當(dāng)你添加一個(gè)fragment作為某個(gè)activity布局的一部分時(shí),它就存在于這個(gè)activity視圖體系內(nèi)部的ViewGroup之中,并且定義了它自己的視圖布局。你可以通過(guò)在activity布局文件中聲明fragment,用<fragment>元素把fragment插入到activity的布局中,或者是用應(yīng)用程序源碼將它添加到一個(gè)存在的ViewGroup中。然而,fragment并不是一個(gè)定要作為activity布局的一部分;fragment也可以為activity隱身工作.
Fragment使用FragmentTransaction來(lái)操作的,從activity上獲取FragmentTransaction:
主要的操作都是FragmentTransaction的方法
FragmentTransaction transaction = fm.benginTransatcion();//開啟一個(gè)事務(wù)
transaction.add()
往Activity中添加一個(gè)Fragment
transaction.remove()
從Activity中移除一個(gè)Fragment,如果被移除的Fragment沒有添加到回退棧(回退棧后面會(huì)詳細(xì)說(shuō)),這個(gè)Fragment實(shí)例將會(huì)被銷毀。
transaction.replace()
使用另一個(gè)Fragment替換當(dāng)前的,實(shí)際上就是remove()然后add()的合體~
transaction.hide()
隱藏當(dāng)前的Fragment,僅僅是設(shè)為不可見,并不會(huì)銷毀
transaction.show()
顯示之前隱藏的Fragment
transaction.commit()
提交事務(wù)
在Activity,如果一個(gè)activity跳轉(zhuǎn)(不銷毀的情況)到另外一個(gè)activity,按下back鍵就返回到上個(gè)activity,Fragment在提交事務(wù)之前調(diào)用:
addToBackStatck(@null String name)
在調(diào)用commit()之前,為了將事務(wù)添加到fragment事務(wù)后臺(tái)棧中,調(diào)用addToBackStatck()。這個(gè)后臺(tái)棧由activity管理,并且允許用戶通過(guò)按BACK鍵回退到前一個(gè)fragment狀態(tài)。(相當(dāng)于反向操作)
repalce()
替換原來(lái)的fragment添加新的fragment,被替換的Fragment如果沒有調(diào)用addToBackStatck()直接銷毀,如果添加了addToBackStatck()-生命周期走到onDestroyView(),在堆棧待命
使用addToBackStatck和repalce舉個(gè)例子
public static void replaceFragment(Fragment from, Fragment to) {
if (from != to) {
FragmentTransaction transaction = from.getActivity().getSupportFragmentManager().beginTransaction();
transaction.addToBackStack(to.getClass().getName());
transaction.replace(R.id.framelayout, to, to.getClass().getName()).commit();
}
}
OneFragment
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.one_fragment, null);
button = view.findViewById(R.id.tv1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// skip();
// skipAddToBackStack();
// skipAddToBackStackan();
replace();
}
});
Toast.makeText(getActivity(), "重新加載", Toast.LENGTH_SHORT).show();
return view;
}
public void replace() {
FragmentUtils.replaceFragment(this, new TwoFragment());
}
TwoFragment
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.two_fragment, null);
view.findViewById(R.id.back).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
popBack();//fragment之間返回
}
});
return view;
}
不知道啥原因,看回上面的解釋
同時(shí)fragmentTransaction的setCustomAnimations方法設(shè)置fragment的進(jìn)場(chǎng)動(dòng)畫。和Activity的 overridePendingTransition();
大概來(lái)說(shuō)前兩個(gè)參數(shù)普通進(jìn)出場(chǎng)動(dòng)畫,后兩個(gè)參數(shù)進(jìn)出堆棧動(dòng)畫
public abstract FragmentTransaction setCustomAnimations(@AnimRes int enter,
@AnimRes int exit);
public abstract FragmentTransaction setCustomAnimations(@AnimRes int enter,
@AnimRes int exit, @AnimRes int popEnter, @AnimRes int popExit);
Fragment進(jìn)出的場(chǎng)的效果:
分析一下Fragment進(jìn)出場(chǎng)動(dòng)畫,
public static void skipAddToBackStackan(Fragment from, Fragment to) {
if (from != to) {
FragmentTransaction transaction = from.getActivity().getSupportFragmentManager().beginTransaction();
transaction.addToBackStack(to.getClass().getName());
transaction.setCustomAnimations(R.anim.fragment_in, R.anim.fragment_out, R.anim.slide_in_right, R.anim.slide_out_right);
if (to.isAdded()) {
transaction.hide(from).show(to).commitAllowingStateLoss();
} else {
transaction.hide(from).add(R.id.framelayout, to, to.getClass().getName()).commitAllowingStateLoss();
}
}
}
fragment_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="100%p"
android:toXDelta="0"
/>
</set>
fragment_out.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="0"
android:toXDelta="-100%p" />
</set>
slide_in_right.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="-100%p"
android:toXDelta="0"
/>
</set>
slide_out_right.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="0"
android:toXDelta="100%p" />
</set>
簡(jiǎn)單的來(lái)說(shuō),事務(wù)進(jìn)堆棧的時(shí)候,屬于普通進(jìn)出場(chǎng)效果,出棧的時(shí)候,屬于進(jìn)出堆棧的效果
Fragment之間的數(shù)據(jù)傳遞--它們的數(shù)據(jù)傳遞,感覺就是小偷去農(nóng)田偷菜,偷到回自己家煮。
主要步驟(該步驟必須在fragmentTransaction.commit()之前完成):
1.創(chuàng)建一個(gè)fragment實(shí)例
2.創(chuàng)建一個(gè)Bundle 對(duì)象(其為鍵值對(duì)存儲(chǔ),可以理解為一個(gè)Map<K,V>): Bundle bundle = new Bundle();
3.向bundle中傳值:bundle.putString(key,values);
4.將bundle通過(guò)setArguments(bundle)方法設(shè)置進(jìn)fragment:fragment.setArguments(bundle);
5.獲取數(shù)據(jù)getArguments().getBunlde(),getArguments().getInt()......各種get方法
public class OneFragment extends Fragment {
private Button button;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.one_fragment, null);
button = view.findViewById(R.id.tv1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// skip();
// skipAddToBackStack();
skipAddToBackStackan();
// replace();
}
});
return view;
}
public void skipAddToBackStackan() {
TwoFragment twoFragment = new TwoFragment();
Bundle bundle = new Bundle();
bundle.putInt("key", 1);
twoFragment.setArguments(bundle);
FragmentUtils.skipAddToBackStackan(this, twoFragment);
}
public class TwoFragment extends Fragment {
private Activity activity;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.two_fragment, null);
view.findViewById(R.id.tv2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(activity, ""+getArguments().getInt("key"), Toast.LENGTH_SHORT).show();
}
});
return view;
}
再續(xù)