2015-09-01 12 views
7

Ich habe gerade 2 Zeichnungen erstellt, um einen zu bekommen, der genauso aussieht wie der andere, aber ich habe kein Glück. Bei den Screenshots wurde die Zeichnung oben mit Canvas erstellt und die Zeichnung unten mit XML erstellt. Die XML-Zeichnung ist perfekt für mich, aber leider sollte ich sie laut Android nicht verwenden, da sie die Warnung "zu viele Ansichten" zurückgibt. Ich habe die folgenden Methoden für die Leinwandzeichnung ausprobiert, aber ich bekomme immer noch nicht das gewünschte Ergebnis.Canvas-Zeichnung wird trotz Einstellung der Eigenschaften nicht richtig gezeichnet

Ich habe das Projekt auf einem Dutzend Emulatoren getestet und sie alle nehmen nicht mehr als eine Sekunde auf, obwohl die XML-Zeichnung so viele Ansichten hat.

  1. verschiedenen Zeichnungen Unter Verwendung basierend auf der Ausrichtung des Geräts
  2. Verwendung von Float-Werte eher als ganze Zahlen
  3. Einstellen der Float-Werte mehrmals

weiß jemand, was andere Optionen gibt es zu lösen Dieses lästige Canvas-Problem und stellen Sie auch sicher, dass die Canvas-Zeichnung unabhängig von Bildschirmgröße und -ausrichtung genauso aussieht wie die XML-Zeichnung? Sollte die "zu viele Ansichten" Warnung in diesem Szenario ignoriert werden und/oder ich die Anzahl der Aufrufe auf über 80 erhöhen? Alle relevante Hilfe würde sehr geschätzt werden.

Java-Code

http://pastebin.com/VXgkJR2Z

XML-Code

http://pastebin.com/JyVvxS5n

enter image description here enter image description here

+0

so tun müssen Sie in der Lage sein, diese Rects oder etwas zu wechseln? – tachyonflux

+0

Sie können benutzerdefinierte Ansichten erstellen oder 'include' verwenden, um Ihr Layout zu trennen und die Flusenwarnung zu umgehen. Ich glaube nicht, dass dies Auswirkungen auf die Leistung hätte. Es ist schließlich nur eine Warnung. – tachyonflux

Antwort

7

Im Folgenden finden Sie Ergebnisse nach der Arbeit an Ihrem Code sehen können. Es ist fast ähnlich wie das XML, aber wenn Sie es mit mignifier betrachten, können Sie einige Unterschiede finden.

So gibt es einige wichtige Dinge, wenn Sie zeichnen.

  1. Verwenden Sie nicht int. Du verlierst die Präzision. Ich habe alle int ersetzt, um in Ihrem Code zu schwimmen.
  2. Seien Sie vorsichtig in Schleifen. Du verlierst auch in Loops die Präzision.

gemeinsame Muster in Ihrem Code:

float boxWidth = (getWidth() - mSideRectWidth)/8; // I replaced int to float 
for (int i = 0; i < 8; i++) { 
    float position = i * boxWidth; // loss of precision 
    ... 
} 

Es ist besser Position in der Schleife zu berechnen:

for (int i = 0; i < 8; i++) { 
    float position = i * (getWidth() - mSideRectWidth)/8; 
    ... 
} 
  1. den Hub nicht Vergessen Sie Breite. Sie vermissen diesen Wert, wenn Sie Positionen von Formen und Linien berechnen.

Und hier ist mein voller Code:

import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.RectF; 
import android.text.TextPaint; 
import android.util.AttributeSet; 
import android.util.TypedValue; 
import android.view.View; 

public class Car extends View { 
    private final Paint mBlackPaint = new Paint(); 
    private final Paint mRedPaint = new Paint(); 
    private final TextPaint mTextPaint; 

    public static final int BOXES_COUNT = 8; 

    private float oneDp; 
    private float textSize; 
    private float windowHeight; 

    public Car(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     oneDp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, 
      getResources().getDisplayMetrics()); 
     windowHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, 
      getResources().getDisplayMetrics()); 
     textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 15, 
      getResources().getDisplayMetrics()); 

     mRedPaint.setColor(Color.parseColor("#CC3333")); 

     mBlackPaint.setAntiAlias(true); 
     mBlackPaint.setColor(Color.BLACK); 
     mBlackPaint.setStrokeWidth(oneDp); 
     mBlackPaint.setStyle(Paint.Style.STROKE); 

     mTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); 
     mTextPaint.setColor(Color.BLACK); 
     mTextPaint.setTextAlign(Paint.Align.CENTER); 
     mTextPaint.setTextSize(textSize); 

     mWindowPaint = new Paint(); 
     mWindowPaint.setAntiAlias(true); 
     mWindowPaint.setColor(Color.parseColor("#CC3333")); 
     mWindowPaint.setStyle(Paint.Style.STROKE); 
     mWindowPaint.setStrokeWidth(oneDp); 
    } 

    private Paint mWindowPaint; 
    RectF rect = new RectF(); 
    RectF rect2 = new RectF(); 

    @Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 

     if (getWidth() == 0) return; 

     int w = canvas.getWidth(); 
     int h = canvas.getHeight(); 

     //draw red rectangles 
     float mSideRectWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, 
      getResources().getDisplayMetrics()); 
     canvas.drawRect(0, 0, mSideRectWidth, getHeight(), mRedPaint); //draw left end rectangle 
     canvas.drawRect(getWidth() - mSideRectWidth, 0, getWidth(), getHeight(), 
      mRedPaint); //draw right end rectangle 

     //draw grey boxes 
     setBackgroundColor(Color.parseColor("#808080")); 

     for (int i = 0; i < BOXES_COUNT; i++) { 
      float leftPosition = mSideRectWidth 
       + i * oneDp 
       + (getWidth() - mSideRectWidth * 2 - (BOXES_COUNT - 1) * oneDp) * i/BOXES_COUNT; 
      float rightPosition = mSideRectWidth 
       + i * oneDp 
       + (getWidth() - mSideRectWidth * 2 - (BOXES_COUNT - 1) * oneDp) * (i + 1) 
       /BOXES_COUNT; 
      if (i == 0) { 
       fillRectLeft(canvas, leftPosition, rightPosition, (i + 1) + ""); 
      } else if (i == BOXES_COUNT - 1) { 
       fillRectRight(canvas, leftPosition, rightPosition, (i + 1) + ""); 
      } else { 
       fillRect(canvas, leftPosition, rightPosition, (i + 1) + ""); 
      } 
     } 

     //draw black lines 
     for (int i = 1; i < BOXES_COUNT; i++) { 
      float position = mSideRectWidth + (getWidth() - mSideRectWidth * 2) * i/BOXES_COUNT; 
      canvas.drawLine(position, 0, position, getHeight(), mBlackPaint); 
     } 
    } 

    private void fillRect(Canvas canvas, float left, float right, String number) { 
     rect.set(left + oneDp/2, 0 + oneDp/2, right - oneDp/2, getHeight() - oneDp/2); 
     float xPos = left + ((right - left)/2); 
     float yPos = (canvas.getHeight()/2) - ((mTextPaint.descent() + mTextPaint.ascent())/2); 
     //((textPaint.descent() + textPaint.ascent())/2) is the distance from the baseline to the center. 
     canvas.drawText(number, xPos, yPos, mTextPaint); 
     //canvas.drawRect(rect, mWindowPaint); 

     // top row 
     rect2.set(left + oneDp/2, 0 + oneDp/2, left + (right - left) * 20/100 - oneDp/2, 
      windowHeight - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
     rect2.set(left + (right - left) * 27/100 + oneDp/2, 0 + oneDp/2, 
      left + (right - left) * 47/100 - oneDp/2, windowHeight - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
     rect2.set(left + (right - left) * 53/100 + oneDp/2, 0 + oneDp/2, 
      left + (right - left) * 73/100 - oneDp/2, windowHeight - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
     rect2.set(left + (right - left) * 80/100 + oneDp/2, 0 + oneDp/2, 
      left + (right - left) * 100/100 - oneDp/2, windowHeight - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 

     // bottom row 
     rect2.set(left + oneDp/2, getHeight() - windowHeight + oneDp/2, 
      left + (right - left) * 20/100 - oneDp/2, getHeight() - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
     rect2.set(left + (right - left) * 27/100 + oneDp/2, 
      getHeight() - windowHeight + oneDp/2, left + (right - left) * 47/100 - oneDp/2, 
      getHeight() - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
     rect2.set(left + (right - left) * 53/100 + oneDp/2, 
      getHeight() - windowHeight + oneDp/2, left + (right - left) * 73/100 - oneDp/2, 
      getHeight() - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
     rect2.set(left + (right - left) * 80/100 + oneDp/2, 
      getHeight() - windowHeight + oneDp/2, left + (right - left) * 100/100 - oneDp/2, 
      getHeight() - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
    } 

    private void fillRectLeft(Canvas canvas, float left, float right, String number) { 
     rect.set(left + oneDp/2, 0 + oneDp/2, right - oneDp/2, getHeight() - oneDp/2); 
     float xPos = left + ((right - left)/2); 
     float yPos = (canvas.getHeight()/2) - ((mTextPaint.descent() + mTextPaint.ascent())/2); 
     //((textPaint.descent() + textPaint.ascent())/2) is the distance from the baseline to the center. 
     canvas.drawText(number, xPos, yPos, mTextPaint); 
     //canvas.drawRect(rect, mWindowPaint); 

     // top row 
     rect2.set(left + (right - left) * 4/100 + oneDp/2, 0 + oneDp/2, 
      left + (right - left) * 24/100 - oneDp/2, windowHeight - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
     rect2.set(left + (right - left) * 42/100 + oneDp/2, 0 + oneDp/2, 
      left + (right - left) * 62/100 - oneDp/2, windowHeight - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
     rect2.set(left + (right - left) * 80/100 + oneDp/2, 0 + oneDp/2, 
      left + (right - left) * 100/100 - oneDp/2, windowHeight - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 

     // bottom row 
     rect2.set(left + (right - left) * 4/100 + oneDp/2, 
      getHeight() - windowHeight + oneDp/2, left + (right - left) * 24/100 - oneDp/2, 
      getHeight() - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
     rect2.set(left + (right - left) * 42/100 + oneDp/2, 
      getHeight() - windowHeight + oneDp/2, left + (right - left) * 62/100 - oneDp/2, 
      getHeight() - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
     rect2.set(left + (right - left) * 80/100 + oneDp/2, 
      getHeight() - windowHeight + oneDp/2, left + (right - left) * 100/100 - oneDp/2, 
      getHeight() - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
    } 

    private void fillRectRight(Canvas canvas, float left, float right, String number) { 
     rect.set(left + oneDp/2, 0 + oneDp/2, right - oneDp/2, getHeight() - oneDp/2); 
     float xPos = left + ((right - left)/2); 
     float yPos = (canvas.getHeight()/2) - ((mTextPaint.descent() + mTextPaint.ascent())/2); 
     //((textPaint.descent() + textPaint.ascent())/2) is the distance from the baseline to the center. 
     canvas.drawText(number, xPos, yPos, mTextPaint); 
     //canvas.drawRect(rect, mWindowPaint); 

     // top row 
     rect2.set(left + (right - left) * 0/105 + oneDp/2, 0 + oneDp/2, 
      left + (right - left) * 20/105 - oneDp/2, windowHeight - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
     rect2.set(left + (right - left) * 38/105 + oneDp/2, 0 + oneDp/2, 
      left + (right - left) * 58/105 - oneDp/2, windowHeight - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
     rect2.set(left + (right - left) * 78/105 + oneDp/2, 0 + oneDp/2, 
      left + (right - left) * 98/105 - oneDp/2, windowHeight - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 

     // bottom row 
     rect2.set(left + (right - left) * 0/105 + oneDp/2, 
      getHeight() - windowHeight + oneDp/2, left + (right - left) * 20/105 - oneDp/2, 
      getHeight() - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
     rect2.set(left + (right - left) * 38/105 + oneDp/2, 
      getHeight() - windowHeight + oneDp/2, left + (right - left) * 58/105 - oneDp/2, 
      getHeight() - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
     rect2.set(left + (right - left) * 78/105 + oneDp/2, 
      getHeight() - windowHeight + oneDp/2, left + (right - left) * 98/105 - oneDp/2, 
      getHeight() - oneDp/2); 
     canvas.drawRect(rect2, mWindowPaint); 
    } 
} 

Portrait Portrait

Landschaft Landscape

+1

Ihre Antwort würde verbessert werden, wenn Sie 'float' in' double' ändern würden. Auf der meisten Hardware ist der einzige Vorteil von einzelnen Floats über Double Floats, wenn Sie mit riesigen Arrays von ihnen zu tun haben, die einzelne Version nimmt halb so viel Platz und verwendet die Hälfte der Speicherbandbreite. Sonst gewinnt "double" überall. Selbst wenn Sie einen gültigen Grund für _store_ floats haben, sollten Sie sie zu einer Verdoppelung anpreisen, wenn Sie sie in Berechnungen verwenden. –

+0

Wie würde ich eines der roten Fenster in 'mWindowPaint.setStyle (Paint.Style.STROKE_AND_FILL)' anstelle von 'mWindowPaint.setStyle (Paint.Style.STROKE)' ändern? Insbesondere für eines der roten Fenster in den Kästchen 2-7. – MacaronLover

+0

@MacaronLover ja, du hast Recht. Fügen Sie einfach die Zeile 'mWindowPaint.setStyle (Paint.Style.FILL_AND_STROKE);' hinzu, bevor Sie das gefüllte Rechteck zeichnen und kehren Sie dann zu 'mWindowPaint.setStyle (Paint.Style.STROKE)' zurück, bevor Sie ein leeres Rechteck zeichnen. –

-1

Was die beiden Varianten zu kombinieren - fügen Sie diese Ansichten programmatisch mit
addView (your_view, your_layout_params)

Verwandte Themen