我编写了一个自定义视图,可在运行时生成Google地图标记,代码如下:
public class CustomMapMarker extends View {
Paint paint;
Path bodyPath;
Path dotPath;
private Paint paint2;
private int backGroundColor;
private int foreGroundColor;
Matrix scaleMatrix;
public CustomMapMarker(Context context)
{
super(context);
init(context);
}
public CustomMapMarker(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomMapMarker);
try {
backGroundColor = a.getColor(R.styleable.CustomMapMarker_markerBackgroundColor, Color.parseColor("#4180e0"));
foreGroundColor = a.getColor(R.styleable.CustomMapMarker_dotBackgroundColor, Color.WHITE);
}
finally {
a.recycle();
}
init(context);
}
public CustomMapMarker(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
scaleMatrix = new Matrix();
bodyPath = new Path();
dotPath = new Path();
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(backGroundColor);
paint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
paint2.setStyle(Paint.Style.FILL);
paint2.setColor(foreGroundColor);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onDraw(Canvas canvas)
{
bodyPath.setFillType(Path.FillType.EVEN_ODD);
bodyPath.moveTo(132, 416);
bodyPath.cubicTo(123, 370, 107, 332, 87, 297);
bodyPath.cubicTo(72, 270, 55, 246, 39, 221);
bodyPath.cubicTo(33, 212, 29, 203, 24, 194);
bodyPath.cubicTo(14,177,5,156, 6, 130);
bodyPath.cubicTo(6,104,14,83,25,66);
bodyPath.cubicTo(42,38,72,15,112,9);
bodyPath.cubicTo(145, 4, 176,12,197,25);
bodyPath.cubicTo(215, 36, 229,49,239,66);
bodyPath.cubicTo(250, 83, 258, 103,258,129);
bodyPath.cubicTo(259, 143, 256, 155, 253, 166);
bodyPath.cubicTo(250, 176, 245, 185, 241, 194);
bodyPath.cubicTo(232, 212, 221, 229, 210, 246);
bodyPath.cubicTo(177, 296, 146, 347, 132, 416);
bodyPath.close();
dotPath.setFillType(Path.FillType.EVEN_ODD);
dotPath.arcTo(82, 85, 182, 185, 270, 360, true);
dotPath.close();
bodyPath.addPath(dotPath);
RectF drawableRect = new RectF(0, 0, 265, 412);
RectF viewRect = new RectF(0, 0, getWidth(), getHeight());
scaleMatrix.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.CENTER);
bodyPath.transform(scaleMatrix);
dotPath.transform(scaleMatrix);
canvas.drawPath(bodyPath, paint);
canvas.drawPath(dotPath, paint2);
}
public void setBackgroundColor(int mColor) {
this.backGroundColor = mColor;
this.invalidate();
}
public void setForeGroundColor(int mColor) {
this.foreGroundColor = mColor;
this.invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int desiredWidth = 255;
int desiredHeight = 412;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
width = Math.min(desiredWidth, widthSize);
} else {
width = desiredWidth;
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
height = Math.min(desiredHeight, heightSize);
} else {
height = desiredHeight;
}
setMeasuredDimension(width, height);
}
}
在XML预览中,按预期显示:
但是,在运行时,将此标记嵌入应用程序的某个位置以进行测试,白点不可见?
对自定义视图有更多经验的人是否能够对此有所了解?我认为这与我缩放路径以使其适合任何尺寸的方式有关?
答案 0 :(得分:0)
我终于找到了一些时间来看你的问题。
1)使用addArc()而不是arcTo()。如果你想要的只是一个圆圈,不要使用路径,请使用canvas.drawCircle()。我做到了。
2)不要在onDraw()中创建对象。使用onSizeChanged()来创建您的视图,这是您知道视图有多大的时间。然后,您可以根据视图的宽度和高度计算路径。因此,您不需要扩展任何东西。在onDraw()中你只是画画。
@Override
public void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
bodyPath = getBodyPath(width, height);
dotPath = getDotPath(width, height);
}
@Override
public void onDraw(Canvas canvas)
{
canvas.save();
if(bodyPath != null) {
canvas.drawPath(bodyPath, backgroundPaint);
}
if(dotPath != null) {
canvas.drawPath(dotPath, foregroundPaint);
}
//or just a circle
//canvas.drawCircle(getWidth()/2, getHeight()/3,Math.min(getWidth(),getHeight())/5,foregroundPaint);
canvas.restore();
}
getBodyPath(),例如看起来像这样
private Path getOutlinePath(float w, float h) {
Path bodyPath = new Path();
bodyPath.setFillType(Path.FillType.EVEN_ODD);
bodyPath.moveTo(w* 0.5f, h);
bodyPath.cubicTo(w * 0.4f, h * 0.8f, w * 0.3f, h * 0.7f, w * 0.25f, h * 0.6f);
bodyPath.cubicTo(w * 0.2f, h * 0.5f, w * 0.1f, h * 0.5f, 0, h * 0.3f);
bodyPath.cubicTo(0, h * 0.25f, w * 0.25f, 0, w * 0.5f, 0);
bodyPath.cubicTo(w * 0.75f, 0, w, h * 0.25f, w, h * 0.5f);
bodyPath.close();
return bodyPath;
}
是的,它是一条丑陋的路径,但您可以看到我如何使用视图的宽度和高度来计算控制点。这样你就不需要你的比例矩阵,你也不需要onMeasure()。路径适合任何大小。