Skip to content

Commit 49ab25c

Browse files
committed
仿QQ小红点
1 parent 27349cd commit 49ab25c

File tree

3 files changed

+23
-8
lines changed

3 files changed

+23
-8
lines changed

app/src/main/java/org/ninetripods/mq/study/bezier/view/QQPoint/QQBezierView.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
public 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()) {

app/src/main/res/layout/activity_swipe_recycleview.xml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,5 @@
1111
android:id="@+id/swipe_recycleview"
1212
android:layout_width="match_parent"
1313
android:layout_height="match_parent"
14-
android:layout_below="@id/toolbar"
15-
android:clipChildren="false" />
14+
android:layout_below="@id/toolbar" />
1615
</RelativeLayout>

app/src/main/res/layout/swipe_menu_item.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
android:layout_height="70dp"
77
android:layout_centerInParent="true"
88
android:background="@color/white"
9-
android:clipChildren="false"
109
android:orientation="horizontal"
1110
app:right_id="@+id/ll_right_menu">
1211

0 commit comments

Comments
 (0)