对于微信滑动关闭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