美文网首页
DrawerLayout点击事件向下传递

DrawerLayout点击事件向下传递

作者: 蒙面乌鸦 | 来源:发表于2019-06-20 15:45 被阅读0次

使用DrawerLayout可以很方便的完成抽屉布局,但如果你的DrawerLayout是覆盖在另一个布局之上的,那DrawerLayout下面的所有界面都无法收到onTouch事件,翻阅源码,查看DrawerLayout的onTouch方法:

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        ...
        boolean wantTouchEvents = true;
        ...
        return wantTouchEvents;
    }

发现该方法内有一个wantTouchEvents参数,并且设为默认值后不做任何修改直接返回,也就是说DrawerLayout将会拦截所有点击事件不向下传递。

到这里很自然的会想到重写该方法,将返回值修改为false不就可以让底层界面收到点击事件了?于是有了修改如下:

public class CustomDrawerLayout extends DrawerLayout {
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        return false;
    }
}

修改完后发现,确实事件可以正常向下传递了,但也引发了其他问题,抽屉不能正常滑动了,说明我们不能一股脑的把事件都向下传递,如果当前正在滑动抽屉时事件不传递。针对此问题,我们需要解决两个问题:

1.我们知道抽屉是在滑动边缘位置时触发的,所以我们需要判断事件是否落在边缘区域
2.如果当前抽屉正处于滑动状态,则事件不向下传递

针对第一点,查看源码发现,边缘宽度的定义放在ViewDragHelper中:

public class ViewDragHelper {
    private static final int EDGE_SIZE = 20; // dp
    private int mEdgeSize;
    private ViewDragHelper(@NonNull Context context, @NonNull ViewGroup forParent,@NonNull Callback cb) {
        ...
        final float density = context.getResources().getDisplayMetrics().density;
        mEdgeSize = (int) (EDGE_SIZE * density + 0.5f);
        ...
    }
}

针对第二点,DrawerLayout有两个public方法可以判断:

public boolean isDrawerOpen(@EdgeGravity int drawerGravity) {}
public boolean isDrawerVisible(@EdgeGravity int drawerGravity) {}

传入抽屉方向即可获取当前是否有展示抽屉

最终可运行代码如下:

public class CustomDrawerLayout extends DrawerLayout {
    private static final int EDGE_SIZE = 20; // dp
    private float mEdgeSize;

    public CustomDrawerLayout(@NonNull Context context) {
        this(context, null);
    }

    public CustomDrawerLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomDrawerLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        final float density = context.getResources().getDisplayMetrics().density;
        mEdgeSize = EDGE_SIZE * density + 0.5f;
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean superResult = super.onTouchEvent(event);

        if (isEdge(event) || isDrawerOpen(GravityCompat.START) || isDrawerVisible(GravityCompat.START) 
                || isDrawerOpen(GravityCompat.END) || isDrawerVisible(GravityCompat.END)) {
            return superResult;
        } else {
            return false;
        }
    }

    private boolean isEdge(MotionEvent event) {
        return event.getX() <= mEdgeSize || event.getX() >= (getWidth() - mEdgeSize);
    }
}

相关文章

网友评论

      本文标题:DrawerLayout点击事件向下传递

      本文链接:https://www.haomeiwen.com/subject/mrgdqctx.html