有些时候在Activity中监听的返回键,但此Activity中的Fragment并不想返回键实现同样的功能,所以需要Fragment中监听返回键。令人失望的是Fragment并不能直接对物理返回键进行监听,所以需要自己另外去进行代码实现。
下面的代码适合如下情况:一个Activity中实现了连续两次点击物理返回键退出应用程序,但此Activity中的Fragment物理返回键功能是从Fragment栈中移除此界面。
宿主FragmentActivity要实现的接口,以便确定当前屏幕可见的Fragment
public interface BackHandledInterface {
public abstract void setSelectedFragment(BackHandledFragment selectedFragment);
}
主界面的FragmentActivity
public class MainActivity extends FragmentActivity implements BackHandledInterface{
private BackHandledFragment mBackHandedFragment;
private Button mBtn;
/** 上次点击返回键的时间 */
private long lastBackPressed;
/** 上次点击返回键的时间 */
private static final int QUIT_INTERVAL = 2000;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.mBtn = (Button)findViewById(R.id.btn);
this.mBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
MyFragment f = new MyFragment();
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.container, f);
ft.addToBackStack("tag");
ft.commit();
}
});
}
@Override
public void setSelectedFragment(BackHandledFragment selectedFragment) {
this.mBackHandedFragment = selectedFragment;
}
@Override
public void onBackPressed() {
if(mBackHandedFragment == null || !mBackHandedFragment.onBackPressed()){
if(getSupportFragmentManager().getBackStackEntryCount() == 0){
long backPressed = System.currentTimeMillis();
if (backPressed - lastBackPressed > QUIT_INTERVAL) {
lastBackPressed = backPressed;
Toast.makeText(this, "再按一次退出", Toast.LENGTH_LONG).show();
} else {
finish();
System.exit(0);
}
} else {
getSupportFragmentManager().popBackStack();
}
}
}
}
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);
}
}
显示在当前屏幕的Fragment
public class MyFragment extends BackHandledFragment {
private boolean hadIntercept;
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return getLayoutInflater(savedInstanceState).inflate(R.layout.fragment_a, null);
}
@Override
protected boolean onBackPressed() {
if(hadIntercept){
return false;
}else{
getFragmentManager().popBackStack();
hadIntercept = true;
return true;
}
}
}
如果要在Fragment中的物理返回键实现其他功能,则可根据此代码另行改进。
思路来源于另一位博友的优雅的让Fragment监听返回键 ,感谢这位博友。