Fragment的addToBackStatck和進(jìn)出場(chǎng)動(dòng)畫,F(xiàn)ragment間數(shù)據(jù)傳遞

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;
    }
test1.gif

不知道啥原因,看回上面的解釋

同時(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)的效果:


test2.gif

分析一下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方法

test2.gif
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ù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。