package se.alexanderblom.delicious.view; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.ViewConfiguration; import android.widget.LinearLayout; public class InterceptLinearLayout extends LinearLayout { public interface OnInterceptListener { boolean isFlyoutOpen(); void shouldClose(); void shouldOpen(); } private OnInterceptListener interceptListener; private int edgeSlop; private int touchSlop; private int ignoreIndex = -1; private boolean watchingGesture = false; private float startX; public InterceptLinearLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public InterceptLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); init(); } public InterceptLinearLayout(Context context) { super(context); init(); } private void init() { ViewConfiguration config = ViewConfiguration.get(getContext()); edgeSlop = config.getScaledEdgeSlop(); touchSlop = config.getScaledTouchSlop(); } @Override public boolean onTouchEvent(MotionEvent event) { if (interceptListener == null) { return false; } if (event.findPointerIndex(ignoreIndex) != -1) { return false; } int action = event.getActionMasked(); if (interceptListener.isFlyoutOpen()) { // It's open, close it when the user releases his finger if (action == MotionEvent.ACTION_UP) { interceptListener.shouldClose(); } } else if (action == MotionEvent.ACTION_MOVE && watchingGesture) { // It's closed, open if we drag right float distance = event.getRawX() - startX; if (distance > touchSlop) { if (interceptListener != null) { interceptListener.shouldOpen(); // Make sure we don't handle this events up later ignoreIndex = event.getPointerId(0); } } } return true; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { // New touch event, don't ignore it ignoreIndex = -1; watchingGesture = false; if (interceptListener == null) { return false; } if (interceptListener.isFlyoutOpen()) { // Steal all the events return true; } else if (ev.getActionMasked() == MotionEvent.ACTION_DOWN && ev.getX() < edgeSlop) { // If it's closed, only steal events close to the left edge startX = ev.getRawX(); watchingGesture = true; return true; } else { return false; } } public void setOnInterceptListener(OnInterceptListener listener) { interceptListener = listener; } }