優(yōu)雅的讓Fragment監(jiān)聽(tīng)返回鍵

Activity 比較容易監(jiān)聽(tīng)物理鍵返回事件(onBackPressed);Fragment卻不能

假設(shè)一個(gè)FragmentActivity包含3個(gè)Fragment,用戶一般期望在返回時(shí),逐層返回到FragmentActivity,當(dāng)然我們可以將每個(gè)Fragment對(duì)應(yīng)的Transaction放到BackStack當(dāng)中,但是如果每個(gè)Fragment有對(duì)返回事件的特殊消費(fèi),如何優(yōu)雅的實(shí)現(xiàn)了?

  1. 首先創(chuàng)建一個(gè)抽象類BaseHandleFragment,該類有一個(gè)抽象方法onBackPressed方法,所有子Fragment繼承于他,實(shí)現(xiàn)該方法處理各自對(duì)Back事件的消費(fèi)邏輯,該方法返回一個(gè)布爾值,宿主FragmentActivity將會(huì)根據(jù)該方法返回值判斷子Fragment是否有消費(fèi)Back事件
public abstract class BackHandledFragment extends Fragment {

    protected BackHandledInterface mBackHandledInterface;
    
    /**
     * 所有繼承BackHandledFragment的子類都將在這個(gè)方法中實(shí)現(xiàn)物理Back鍵按下后的邏輯
     * FragmentActivity捕捉到物理返回鍵點(diǎn)擊事件后會(huì)首先詢問(wèn)Fragment是否消費(fèi)該事件
     * 如果沒(méi)有Fragment消息時(shí)FragmentActivity自己才會(huì)消費(fèi)該事件
     */
    protected abstract boolean onBackPressed();
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(!(getActivity() instanceof BackHandledInterface)){
            throw new ClassCastException("Hosting Activity must implement BackHandledInterface");
        }else{
            this.mBackHandledInterface = (BackHandledInterface)getActivity();
        }
    }
    
    @Override
    public void onStart() {
        super.onStart();
        //告訴FragmentActivity,當(dāng)前Fragment在棧頂
        mBackHandledInterface.setSelectedFragment(this);
    }
    
}

2.宿主Activity將會(huì)保存一份當(dāng)前Fragment的引用,當(dāng)用戶按下Back鍵時(shí),Activity會(huì)通過(guò)上述1中onBackPressed的返回值,判斷該Fragment是否有消費(fèi)該事件,沒(méi)有才會(huì)自己消費(fèi)

3.宿主FragmentActivity需要繼承BackHandleInterface,子Fragment會(huì)通過(guò)該接口告訴宿主Activity自己是當(dāng)前屏幕可見(jiàn)的Fragment

public interface BackHandledInterface {

    public abstract void setSelectedFragment(BackHandledFragment selectedFragment);
}
public class MainActivity extends FragmentActivity implements BackHandledInterface{

    private BackHandledFragment mBackHandedFragment;
    private boolean hadIntercept;

    @Override
    public void setSelectedFragment(BackHandledFragment selectedFragment) {
        this.mBackHandedFragment = selectedFragment;
    }
    
    @Override
    public void onBackPressed() {
        if(mBackHandedFragment == null || !mBackHandedFragment.onBackPressed()){
            if(getSupportFragmentManager().getBackStackEntryCount() == 0){
                super.onBackPressed();
            }else{
                getSupportFragmentManager().popBackStack();
            }
        }
    }
}

總結(jié)一下:
每個(gè)Fragment的onCreate方法中,會(huì)判斷宿主Activity是否實(shí)現(xiàn)了上述3中所說(shuō)的接口,在Fragment的onStart方法中,通過(guò)Fragment 獲取Activity 引用,然后調(diào)用該Activity實(shí)現(xiàn)的接口方法告知宿主FragmentActivity自己是當(dāng)前屏幕可見(jiàn)的Fragment,宿主Activity就可以在onBackPressed 方法中對(duì)Back事件進(jìn)行判斷處理了

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容