自定义视图的一部分在运行时无法呈现?

时间:2016-04-01 12:23:15

标签: android

我编写了一个自定义视图,可在运行时生成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预览中,按预期显示:

enter image description here

但是,在运行时,将此标记嵌入应用程序的某个位置以进行测试,白点不可见?

enter image description here

对自定义视图有更多经验的人是否能够对此有所了解?我认为这与我缩放路径以使其适合任何尺寸的方式有关?

1 个答案:

答案 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()。路径适合任何大小。