Fragment表現(xiàn)Activity中用戶界面的一個行為或者是一部分。你可以在一個單獨的activity上把多個fragment組合成為一個多區(qū)域的UI焚鲜,并且可以在多個activity中再使用掌唾。你可以認為fragment是activity的一個模塊零件放前,它有自己的生命周期,接收它自己的輸入事件糯彬,并且可以在activity運行時添加或者刪除凭语。
Fragment必須總是被嵌入到一個activity之中,并且fragment的生命周期直接受其宿主activity的生命周期的影響撩扒。例如似扔,一旦activity被暫停,它里面所有的fragment也被暫停搓谆,一旦activity被銷毀炒辉,它里面所有的fragment也被銷毀。然而泉手,當activity正在運行時(處于resumed的生命周期狀態(tài))黔寇,你可以單獨的操控每個fragment,比如添加或者刪除斩萌。當你執(zhí)行這樣一項事務(wù)時缝裤,可以將它添加到后臺的一個棧中,這個棧由activity管理著——activity里面的每個后臺棧內(nèi)容實體是fragment發(fā)生過的一條事務(wù)記錄术裸。這個后臺棧允許用戶通過按BACK鍵回退一項fragment事務(wù)(往后導航)倘是。
當你添加一個fragment作為某個activity布局的一部分時,它就存在于這個activity視圖體系內(nèi)部的ViewGroup之中袭艺,并且定義了它自己的視圖布局搀崭。你可以通過在activity布局文件中聲明fragment,用<fragment>元素把fragment插入到activity的布局中猾编,或者是用應用程序源碼將它添加到一個存在的ViewGroup中瘤睹。然而,fragment并不是一個定要作為activity布局的一部分答倡;fragment也可以為activity隱身工作.
Fragment使用FragmentTransaction來操作的轰传,從activity上獲取FragmentTransaction:
主要的操作都是FragmentTransaction的方法
FragmentTransaction transaction = fm.benginTransatcion();//開啟一個事務(wù)
transaction.add()
往Activity中添加一個Fragment
transaction.remove()
從Activity中移除一個Fragment,如果被移除的Fragment沒有添加到回退棧(回退棧后面會詳細說)瘪撇,這個Fragment實例將會被銷毀获茬。
transaction.replace()
使用另一個Fragment替換當前的,實際上就是remove()然后add()的合體~
transaction.hide()
隱藏當前的Fragment倔既,僅僅是設(shè)為不可見恕曲,并不會銷毀
transaction.show()
顯示之前隱藏的Fragment
transaction.commit()
提交事務(wù)
在Activity,如果一個activity跳轉(zhuǎn)(不銷毀的情況)到另外一個activity,按下back鍵就返回到上個activity,Fragment在提交事務(wù)之前調(diào)用:
addToBackStatck(@null String name)
在調(diào)用commit()之前渤涌,為了將事務(wù)添加到fragment事務(wù)后臺棧中佩谣,調(diào)用addToBackStatck()。這個后臺棧由activity管理实蓬,并且允許用戶通過按BACK鍵回退到前一個fragment狀態(tài)茸俭。(相當于反向操作)
repalce()
替換原來的fragment添加新的fragment吊履,被替換的Fragment如果沒有調(diào)用addToBackStatck()直接銷毀,如果添加了addToBackStatck()-生命周期走到onDestroyView(),在堆棧待命
使用addToBackStatck和repalce舉個例子
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;
}
不知道啥原因调鬓,看回上面的解釋
同時fragmentTransaction的setCustomAnimations方法設(shè)置fragment的進場動畫艇炎。和Activity的 overridePendingTransition();
大概來說前兩個參數(shù)普通進出場動畫,后兩個參數(shù)進出堆棧動畫
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進出的場的效果:
分析一下Fragment進出場動畫,
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>
簡單的來說腾窝,事務(wù)進堆棧的時候冕臭,屬于普通進出場效果,出棧的時候燕锥,屬于進出堆棧的效果
Fragment之間的數(shù)據(jù)傳遞--它們的數(shù)據(jù)傳遞,感覺就是小偷去農(nóng)田偷菜悯蝉,偷到回自己家煮归形。
主要步驟(該步驟必須在fragmentTransaction.commit()之前完成):
1.創(chuàng)建一個fragment實例
2.創(chuàng)建一個Bundle 對象(其為鍵值對存儲,可以理解為一個Map<K,V>): Bundle bundle = new Bundle();
3.向bundle中傳值:bundle.putString(key,values);
4.將bundle通過setArguments(bundle)方法設(shè)置進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ù)