2016-04-01 10 views
0

Ich habe eine benutzerdefinierte Ansicht geschrieben, die eine Google Map Marker zur Laufzeit folgende Code generieren:Teil der benutzerdefinierten Ansicht nicht zur Laufzeit gerendert?

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); 
    } 


} 

, die in der XML-Vorschau, zeigt, wie beabsichtigt:

enter image description here

, jedoch bei Laufzeit, Einbettung dieser Marker irgendwo in der App zu testen, ist der weiße Punkt nicht sichtbar?

enter image description here

Würde jemand mit mehr Erfahrung mit benutzerdefinierten Ansichten der Lage sein, etwas Licht in diesen Schuppen? Ich vermute, dass es etwas damit zu tun hat, wie ich den Weg skaliere, um ihn an jede Größe anzupassen?

+0

Verwenden Sie keine hartcodierten Zahlen, berechnen Sie den Pfad mit getWidth() und getHeight() und Prozentangaben von denen, dann brauchen Sie überhaupt keine Skalierung. Warum fügen Sie einen Pfad zum Körperpfad hinzu? In den setXXXColor-Funktionen müssen Sie paint.setColor() verwenden, sonst haben sie keine Wirkung. – ElDuderino

+0

@ElDuderino Danke für die Antwort, guten Ruf auf die setXXXColors, sie sind eigentlich nicht im Moment verwendet, aber hätte mich später gestochen! Leider bin ich bezüglich der Skalierung sehr unerfahren mit programmatischem Zeichnen und/oder benutzerdefinierten Ansichten und würde sehr wenig Erfolg beim Versuch haben, die richtige Methode, die Sie erwähnt haben, zu versuchen! – Broak

Antwort

0

Ich habe endlich etwas Zeit gefunden, um Ihr Problem zu betrachten.

1) Verwenden Sie addArc() anstelle von arcTo(). Wenn alles, was Sie wollen, ein Kreis ist, verwenden Sie keinen Pfad, verwenden Sie canvas.drawCircle(). Ich würde das tun.

2) Erstellen Sie keine Objekte in onDraw(). Verwenden Sie onSizeChanged(), um Ihre Pfade zu erstellen, das ist der Zeitpunkt, an dem Sie wissen, wie groß Ihre Ansicht ist. Sie können dann Ihren Pfad abhängig von der Breite und Höhe Ihrer Ansicht berechnen. Sie müssen also nichts skalieren. In onDraw() zeichnest du einfach.

@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() z.B. sieht wie folgt aus

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; 
} 

Ja es eine hässliche Weg ist, aber man kann sehen, wie ich die Breite und Höhe der Ansicht verwenden, um die Kontrollpunkte zu berechnen. Auf diese Weise brauchen Sie Ihre Maßstabsmatrix nicht und Sie benötigen onMeasure() nicht. Der Pfad passt zu jeder Größe.

Verwandte Themen