Loading

滑动关闭activity

对于微信滑动关闭activity的功能,我一直觉得挺酷,想在自己的项目上也加上这个功能。网上找了一下发现一个不错的思路。

使用ViewDragHelper。

首先要让activity在滑动的时候下面的activity能够看得到,那么就得设置activity的主题,让activity的窗口变透明。

<style name="MyActivityBackground" parent="MyAppTheme">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Activity</item>
</style>

该主题继承MyAppTheme(这也是个自定义的主题,整个application就是用这个主题,为了不避免冲突,继承它)。
尤其要注意的是windowAnimationStyle,这个是设置activity的进入与退出的动画效果,设置为默认的效果。

然后在需要实现滑动退出的activity的注册文件上用上这个主题就行了。

 以下是全部代码

public class MyDragViewGroup extends FrameLayout{

    private ViewDragHelper mViewDragHelper;

    //该自定义组件的宽
    private int mWidth;

    //该自定义组件的高
    private int mHeight;

    //需要滑动的组件目前已经滑动的距离
    private int currentLeft;

    //该滑动距离用于判断是否可以将activity关闭
    private int mSlidX;

    private static final int x=40;
    private Context mContext;

    //需要滑动的view
    private View view;

    private Paint mPaint;

    public MyDragViewGroup(Context context) {
        super(context);
        initView(context);
    }

    public void bind()
    {
        //获取activity的视图
        ViewGroup viewGroup= (ViewGroup) ((Activity)mContext).getWindow().getDecorView();
        view=viewGroup.getChildAt(0);

        viewGroup.removeView(view); //将该视图移除
        addView(view);  //将该视图添加进去这个自定义的组件
        viewGroup.addView(this); //将该自定义的组件整个添加进decorView
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth=getMeasuredWidth();
        mHeight=getMeasuredHeight();
        mSlidX= (int) (mWidth*0.3);
    }

    private void initView(Context context)
    {
        mContext=context;

        mViewDragHelper=ViewDragHelper.create(this,callback);
        //边缘检测
        mViewDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);

        mPaint=new Paint();
        mPaint.setStrokeWidth(2);
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.GRAY);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return mViewDragHelper.shouldInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mViewDragHelper.processTouchEvent(event);
        return true;
    }


    private ViewDragHelper.Callback callback=new ViewDragHelper.Callback() {
        @Override
        public boolean tryCaptureView(View child, int pointerId) {
            return false;
        }

        @Override
        public int clampViewPositionVertical(View child, int top, int dy) {
            return 0;
        }

        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
            return left;
        }

        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {
            super.onViewReleased(releasedChild, xvel, yvel);

            //如果滑动的距离小于mSlidX,那么就滑回原处
            if (view.getLeft()<mSlidX)
            {
                mViewDragHelper.smoothSlideViewTo(view,0,0);
                ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
            }
            //否则滑出屏幕
            else
            {
                mViewDragHelper.smoothSlideViewTo(view,mWidth,0);
                ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
            }
            invalidate();
        }

        @Override
        public void onEdgeDragStarted(int edgeFlags, int pointerId) {
            mViewDragHelper.captureChildView(view,pointerId);
        }

        @Override
        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
            currentLeft=left;
            invalidate();
            if (left>=mWidth)
            {
                ((Activity)mContext).finish();
            }
        }
    };

    @Override
    public void computeScroll() {
        if (mViewDragHelper.continueSettling(true))
        {
            ViewCompat.postInvalidateOnAnimation(this);
            invalidate();
        }
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        drawShadow(canvas);
        super.dispatchDraw(canvas);
    }

    protected void drawShadow(Canvas canvas) {
        canvas.save();

        Shader mShader=new LinearGradient(currentLeft - x, 0, currentLeft, 0, new int[]{Color.parseColor("#1edddddd"),
                Color.parseColor("#6e666666"), Color.parseColor("#9e666666")}, null, Shader.TileMode.REPEAT);
        mPaint.setShader(mShader);
        //绘制时,注意向左边偏移
        RectF rectF = new RectF(currentLeft - x, 0, currentLeft, mHeight);
        canvas.drawRect(rectF, mPaint);
        canvas.restore();
    }
}

如果知道ViewDragHelper的使用,那么上面的代码很容易看得明白。drawShadow()是为了绘制阴影,注意在滑动的过程中要不断的刷新重绘,让阴影跟随着activity的移动而移动。

 

值得注意的是ViewGroup容器组件的绘制,当它没有背景时直接调用的是dispatchDraw()方法, 而绕过了draw()方法,当它有背景的时候就调用draw()方法,而draw()方法里包含了dispatchDraw()方法的调用。因此要在ViewGroup上绘制东西的时候往往重写的是dispatchDraw()方法而不是onDraw()方法,或者自定制一个Drawable,重写它的draw(Canvas c)和 getIntrinsicWidth(), getIntrinsicHeight()方法,然后设为背景。

 

要使用的时候只需要在activity里加入

MyDragViewGroup myDragViewGroup=new MyDragViewGroup(this); myDragViewGroup.bind();就OK了。

myDragViewGroup.bind();主要是将activity的视图放入该自定义的ViewGroup当中,然后再把整个自定义的ViewGroup设置给activity。

参考博客:http://blog.csdn.net/meijian531161724/article/details/50763931

posted @ 2017-05-23 21:22  妖久  阅读(734)  评论(0编辑  收藏  举报