在qq上面用一个红色的黏性控件来表示消息已读或未读。可拖动。今天就来分享一下如何实现这个功能。我们需要的jar包是nineoldandroids-2.4.0.jar,还需要一个开源的几何工具类GeometryUtil.java。
应用场景: 未读提醒的清除
1.画静态图
//1.画固定圆
canvas.drawCircle(mStickCenter.x,mStickCenter.y,mStickRadious, mPaint);
//2.画拖拽圆
canvas.drawCircle(mDragCenter.x,mDragCenter.y,mDragRadius, mPaint);
2.把静态的数值变成变量(计算得到真实的变量)
// 3. 获取控制点坐标
mControlPoint = GeometryUtil.getMiddlePoint(mDragCenter, mStickCenter);
// 保存画布状态
canvas.save();
canvas.translate(0, -statusBarHeight);
// 画出最大范围(参考用)
mPaint.setStyle(Style.STROKE);
canvas.drawCircle(mStickCenter.x, mStickCenter.y, farestDistance, mPaint);
mPaint.setStyle(Style.FILL);
3.不断地修改变量, 重绘界面, 动起来了.
// 计算连接点值, 控制点, 固定圆半径
// 1. 获取固定圆半径(根据两圆圆心距离)
float tempStickRadius = getTempStickRadius();
// 2. 获取直线与圆的交点
float yOffset = mStickCenter.y - mDragCenter.y;
float xOffset = mStickCenter.x - mDragCenter.x;
Double lineK = null;
if(xOffset != 0){
lineK = (double) (yOffset / xOffset);
}
// 通过几何图形工具获取交点坐标
mDragPoints = GeometryUtil.getIntersectionPoints(mDragCenter, mDragRadius, lineK);
mStickPoints = GeometryUtil.getIntersectionPoints(mStickCenter, tempStickRadius, lineK);
4.功能分析:
a. 拖拽超出范围,断开, 松手, 消失
b. 拖拽超出范围,断开,放回去了,恢复
c. 拖拽没超出范围, 松手,弹回去
case MotionEvent.ACTION_UP:
if(isOutofRange){
float d = GeometryUtil.getDistanceBetween2Points(mDragCenter, mStickCenter);
if(d > farestDistance){
// a. 拖拽超出范围,断开, 松手, 消失
isDisappear = true;
invalidate();
}else {
//b. 拖拽超出范围,断开,放回去了,恢复
updateDragCenter(mStickCenter.x, mStickCenter.y);
}
}else {
// c. 拖拽没超出范围, 松手,弹回去
final PointF tempDragCenter = new PointF(mDragCenter.x, mDragCenter.y);
ValueAnimator mAnim = ValueAnimator.ofFloat(1.0f);
mAnim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator mAnim) {
// 0.0 -> 1.0f
float percent = mAnim.getAnimatedFraction();
PointF p = GeometryUtil.getPointByPercent(tempDragCenter, mStickCenter, percent);
updateDragCenter(p.x, p.y);
}
});
mAnim.setInterpolator(new OvershootInterpolator(4));
mAnim.setDuration(500);
mAnim.start();
}
break;