簡體   English   中英

盡管設置屬性,但畫布繪圖未正確繪制

[英]Canvas drawing not being drawn properly despite setting properties

我剛剛制作了2張圖紙,試圖讓其中一張看起來與另一張相同,但我沒有運氣。 關於屏幕截圖,頂部的繪圖是使用畫布創建的,底部的繪圖是使用XML創建的。 XML繪圖對我來說是完美的,但不幸的是根據Android,我不應該使用它,因為它返回“太多視圖”警告。 我已經嘗試了以下方法用於畫布繪制,但我仍然沒有得到所需的結果。

我已經在十幾個仿真器上測試了這個項目,盡管XML繪圖有很多視圖,但它們都只需要一秒鍾就能顯示出來。

  1. 根據設備的方向使用不同的圖紙
  2. 使用浮點值而不是整數
  3. 多次調整浮動值

有沒有人知道有什么其他選項可以解決這個惱人的畫布問題,並確保畫布繪圖看起來與XML繪圖完全相同,無論屏幕大小和方向如何? 此情景中是否應忽略“太多視圖”警告和/或我將查看次數限制增加到80以上? 所有相關的幫助將受到高度贊賞。

Java代碼

http://pastebin.com/VXgkJR2Z

XML代碼

http://pastebin.com/JyVvxS5n

在此輸入圖像描述 在此輸入圖像描述

您可以在下面看到處理代碼后的結果。 它幾乎與xml類似,但是如果你用mignifier來看它,你可以找到一些差異。

所以當你畫畫時有一些重要的事情。

  1. 不要使用int。 你正在失去精確度。 我將所有int替換為代碼中的float。
  2. 循環時要小心。 你也在循環中失去精確度。

代碼中的常見模式:

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

最好在循環中計算位置:

for (int i = 0; i < 8; i++) {
    float position = i * (getWidth() - mSideRectWidth) / 8;
    ...
}
  1. 不要忘記筆畫寬度。 在計算形狀和線條的位置時,您會錯過該值。

這是我的完整代碼:

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

肖像 肖像

景觀 景觀

如何組合這兩個變體 - 以編程方式添加這些視圖
addView(your_view,your_layout_params)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM