左滑退出activity,处理了部分事件分发

自定义布局

/**
 * 左滑退出activity
 */

public class LeftSwipeBackLayout extends ViewGroup {

    private static final int FULL_ALPHA = 255;
    private static final int MIN_FLING_VELOCITY = 400; // dips per second
    private static final int OVERSCROLL_DISTANCE = 10;
    private static final int DEFAULT_SCRIM_COLOR = 0x99000000;
    /**
     * Default threshold of scroll
     */
    private static final float DEFAULT_SCROLL_THRESHOLD = 0.3f;
    private ViewDragHelper viewDragHelper;
    private ViewDragHelperCallBack callBack;
    private Drawable leftShadow;
    private float scrimOpacity;
    private boolean enableSwipeBack;
    private float scrollPercent;
    private boolean inLayout;
    private View contentView; //this view is the child of LeftSwipeBackLayout
    private Rect tmpRect;
    private int scrimColor;
    private Activity activity;
    private View scrollChildView;
    private int horizontalDragRange;
    private int contentLeft;
    private int contentTop;
    private float scrollThreshold;
    private float initialX;
    private float initialY;

    public LeftSwipeBackLayout(Context context) {
        this(context, null);
    }

    public LeftSwipeBackLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        tmpRect = new Rect();
        scrollThreshold = DEFAULT_SCROLL_THRESHOLD;
        callBack = new ViewDragHelperCallBack();
        viewDragHelper = ViewDragHelper.create(this, 1.0f, callBack);
        scrimColor = DEFAULT_SCRIM_COLOR;
        leftShadow = ContextCompat.getDrawable(context, R.drawable.shadow_left);
        final float density = getResources().getDisplayMetrics().density;
        viewDragHelper.setMinVelocity(MIN_FLING_VELOCITY * density);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (getChildCount() > 1) {
            throw new IllegalStateException("SwipeBackLayout must contains only one direct child.");
        }
        if (getChildCount() > 0) {
            int measureWidth = MeasureSpec.makeMeasureSpec(getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), MeasureSpec.EXACTLY);
            int measureHeight = MeasureSpec.makeMeasureSpec(getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), MeasureSpec.EXACTLY);
            getChildAt(0).measure(measureWidth, measureHeight);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        inLayout = true;
        if (contentView != null) {
            contentView.layout(contentLeft, contentTop, contentLeft + contentView.getMeasuredWidth(), contentTop + contentView.getMeasuredHeight());
        }
        inLayout = false;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        horizontalDragRange = w;
    }

    @Override
    public void requestLayout() {
        if (!inLayout) {
            super.requestLayout();
        }
    }

    @Override
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        final boolean drawContent = (child == contentView);
        boolean ret = super.drawChild(canvas, child, drawingTime);
        if (scrimOpacity > 0f && drawContent && viewDragHelper.getViewDragState() != ViewDragHelper.STATE_IDLE) {
            drawShadow(canvas, child);
            drawScrim(canvas, child);
        }
        return ret;
    }

    private void drawShadow(Canvas canvas, View child) {
        final Rect childRect = tmpRect;
        child.getHitRect(childRect);
        leftShadow.setBounds(childRect.left - leftShadow.getIntrinsicWidth(), childRect.top, childRect.left, childRect.bottom);
        leftShadow.setAlpha((int) (FULL_ALPHA * scrimOpacity));
        leftShadow.draw(canvas);
    }

    private void drawScrim(Canvas canvas, View child) {
        final int baseAlpha = (scrimColor & 0xff000000) >>> 24;
        final int alpha = (int) (baseAlpha * scrimOpacity);
        final int color = alpha << 24 | (scrimColor & 0xffffff);
        canvas.clipRect(0, 0, child.getLeft(), getHeight());
        canvas.drawColor(color);
    }

    @Override
    public void computeScroll() {
        scrimOpacity = 1 - scrollPercent;
        if (viewDragHelper.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(this);
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean handled = super.onInterceptTouchEvent(ev);
        if (enableSwipeBack) {
            viewDragHelper.shouldInterceptTouchEvent(ev);
            if (!checkHorizontalScrollToRight()) {
                handled = computeGestureStandard(ev);
            }
        } else {
            viewDragHelper.cancel();
        }
        return handled;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!enableSwipeBack) {
            return false;
        }
        viewDragHelper.processTouchEvent(event);
        return true;
    }

    private boolean computeGestureStandard(MotionEvent ev) {
        boolean ret = false;
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                initialX = ev.getX();
                initialY = ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                float deltaX = Math.abs((ev.getX() - initialX));
                float deltaY = Math.abs((ev.getY() - initialY));
                ret = ev.getX() > initialX && deltaX > deltaY && deltaY < 24;
                initialX = ev.getX();
                initialY = ev.getY();
                break;
            case MotionEvent.ACTION_UP:
                initialX = ev.getX();
                initialY = ev.getY();
                break;
        }
        return ret;
    }

    private boolean checkHorizontalScrollToRight() { //check the view could move to right direction
        return ViewCompat.canScrollHorizontally(scrollChildView, -1);
    }

    /**
     * control swiping back on or off
     *
     * @param enableSwipeBack
     */
    public void setEnableSwipeBack(boolean enableSwipeBack) {
        this.enableSwipeBack = enableSwipeBack;
    }

    /**
     * Set scroll threshold, we will close the activity, when scrollPercent over
     * this value
     *
     * @param threshold
     */
    public void setScrollThreshold(float threshold) {
        if (threshold >= 1.0f || threshold <= 0) {
            throw new IllegalArgumentException("Threshold value should be between 0 and 1.0");
        }
        scrollThreshold = threshold;
    }

    /**
     * Set up contentView which will be moved by user gesture
     *
     * @param view
     */
    private void setContentView(View view) {
        contentView = view;
    }

    public void attachToActivity(Activity activity) {
        this.activity = activity;
        TypedArray a = activity.getTheme().obtainStyledAttributes(new int[]{android.R.attr.windowBackground});
        int background = a.getResourceId(0, android.R.color.black);
        a.recycle();
        // add the swipeLayout outermost layer
        ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView();
        final ViewGroup decorChild = (ViewGroup) decor.getChildAt(0);
        scrollChildView = decorChild;
        decor.post(new Runnable() {
            @Override
            public void run() {
                findScrollChildView(decorChild);
            }
        });
        decorChild.setBackgroundResource(background);
        decor.removeView(decorChild);
        this.addView(decorChild);
        this.setContentView(decorChild);
        decor.addView(this);
    }

    private void findScrollChildView(View view) {
        if (view instanceof ViewGroup) {
            ViewGroup parent = (ViewGroup) view;
            if (parent.getChildCount() > 0) {
                for (int i = 0; i < parent.getChildCount(); i++) {
                    View child = parent.getChildAt(i);
                    if (ViewCompat.canScrollHorizontally(child, 1) || ViewCompat.canScrollHorizontally(child, -1)) {
                        scrollChildView = child;
                        break;
                    }
                    findScrollChildView(child);
                }
            }
        }
    }

    private class ViewDragHelperCallBack extends ViewDragHelper.Callback {

        private boolean isScrollOverValid;

        @Override
        public boolean tryCaptureView(View child, int pointerId) {
            return child == contentView && enableSwipeBack;
        }

        @Override
        public int getViewHorizontalDragRange(View child) {
            return horizontalDragRange;
        }

        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
            int result = 0;
            if (!ViewCompat.canScrollHorizontally(scrollChildView, -1) && left > 0) { //left boundary
                final int leftBound = getPaddingLeft();
                final int rightBound = horizontalDragRange;
                result = Math.min(Math.max(leftBound, left), rightBound);
            }
            return result;
        }

        @Override
        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
            super.onViewPositionChanged(changedView, left, top, dx, dy);
            scrollPercent = Math.abs((float) left / (contentView.getWidth() + leftShadow.getIntrinsicWidth()));
            contentLeft = left;
            contentTop = top;
            invalidate();
            if (scrollPercent < scrollThreshold && !isScrollOverValid) {
                Utils.convertActivityToTranslucent(activity);
                isScrollOverValid = true;
            }
            if (viewDragHelper.getViewDragState() == ViewDragHelper.STATE_DRAGGING && scrollPercent >= scrollThreshold && isScrollOverValid) {
                isScrollOverValid = false;
            }
            if (scrollPercent >= 1) {
                if (!activity.isFinishing()) {
                    activity.finish();
                    activity.overridePendingTransition(0, 0);
                }
            }
        }

        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {
            final int childWidth = releasedChild.getWidth();
            int left;
            int top = 0;
            left = xvel > 0 || xvel == 0 && scrollPercent > scrollThreshold ? childWidth + leftShadow.getIntrinsicWidth() + OVERSCROLL_DISTANCE : 0;
            viewDragHelper.settleCapturedViewAt(left, top); //If you release, it will finish or back to origin
            invalidate();
        }
    }

}

初始化

/**
 * 左滑退出activity
 */

public class SwipeBackHelper {

    private Activity activity;

    private LeftSwipeBackLayout swipeBackLayout;

    public SwipeBackHelper(Activity activity) {
        this.activity = activity;
    }

    public void onActivityCreate() {
        activity.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        activity.getWindow().getDecorView().setBackgroundDrawable(null);
        swipeBackLayout = new LeftSwipeBackLayout(activity);
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        swipeBackLayout.setLayoutParams(params);
        swipeBackLayout.setEnableSwipeBack(true);
    }

    public void onPostCreate() {
        swipeBackLayout.attachToActivity(activity);
    }

    public View findViewById(int id) {
        if (swipeBackLayout != null) {
            return swipeBackLayout.findViewById(id);
        }
        return null;
    }

    public LeftSwipeBackLayout getSwipeBackLayout() {
        return swipeBackLayout;
    }
}

Utils

/**
 * 左滑退出activity
 */
public class Utils {
    private Utils() {
    }

    public static void convertActivityFromTranslucent(Activity activity) {
        try {
            Method method = Activity.class.getDeclaredMethod("convertFromTranslucent");
            method.setAccessible(true);
            method.invoke(activity);
        } catch (Throwable t) {
        }
    }


    public static void convertActivityToTranslucent(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            convertActivityToTranslucentAfterL(activity);
        } else {
            convertActivityToTranslucentBeforeL(activity);
        }
    }


    public static void convertActivityToTranslucentBeforeL(Activity activity) {
        try {
            Class<?>[] classes = Activity.class.getDeclaredClasses();
            Class<?> translucentConversionListenerClazz = null;
            for (Class clazz : classes) {
                if (clazz.getSimpleName().contains("TranslucentConversionListener")) {
                    translucentConversionListenerClazz = clazz;
                }
            }
            Method method = Activity.class.getDeclaredMethod("convertToTranslucent",
                    translucentConversionListenerClazz);
            method.setAccessible(true);
            method.invoke(activity, new Object[] {
                null
            });
        } catch (Throwable t) {
        }
    }

    private static void convertActivityToTranslucentAfterL(Activity activity) {
        try {
            Method getActivityOptions = Activity.class.getDeclaredMethod("getActivityOptions");
            getActivityOptions.setAccessible(true);
            Object options = getActivityOptions.invoke(activity);

            Class<?>[] classes = Activity.class.getDeclaredClasses();
            Class<?> translucentConversionListenerClazz = null;
            for (Class clazz : classes) {
                if (clazz.getSimpleName().contains("TranslucentConversionListener")) {
                    translucentConversionListenerClazz = clazz;
                }
            }
            Method convertToTranslucent = Activity.class.getDeclaredMethod("convertToTranslucent",
                    translucentConversionListenerClazz, ActivityOptions.class);
            convertToTranslucent.setAccessible(true);
            convertToTranslucent.invoke(activity, null, options);
        } catch (Throwable t) {
        }
    }
}

使用方法:

	private SwipeBackHelper helper;
	
	@Override
	protected void onCreate(@Nullable Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
    	helper = new SwipeBackHelper(this);
    	helper.onActivityCreate();
	}


	@Override
    protected void onPostCreate(@Nullable Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        helper.onPostCreate();
    }

    @Override
    public View findViewById(int id) {
        View v = super.findViewById(id);
        if (v == null && helper != null)
           return helper.findViewById(id);
        return v;
    }

需要的drawable文件
退出时左侧边框显示的图片

简单的滑动冲突有处理,复杂的需要自己处理,下面是我自己处理的一个例子

	float x1 = 0;
    float x2 = 0;
    float y1 = 0;
    float y2 = 0;
    int move = 100;//移动距离

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN://当手指按下的时候
                x1 = ev.getX();
                y1 = ev.getY();
                break;
            case MotionEvent.ACTION_MOVE://手指移动的时候
                x2 = ev.getX();
                y2 = ev.getY();
                float slideX = x2 - x1;
                float slideY = Math.abs(y1 - y2);
                if (slideX > move && slideX > slideY) {
                    finish();
                }
                break;
        }
        return super.dispatchTouchEvent(ev);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值