Android 侧边滑动关闭Activity【废弃】

日报写手
• 阅读 1749

0.效果图

Android 侧边滑动关闭Activity【废弃】

1.设置Activity样式属性

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowIsTranslucent">true</item>
</style>

2.自定义侧边阴影视图

class SlideBackView extends View {

        private Paint mBgPaint, mShadowPaint;
        private RectF mBgRectF, mShadowRectF;
        private float mRatio;
        private float mShadowSize;

        public SlideBackView(Context context) {
            super(context);
            mBgPaint = new Paint();
            mBgPaint.setAntiAlias(true);
            mBgPaint.setColor(0xff000000);
            mShadowPaint = new Paint();
            mShadowPaint.setAntiAlias(true);
            mShadowPaint.setStyle(Paint.Style.FILL);
            mShadowSize = dp2px(15);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            mBgRectF = new RectF();
            mBgRectF.top = 0;
            mBgRectF.left = 0;
            mBgRectF.bottom = MeasureSpec.getSize(heightMeasureSpec);

            mShadowRectF = new RectF();
            mShadowRectF.top = 0;
            mShadowRectF.bottom = MeasureSpec.getSize(heightMeasureSpec);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            int width = getMeasuredWidth();
            float right = mRatio * width;
            mBgRectF.right = right;
            mBgPaint.setAlpha((int) (128 * (1 - mRatio)));
            canvas.drawRect(mBgRectF, mBgPaint);
            mShadowRectF.left = right - mShadowSize;
            mShadowRectF.right = right;
            mShadowPaint.setShader(new LinearGradient(mShadowRectF.left, 0, mShadowRectF.right, 0, 0x00000000, 0x26000000, Shader.TileMode.CLAMP));
            canvas.drawRect(mShadowRectF, mShadowPaint);
        }

        public void setDistance(float ratio) {
            mRatio = ratio;
            invalidate();
        }

        private float dp2px(float dpValue) {
            float density = getResources().getDisplayMetrics().density;
            return dpValue * density + 0.5F;
        }
    }

3.定义可滑动的Activity父类

public class SlideBaseActivity extends AppCompatActivity implements ValueAnimator.AnimatorUpdateListener {

    private boolean isAnimate, isSlide, isHandle;
    private float moveNum;
    private float lastX, lastY;
    private int lastPointerCount;
    private float mAnimatedValue;
    private ValueAnimator mValueAnimator;
    private SlideBackView mSlideBackView;
    private float mTouchSlop;
    private List<ShieldView> shieldViews = new ArrayList<>();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        super.onCreate(savedInstanceState);
        initAnimator();
        initSlideBackView();
        mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
    }

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        mAnimatedValue = (float) animation.getAnimatedValue();
        moveView(mAnimatedValue);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (!isAnimate) {
            float x = event.getRawX();
            float y = event.getRawY();
            if (event.getPointerCount() != lastPointerCount) {
                lastPointerCount = event.getPointerCount();
                lastX = x;
                lastY = y;
            }
            float offsetX, offsetY;
            switch (event.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    offsetX = x - lastX;
                    offsetY = y - lastY;
                    if (!isHandle) {
                        float absX = Math.abs(offsetX);
                        float absY = Math.abs(offsetY);
                        if (absX > mTouchSlop) {
                            if (absX * 0.5f > absY) {
                                isSlide = true;
                                checkSlide((int) x, (int) y);
                            } else {
                                isSlide = false;
                            }
                            isHandle = true;
                        }
                    } else if (isSlide) {
                        moveNum += offsetX;
                        if (moveNum < 0) {
                            moveNum = 0;
                        }
                        moveView(moveNum);
                        lastX = event.getX();
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if (isHandle) {
                        isSlide = false;
                        isHandle = false;
                        isAnimate = true;
                        int width = getWindow().getDecorView().getMeasuredWidth();
                        if (moveNum < width / 3f) {
                            mValueAnimator.setFloatValues(moveNum, 0);
                        } else {
                            mValueAnimator.setFloatValues(moveNum, width);
                        }
                        mValueAnimator.start();
                        moveNum = 0;
                        lastPointerCount = 0;
                    }
            }
        }
        return isSlide || super.dispatchTouchEvent(event);
    }

    /**
     * 添加禁用滑动的子布局
     */
    public void addShieldView(View view) {
        shieldViews.add(new ShieldView(false, view));
    }

    /**
     * 添加水平禁用滑动的子布局
     */
    public void addHorizontalShieldView(View view) {
        shieldViews.add(new ShieldView(true, view));
    }

    /**
     * 移除禁用滑动的子布局
     */
    public void removeShieldView(View view) {
        for (ShieldView v : shieldViews) {
            if (v.view != null && v.view.equals(view)) {
                shieldViews.remove(v);
                break;
            }
        }
    }

    /**
     * 清空禁用滑动的子布局
     */
    public void clearShieldView() {
        shieldViews.clear();
    }

    private void initAnimator() {
        mValueAnimator = new ValueAnimator();
        mValueAnimator.setDuration(300);
        mValueAnimator.addUpdateListener(this);
        mValueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                isAnimate = false;
                if (mAnimatedValue == getWindow().getDecorView().getMeasuredWidth()) {
                    SlideBaseActivity.super.finish();
                    overridePendingTransition(0, 0);
                }
            }
        });
    }

    private void initSlideBackView() {
        mSlideBackView = new SlideBackView(this);
        ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
        decorView.addView(mSlideBackView);
    }

    private void moveView(float moveX) {
        ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
        mSlideBackView.setDistance(moveX / decorView.getMeasuredWidth());
        int count = decorView.getChildCount();
        for (int i = 0; i < count; i++) {
            View view = decorView.getChildAt(i);
            if (view != mSlideBackView) {
                view.setX(moveX);
            }
        }
    }

    private void checkSlide(int x, int y) {
        for (ShieldView v : shieldViews) {
            Rect rect = new Rect();
            v.view.getGlobalVisibleRect(rect);
            if (rect.contains(x, y) && (!(lastX < x && !v.view.canScrollHorizontally(-1)) || (!v.isHorizontal))) {
                isSlide = false;
            }
        }
    }
    
    class ShieldView {
        boolean isHorizontal;
        View view;

        public ShieldView(boolean isHorizontal, View view) {
            this.isHorizontal = isHorizontal;
            this.view = view;
        }
    }
}

4.使用

继承SlideBaseActivity类,可调用addShieldViewaddHorizontalShieldView方法解决事件冲突。

5.项目源码

https://gitee.com/yugu/slide-demo

点赞
收藏
评论区
推荐文章
java一生之敌 java一生之敌
3年前
JVM的内存模型和优化方式
一、JVM的内存模型1.!图片(https://imghelloworld.osscnbeijing.aliyuncs.com/imgs/52b2220f04010eb329efbef966f9fa40.png)其中s0,s1为幸
待兔 待兔
5年前
Android Activity生命周期,启动模式,启动过程详解
前言接触过Android开发的同学都知道Activity,Activity作为Android四大组件之一,使用频率高。简单来说Activity提供了一个显示界面,让用户进行各种操作,本文主要分为以下三个部分:Activity的生命周期,启动模式,以及Activity的工作过程。文中大部分篇幅来自《Android开发艺术探索》一书,尽管想多以流程或图
Stella981 Stella981
4年前
Android Activity四种加载方式
1概述Android中的Activity共有四种加载方式,可以在AndroidManifest.xml中对应的activity的android:launchMode中指定,四种方式如下:standradsingleTopsingleTasksingleInstance其中,standard是默认的
Wesley13 Wesley13
4年前
Activity启动模式
当应用运行起来后就会开启一条线程,线程中会运行一个任务栈,当Activity实例创建后就会放入任务栈中。Activity启动模式的设置在AndroidManifest.xml文件中,通过配置Activity的属性android:launchMode""设置。1\.Standard模式(默认)我们平时直接创建的Activity都是这种模式的
Stella981 Stella981
4年前
Android 复选框 以及回显
activity\_main.xml<?xmlversion"1.0"encoding"utf8"?<LinearLayoutxmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http:/
Stella981 Stella981
4年前
Android 面试常问七道题
1Android的四大组件以及作用Activity:Activity是Android程序与用户交互的窗口,是Android构造块中最基本的一种,它需要为保持各界面的状态,做很多持久化的事情,妥善管理生命周期以及一些跳转逻辑。service:后台服务于Activity,封装有一个完整的功能逻辑实现,接受上层指令,完成相关的动作,
Stella981 Stella981
4年前
Android Intent隐式意图显示菜单
package com.example.mytest;import android.os.Bundle;import android.app.Activity;import android.view.Menu;public class MainActivity extends Activity { @
Easter79 Easter79
4年前
TextView中使用链接打开Activity
Activity加入intentfilter支持<activityandroid:name"TestActivity"<intentfilter<dataandroid:host"yourhost"android:scheme"testschema"/<
Stella981 Stella981
4年前
Activity切换导致的onCreate重复执行[转]
部分网友会发现Activity在切换到后台或布局从横屏LANDSCAPE切换到PORTRAIT,会重新切换Activity会触发一次onCreate方法,我们可以在androidmanifest.xml中的activit元素加入这个属性android:configChanges"orientation|keyboardHidden"即可,比如 
Stella981 Stella981
4年前
Android横竖屏切换+ConfigChanges属性对Activity的生命周期影响
在Activity中添加了android:configChanges属性,目的是当所指定属性(ConfigurationChanges)发生改变时,通知程序调用onConfigurationChanged()函数。通过一个例子来介绍:1、运行一个新建的ActivityonCreateonStart
Stella981 Stella981
4年前
Android从相机或相册获取图片裁剪
package com.only.android.app; import java.io.File; import android.app.Activity;import android.app.AlertDialog;import android.content.DialogInterfa
日报写手
日报写手
Lv1
夔府孤城落日斜,每依北斗望京华。
文章
3
粉丝
0
获赞
0