對於微信滑動關閉activity的功能,我一直覺得挺酷,想在自己的項目上也加上這個功能。網上找了一下發現一個不錯的思路。 使用ViewDragHelper。 首先要讓activity在滑動的時候下麵的activity能夠看得到,那麼就得設置activity的主題,讓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