3030public class QQBezierView extends android .support .v7 .widget .AppCompatTextView {
3131 public DragView dragView ;
3232 private float mWidth , mHeight ;//View的宽和高
33- private PointF dragPoint ;//分别为拖动点和固定点
3433 private onDragStatusListener onDragListener ;
3534
3635 public QQBezierView (Context context ) {
@@ -43,7 +42,6 @@ public QQBezierView(Context context, AttributeSet attrs) {
4342
4443 public QQBezierView (Context context , AttributeSet attrs , int defStyleAttr ) {
4544 super (context , attrs , defStyleAttr );
46- dragPoint = new PointF ();
4745 }
4846
4947 @ Override
@@ -55,38 +53,46 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
5553
5654 @ Override
5755 public boolean onTouchEvent (MotionEvent event ) {
56+ //获得根View
5857 View rootView = getRootView ();
58+ //获得触摸位置在全屏所在位置
5959 float mRawX = event .getRawX ();
6060 float mRawY = event .getRawY ();
61- dragPoint .set (event .getX (), event .getY ());
6261 switch (event .getAction ()) {
6362 case MotionEvent .ACTION_DOWN :
63+ //请求父View不拦截
6464 getParent ().requestDisallowInterceptTouchEvent (true );
6565 //获得当前View在屏幕上的位置
6666 int [] cLocation = new int [2 ];
6767 getLocationOnScreen (cLocation );
6868 if (rootView instanceof ViewGroup ) {
69+ //初始化拖拽时显示的View
6970 dragView = new DragView (getContext ());
7071 //设置固定圆的圆心坐标
7172 dragView .setStickyPoint (cLocation [0 ] + mWidth / 2 , cLocation [1 ] + mHeight / 2 , mRawX , mRawY );
73+ //获得缓存的bitmap,滑动时直接通过drawBitmap绘制出来
7274 setDrawingCacheEnabled (true );
7375 Bitmap bitmap = getDrawingCache ();
7476 if (bitmap != null ) {
7577 dragView .setCacheBitmap (bitmap );
78+ //将DragView添加到RootView中,这样就可以全屏滑动了
7679 ((ViewGroup ) rootView ).addView (dragView );
7780 setVisibility (INVISIBLE );
7881 }
7982 }
8083 break ;
8184 case MotionEvent .ACTION_MOVE :
85+ //请求父View不拦截
8286 getParent ().requestDisallowInterceptTouchEvent (true );
8387 if (dragView != null ) {
88+ //更新DragView的位置
8489 dragView .setDragViewLocation (mRawX , mRawY );
8590 }
8691 break ;
8792 case MotionEvent .ACTION_UP :
8893 getParent ().requestDisallowInterceptTouchEvent (false );
8994 if (dragView != null ) {
95+ //手抬起时来判断各种情况
9096 dragView .setDragUp ();
9197 }
9298 break ;
@@ -163,21 +169,24 @@ private void init() {
163169 for (int i = 0 ; i < explode_res .length ; i ++) {
164170 bitmaps [i ] = BitmapFactory .decodeResource (getResources (), explode_res [i ]);
165171 }
166-
167172 }
168173
169174 @ Override
170175 protected void onDraw (Canvas canvas ) {
171176 if (isInsideRange () && mState == STATE_DRAG ) {
172177 mPaint .setColor (Color .RED );
178+ //绘制固定的小圆
173179 canvas .drawCircle (stickyPointF .x , stickyPointF .y , stickRadius , mPaint );
174- //绘制贝塞尔曲线
180+ //首先获得两圆心之间的斜率
175181 Float linK = MathUtil .getLineSlope (dragPointF , stickyPointF );
182+ //然后通过两个圆心和半径、斜率来获得外切线的切点
176183 PointF [] stickyPoints = MathUtil .getIntersectionPoints (stickyPointF , stickRadius , linK );
177184 dragRadius = (int ) Math .min (mWidth , mHeight ) / 2 ;
178185 PointF [] dragPoints = MathUtil .getIntersectionPoints (dragPointF , dragRadius , linK );
179186 mPaint .setColor (Color .RED );
187+ //二阶贝塞尔曲线的控制点取得两圆心的中点
180188 controlPoint = MathUtil .getMiddlePoint (dragPointF , stickyPointF );
189+ //绘制贝塞尔曲线
181190 mPath .reset ();
182191 mPath .moveTo (stickyPoints [0 ].x , stickyPoints [0 ].y );
183192 mPath .quadTo (controlPoint .x , controlPoint .y , dragPoints [0 ].x , dragPoints [0 ].y );
@@ -187,10 +196,12 @@ protected void onDraw(Canvas canvas) {
187196 canvas .drawPath (mPath , mPaint );
188197 }
189198 if (mCacheBitmap != null && mState != STATE_DISMISS ) {
199+ //绘制缓存的Bitmap
190200 canvas .drawBitmap (mCacheBitmap , dragPointF .x - mWidth / 2 ,
191201 dragPointF .y - mHeight / 2 , mPaint );
192202 }
193203 if (mState == STATE_DISMISS && explodeIndex < explode_res .length ) {
204+ //绘制小红点消失时的爆炸动画
194205 canvas .drawBitmap (bitmaps [explodeIndex ], dragPointF .x - mWidth / 2 , dragPointF .y - mHeight / 2 , mPaint );
195206 }
196207 }
@@ -208,14 +219,19 @@ public void setCacheBitmap(Bitmap mCacheBitmap) {
208219
209220
210221 /**
222+ * 设置固定圆的圆心和半径
223+ *
211224 * @param stickyX 固定圆的X坐标
212225 * @param stickyY 固定圆的Y坐标
213226 */
214227 public void setStickyPoint (float stickyX , float stickyY , float touchX , float touchY ) {
228+ //分别设置固定圆和拖拽圆的坐标
215229 stickyPointF .set (stickyX , stickyY );
216230 dragPointF .set (touchX , touchY );
231+ //通过两个圆点算出圆心距,也是拖拽的距离
217232 dragDistance = MathUtil .getTwoPointDistance (dragPointF , stickyPointF );
218233 if (dragDistance <= maxDistance ) {
234+ //如果拖拽距离小于规定最大距离,则固定的圆应该越来越小,这样看着才符合实际
219235 stickRadius = (int ) (defaultRadius - dragDistance / 10 ) < 10 ? 10 : (int ) (defaultRadius - dragDistance / 10 );
220236 mState = STATE_DRAG ;
221237 } else {
@@ -231,6 +247,7 @@ public void setStickyPoint(float stickyX, float stickyY, float touchX, float tou
231247 */
232248 public void setDragViewLocation (float touchX , float touchY ) {
233249 dragPointF .set (touchX , touchY );
250+ //随时更改圆心距
234251 dragDistance = MathUtil .getTwoPointDistance (dragPointF , stickyPointF );
235252 if (mState == STATE_DRAG ) {
236253 if (isInsideRange ()) {
0 commit comments