一、问题现象
多层fragment叠加时,点击上层fragment会使下层fragment的控件对应点击事件响应,这种现象就是点击穿透。
对于这种情况,我们一般都是对baseFragment进行view的点击事件设置,以达到拦截所有页面上的空白处点击事件,以防止穿透到下层fragment。
二、解决方案
/** * 防止点击穿透 * @param view * @param savedInstanceState */ @Override public void onViewCreated(View view, Bundle savedInstanceState) { // 拦截触摸事件,防止泄露下去 view.setOnTouchListener(this); }
完整的Fragment代码:
public abstract class BaseFragment extends Fragment implements View.OnTouchListener { /** * 贴附的activity */ protected FragmentActivity mActivity; /** * 根view */ protected View mRootView; /** * 是否对用户可见 */ protected boolean mIsVisible; /** * 是否加载完成 * 当执行完oncreatview,View的初始化方法后方法后即为true */ protected boolean mIsPrepare; @Override public void onAttach(Context context) { super.onAttach(context); mActivity = (FragmentActivity) getActivity(); } public void startToFragment(Context context, int container, Fragment newFragment){ FragmentManager manager = getFragmentManager(); FragmentTransaction transaction = manager.beginTransaction(); transaction.replace(container,newFragment); transaction.addToBackStack(context.getClass().getName()); transaction.commit(); } @Override @Nullable public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { mRootView = inflater.inflate(setLayoutResouceId(), container, false); initData(getArguments()); initView(); mIsPrepare = true; onLazyLoad(); setListener(); return mRootView; } /** * 初始化数据 * * @param arguments 接收到的从其他地方传递过来的参数*/ protected void initData(Bundle arguments) { } /** * 初始化View*/ protected void initView() { } /** * 设置监听事件*/ protected void setListener() { } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); this.mIsVisible = isVisibleToUser; if (isVisibleToUser) { onVisibleToUser(); } } /** * 用户可见时执行的操作*/ protected void onVisibleToUser() { if (mIsPrepare && mIsVisible) { onLazyLoad(); } } /** * 懒加载,仅当用户可见切view初始化结束后才会执行*/ protected void onLazyLoad() { } @SuppressWarnings("unchecked") protected <T extends View> T findViewById(int id) { if (mRootView == null) { return null; } return (T) mRootView.findViewById(id); } /** * 设置根布局资源id*/ protected abstract int setLayoutResouceId(); /** * 防止点击穿透*/ @Override public void onViewCreated(View view, Bundle savedInstanceState) { // 拦截触摸事件,防止泄露下去 view.setOnTouchListener(this); } @Override public boolean onTouch(View v, MotionEvent event) { return true; } }