可拖拽的气泡效果
自定义view WateView
public class WateView extends FrameLayout {
//定义一个文本控件
private TextView textView;
//定义控件的坐标 文本框的 初始坐标
private PointF initPosition;
//手指是否触摸到了控件
private boolean isClcked = false ;
//手指移动到的坐标 终点坐标
private PointF movePosition;
//绘制的圆的半径
private float mRadius = 40;
//绘制的画笔
private Paint paint ;
//存储连接桥路径对象
private Path path;
// 判断文本框是否离开了某个范围
private boolean isOut =false ;
public WateView(Context context) {
super(context);
init();
}
/**
* 初始化整个效果的控件
*/
private void init(){
initPosition = new PointF(500,500);
movePosition = new PointF();
path = new Path();
//初始化画笔
paint = new Paint();
paint.setColor(Color.RED);
//设置画笔的样式 填充
paint.setStyle(Paint.Style.FILL);
textView = new TextView(getContext());
textView.setPadding(20,20,20,20);
textView.setText("99+");
textView.setTextColor(Color.WHITE);
textView.setBackgroundResource(R.drawable.textview_bg);
LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
textView.setLayoutParams(layoutParams);
this.addView(textView);
}
/**
* 回执包括本身
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
/**
* 绘制当前控件里面的内容 里面的控件
* @param canvas
*/
@Override
protected void dispatchDraw(Canvas canvas) {
// 保存canvasde 状态
canvas.save();
if (isClcked){
textView.setX(movePosition.x-textView.getWidth()/2);
textView.setY(movePosition.y-textView.getHeight()/2);
drawPath();
if (!isOut){ // 在范围内允许画
//画第一个圆
canvas.drawCircle(initPosition.x,initPosition.y,mRadius,paint);
// 画第二个圆 终点的圆
canvas.drawCircle(movePosition.x,movePosition.y,mRadius,paint);
// 画连接桥
canvas.drawPath(path,paint);
}
}else {
textView.setX(initPosition.x-textView.getWidth()/2);
textView.setY(initPosition.y-textView.getHeight()/2);
}
// 回复canvas状态
canvas.restore();
super.dispatchDraw(canvas);
}
/**
* 找到绘制连接桥的四个点 并且用贝塞尔曲线链接起来
*/
public void drawPath(){
// 获取到终点与起点x y 坐标的差值
float widthX = movePosition.x -initPosition.x;
float widthY = movePosition.y -initPosition.y;
//获取两个点之间的直线距离 勾股定理
float sss= (float) Math.sqrt(Math.pow(widthX,2)+Math.pow(widthY,2));
mRadius = 40-sss/20;
if (sss>=300){
isOut = true ;
}else {
isOut =false ;
}
// 得到三角形的正切值
double atan = Math.atan(widthY/widthX);
// 获取到offsetX 长度 offsetY
float offsetX = (float) (mRadius*Math.sin(atan));
float offsetY = (float) (mRadius*Math.cos(atan));、
//获取到a坐标
float ax = initPosition.x+offsetX;
float ay = initPosition.y-offsetY;
//获取到b坐标
float bx = movePosition.x+offsetX;
float by = movePosition.y-offsetY;
//获取到c坐标
float cx = movePosition.x-offsetX;
float cy = movePosition.y+offsetY;
//获取到d坐标
float dx = initPosition.x-offsetX;
float dy = initPosition.y+offsetY;
// 获取到起点坐标和终点坐标的中心点
float conX = (initPosition.x+movePosition.x)/2;
float conY = (initPosition.y+movePosition.y)/2;
// 初始化path对象
path.reset();
//将起点移动到A坐标
path.moveTo(ax,ay);
//从A点链接到B点 // quadTo();第一个参数 是弯曲的点的x点 第二个参数是弯曲点的y点
path.quadTo(conX,conY,bx,by);
//从B点链接到C点
path.lineTo(cx,cy);
//从c点链接到d点 d
path.quadTo(conX,conY,dx,dy);
//从d点链接到A点
path.lineTo(ax,ay);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
movePosition.set(initPosition.x,initPosition.y);
//判断当前点击的位置是否在文本控件里面
Rect rect = new Rect();// 封装文本控件范围的对象
int [] location = new int [2];
//获取textview控件窗体中X Y 坐标
textView.getLocationOnScreen(location);
//初始化rect对象
rect.left = location[0];
rect.top = location[1];
rect.right = location[0]+textView.getWidth();
rect.bottom = location[1]+textView.getHeight();
// 判断当前点击的坐标是否在范围内
if (rect.contains((int)event.getRawX(),(int)event.getRawY())){
isClcked = true ;
}
break;
case MotionEvent.ACTION_UP:
isClcked = false ;
break;
case MotionEvent.ACTION_MOVE:
movePosition.set((int)event.getX(),(int)event.getY());
break;
}
// 通过这个API调用dispatchDraw方法
postInvalidate();
return true;
}
------注释----
getX() getY(); 取值是相对于父控件而言
getRawX() getRawY() 取值相对于屏幕而言
textview_bg
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ff0404"/>
<stroke android:width="0dp" android:color="#ff0404"/>
<corners android:radius="50dp"/>
</shape>
界面布局文件
具体使用
得到帮助的朋友点点赞 也可以对小弟打赏喔