让Fragment监听返回键

Activity可以很容易的得到物理返回键的监听事件,而Fragment却不能。所以使用到了以下的方法。

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

 1 public abstract class BackHandledFragment extends Fragment {  3 protected BackHandledInterface mBackHandledInterface;  5 /**  6  * 所有继承BackHandledFragment的子类都将在这个方法中实现物理Back键按下后的逻辑  7  * FragmentActivity捕捉到物理返回键点击事件后会首先询问Fragment是否消费该事件  8  * 如果没有Fragment消息时FragmentActivity自己才会消费该事件  9 */ 10 protected abstract boolean onBackPressed(); 11 12  @Override 13 public void onCreate(Bundle savedInstanceState) { 14 super.onCreate(savedInstanceState); 15 // instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例 16 if(!(getActivity() instanceof BackHandledInterface)){ 17 throw new ClassCastException("Hosting Activity must implement BackHandledInterface"); 18 }else{ 19 this.mBackHandledInterface = (BackHandledInterface)getActivity(); 20  } 21  } 22 23  @Override 24 public void onStart() { 25 super.onStart(); 26 //告诉FragmentActivity,当前Fragment在栈顶 27 mBackHandledInterface.setSelectedFragment(this); 28  } 29 30 }

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

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

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

 1 public class MainActivity extends FragmentActivity implements BackHandledInterface{

 3     private BackHandledFragment mBackHandedFragment;  4     private boolean hadIntercept;  

 6     private Button mBtn;  7     

 8  @Override  9     protected void onCreate(Bundle savedInstanceState) { 10         super.onCreate(savedInstanceState); 11  setContentView(R.layout.activity_main); 12         this.mBtn = (Button)findViewById(R.id.btn); 13         this.mBtn.setOnClickListener(new OnClickListener() { 14             

15  @Override 16             public void onClick(View v) { 17                 MyFragment f = new MyFragment(); 18                 FragmentManager fm = getSupportFragmentManager(); 19                 FragmentTransaction ft = fm.beginTransaction(); 20  ft.replace(R.id.container, f); 21                 ft.addToBackStack("tag"); 22  ft.commit(); 23  } 24  }); 25  } 26 

27  @Override 28 public void setSelectedFragment(BackHandledFragment selectedFragment) { 29 this.mBackHandedFragment = selectedFragment; 30  } 31 32  @Override 33 public void onBackPressed() { 34 if(mBackHandedFragment == null || !mBackHandedFragment.onBackPressed()){ 35 if(getSupportFragmentManager().getBackStackEntryCount() == 0){ 36 super.onBackPressed(); 37 }else{ 38  getSupportFragmentManager().popBackStack(); 39  } 40  } 41  } 42 }

 

在Fragment中调用使用。

 1 public class MyFragment extends BackHandledFragment {

 3     private boolean hadIntercept;

 5  @Override  6 public View onCreateView(LayoutInflater inflater,  7  @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {  8 return getLayoutInflater(savedInstanceState).inflate(R.layout.fragment_a, null);  9  } 10     

11  @Override 12 protected boolean onBackPressed() { 13 if(hadIntercept){ 14 return false; 15 }else{ 16  Toast.makeText(getActivity(), "Click MyFragment", Toast.LENGTH_SHORT).show(); 17 hadIntercept = true; 18 return true; 19  } 20  } 21 

22 }

 

Demo:https://github.com/mxy1228/FragmentHandleBackDemo/

你可能感兴趣的:(Fragment)