Android -- Handling back button press Inside Fragments

干货(1)

首先创建一个抽象类BackHandledFragment,该类有一个抽象方法onBackPressed(),所有BackHandledFragment的子类在onBackPressed方法中处理各自对Back事件的消费逻辑。onBackPressed返回布尔值,宿主FragmentActivity将会根据该方法的返回值判断子Fragment是否有消费Back事件。此外,宿主FragmentActivity还会保持一份当前Fragment的引用,当用户按下Back键时,宿主Activity会判断当前Fragment是否需要消费该事件,如果没有Fragment消费才会自己消费。

public abstract class BackHandledFragment extends Fragment {  
  
    protected BackHandledInterface mBackHandledInterface;  
      
    /** 
     * 所有继承BackHandledFragment的子类都将在这个方法中实现物理Back键按下后的逻辑 
     * FragmentActivity捕捉到物理返回键点击事件后会首先询问Fragment是否消费该事件 
     * 如果没有Fragment消息时FragmentActivity自己才会消费该事件 
     */  
    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,当前Fragment在栈顶  
        mBackHandledInterface.setSelectedFragment(this);  
    }  
      
}

宿主FragmentActivity需要继承BackHandledIntegerface,子Fragment会通过该接口告诉宿主FragmentActivity自己是当前屏幕可见的Fragment。

public interface BackHandledInterface {  
    public abstract void setSelectedFragment(BackHandledFragment selectedFragment);  
}

所以在Fragment的onCreate中会判断宿主FragmentActivity是否已继承了该接口。在Fragment的onStart()方法中就会调用该接口告诉宿主FragmentActivity自己是当前屏幕可见的Fragment。
宿主FragmentActivity就可以在onBackPressed()方法中对Back事件进行判断处理了。

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();  
            }  
        }  
    }  
}

干货(2)

在Fragment的onResume中通过View去监听。(要注意setFocusableInTouchMode()和requestFocus())

@Override
public void onResume() {

    super.onResume();

    getView().setFocusableInTouchMode(true);
    getView().requestFocus();
    getView().setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {

            if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){

                // handle back button

                return true;

            }

            return false;
        }
    });
}

我是天王盖地虎的分割线

 

 

 

参考:http://vinsol.com/blog/2014/10/01/handling-back-button-press-inside-fragments/

http://stackoverflow.com/questions/22552958/handling-back-press-when-using-fragments-in-android

你可能感兴趣的:(Fragment)