自定义view-侧滑返回

来源:互联网 发布:电脑如何看淘宝微淘 编辑:程序博客网 时间:2024/05/17 21:40
前言

最近发现越来越多的app中使用到侧滑返回的功能,比如微信,今日头条等等。于是我自己去实现这个功能,博客不罗嗦 尽可能的简洁一些

源码地址:https://github.com/bangbangqiu/SliddingBack.git

简要说明思路:

自定义view继承字FrameLayout,嵌套在activity的布局的最外层,作为滑动的view。重写onInterceptTouchEvent()方法拦截滑动事件,在onTouchEvent中根据滑动距离调用View的scroolTo()方法。手指松开 计算滑动速度和滑动距离是否达到activity销毁的大小,并提供销毁的回调方法。在Style.xml中配置activity的样式位背景透明

具体解析及代码:

 @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        //如果点击距离屏幕左边界10dp,触发返回销毁activity        float x = ev.getX();        Log.d(TAG, "onInterceptTouchEvent: x:" + ev.getX());        if (!isOpen) return false;        if (x < dp2px(sliddingLength)) {            //注意: 即使拦截 ACTION_DOWN 也会执行一次            isInterupt = true;        } else {            isInterupt = false;        }        return isInterupt;    }

如果按下的点在滑动的区域内就 return true 拦截事件,交给onTouchEvent()处理


@Override    public boolean onTouchEvent(MotionEvent event) {        Log.d(TAG, "onTouchEvent: x:" + event.getX() + "y: " + event.getY());        Log.d(TAG, "onTouchEvent: downX:" + downPoint.x + "downY: " + downPoint.y);        Log.d(TAG, "onTouchEvent: currentX:" + currentPoint.x + "currentY: " + currentPoint.y);        //当 isInterrupt==false 或者不在拦截区域 进行拦截        if (!isInterupt || downPoint.x > dp2px(sliddingLength)) {            Log.d(TAG, "onTouchEvent: 拦截==================");            return false;        }        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                Log.d(TAG, "onTouchEvent: ACTION_DOWN");                currentPoint.x = downPoint.x = (int) event.getX();                currentPoint.y = downPoint.y = (int) event.getY();                startTime = System.currentTimeMillis();                break;            case MotionEvent.ACTION_MOVE://                Log.d(TAG, "onTouchEvent: ACTION_MOVE");                //滑动操作                speed = (int) ((event.getX() - currentPoint.x) / (System.currentTimeMillis() - startTime) * 1000);                Log.d(TAG, "onTouchEvent: speed: " + speed);                scrollTo(downPoint.x - currentPoint.x, 0);                currentPoint.x = (int) event.getX();                currentPoint.y = (int) event.getY();                startTime = System.currentTimeMillis();                break;            case MotionEvent.ACTION_UP:            case MotionEvent.ACTION_CANCEL:                Log.d(TAG, "onTouchEvent: ACTION_UP_CANCEL");                int x = (int) event.getX();                //如果速度达到了,并且是正值,负数代表反方向                if (speed > 1000) {                    finish();                    return true;                }                if (x < 0.3 * widthPixels || speed < -1000) {//                    Toast.makeText(getContext(), "距离不够activity不销毁", Toast.LENGTH_SHORT).show();                    backActivityListenner.onSliddingOver(false);                    backAnimation(currentPoint.x, 0);                } else {//                    Toast.makeText(getContext(), "距离达到activity销毁", Toast.LENGTH_SHORT).show();                    finish();                }                //初始化                downPoint.set(1, 0);                currentPoint.set(0, 0);                break;        }        return true;    }


不多说了,都在代码中了。完成这两个方法就可以 滑动了

添加动画和绘制引用

 //回复动画    public void backAnimation(final int xStart, final int xEnd) {        final ValueAnimator animator = ValueAnimator.ofInt(xStart, xEnd);        animator.setInterpolator(new AccelerateInterpolator());        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                int animatedValue = (int) animation.getAnimatedValue();                scrollTo(-animatedValue, 0);                Log.d(TAG, "onAnimationUpdate: " + animatedValue);                if (animatedValue == xEnd) {                    animator.removeUpdateListener(this);                }            }        });        animator.setDuration(duration);        animator.start();    }

通过valueAnimator根据值的渐变做动画,记得完成动画后移除监听,防止内存泄漏。


  @Override    protected void onDraw(Canvas canvas) {        //绘制阴影        Log.d(TAG, "onDraw: width " + getWidth());        canvas.drawRect(shaderRectF, fillPaint);        super.onDraw(canvas);    }


在onDraw()中去绘制阴影,带渐变色的,很简洁。注意:在构造函数中加上setWillNotDraw(false);否则onDraw()方法不执行。。


 public interface BackActivityListenner {        void onSliddingOver(boolean canBack);    }    public Point getCurrentPoint() {        return currentPoint;    }

对外提供达到activity可销毁的监听


<style name="TransparentStyle" parent="AppTheme">        <item name="android:windowBackground">@color/transparent</item>        <item name="android:windowIsTranslucent">true</item>        <item name="android:colorBackgroundCacheHint">@null</item>        <!--<item name="colorBackgroundCacheHint">@null</item>--></style>


很重要的一点:设置透明的样式。


效果(项目中测试)

结语 

写的第一篇博客献丑了,技术含量不高

1 0
原创粉丝点击