如何在画布上添加矩形并放置在现有矩形之上

8
我正在尝试在现有的画布上添加一些红色矩形,覆盖特定的方框,就像预期结果图片中一样,但是当我部署我的应用程序时,它们根本不会出现,而是显示了当前不希望的结果。我的代码是创建顶部行上的4个矩形和底部行上的4个矩形,但我只想将其添加到2-6号方框上,但我知道需要添加额外的代码来处理1号和7号方框上的红色矩形。有人知道我做错了什么以及如何解决吗?任何帮助都将不胜感激。
public class RectangleTextView extends View {
    private final Paint mBlackPaint = new Paint();
    private final Paint mRedPaint = new Paint();
    private final TextPaint mTextPaint;

    public RectangleTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        int valueInDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
        int valueInSp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, getResources().getDisplayMetrics());

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

        mBlackPaint.setAntiAlias(false);
        mBlackPaint.setColor(Color.BLACK);
        mBlackPaint.setStrokeWidth(valueInDp);
        mBlackPaint.setStyle(Paint.Style.STROKE);

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

        mWindowPaint = new Paint();
        mWindowPaint.setColor(Color.parseColor("#CC3333"));
        mWindowPaint.setStrokeWidth(valueInDp);
    }

    private Paint mWindowPaint;

    @Override protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (getWidth() == 0)
            return;

        //initialise red rectangles
        int w = canvas.getWidth();
        int h = canvas.getHeight();

        int rectWidth = w / 5;
        int space = w / 15;
        int topRectHeight = getPaddingTop();
        int bottomRectHeight = getPaddingBottom();


        //draw end rectangles
        int mSideRectWidth = 10;
        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"));
        int boxWidth = (getWidth() - mSideRectWidth) / 7;

        //draw text views
        for (int i = 0; i < 7; i++) {
            canvas.drawText(Integer.toString(i + 1), (i * boxWidth + 10) + (boxWidth / 2), ((canvas.getHeight() / 2) - ((mTextPaint.descent() + mTextPaint.ascent()) / 2)), mTextPaint);
        }

        //draw black lines
        for (int i = 1; i < 7; i++) {
            canvas.drawLine(mSideRectWidth + boxWidth * i, 0, mSideRectWidth + boxWidth * i, getHeight(), mBlackPaint);
        }

        //draw red windows
        for (int i = 0; i < 4; i++) {
            mWindowPaint.setStyle(Paint.Style.STROKE);//add this
            int left = i * (rectWidth + space);
            int right = left + rectWidth;
            if (i == 1){
                mWindowPaint.setStyle(Paint.Style.FILL); // change to this
            }

            Rect rect = new Rect(left, 0, right, topRectHeight);
            canvas.drawRect(rect, mWindowPaint);
            Rect rect2 = new Rect(left, h - bottomRectHeight, right, h);
            canvas.drawRect(rect2, mWindowPaint);
        }
    }
}

"expected result": enter image description here "current undesired outcome": enter image description here "activity_main.xml":
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <com.apptacularapps.car.RectangleTextView
        android:layout_width="100dp"
        android:layout_height="45dp"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        android:background="#808080"
        android:gravity="center"/>

</RelativeLayout>

MainActivity.java

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

你想在第一个和最后一个小方块中放置3x2的矩形,而在中间5个方块中放置4x2的矩形吗?这些矩形将作为按钮还是精灵?它们会根据输入以某种方式改变吗? - Emz
你能否发布一下你的活动?我想试一下... - Theo
首先,您有编译错误。mWindowPaint未声明为全局变量,并且第二个for循环(在其中绘制红色窗口)正在声明已经声明的变量。 - Theo
兄弟,你能看下这个链接吗:https://dev59.com/Jl4b5IYBdhLWcg3w-1-c,你那个太多视图的错误会被解决。思路就是把所有的盒子合并成一个盒子,最多容纳尽可能多的元素,然后重复此操作,根据适配器或数据源显示或隐藏视图。这将只是一个列表视图,唯一的不同在于它是一个水平列表! - Skynet
@MacaronLover 我编辑了我的答案,完成了应用程序,代码在我的手机上完美运行,请告诉我你的情况!:) - Pier Giorgio Misley
显示剩余4条评论
3个回答

3
试试这个:

在此输入图像描述


(注意:本文涉及IT技术相关内容。)
public class RectangleTextView extends View {
    private final Paint mBlackPaint = new Paint();
    private final Paint mRedPaint = new Paint();
    private final TextPaint mTextPaint;

    public RectangleTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        int valueInDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
        int valueInSp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, getResources().getDisplayMetrics());

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

        mBlackPaint.setAntiAlias(false);
        mBlackPaint.setColor(Color.BLACK);
        mBlackPaint.setStrokeWidth(valueInDp);
        mBlackPaint.setStyle(Paint.Style.STROKE);

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

        mWindowPaint = new Paint();
        mWindowPaint.setColor(Color.parseColor("#CC3333"));
        mWindowPaint.setStrokeWidth(valueInDp);
    }

    private Paint mWindowPaint;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (getWidth() == 0)
            return;

        //initialise red rectangles
        int h = canvas.getHeight();


        int topRectHeight = getPaddingTop();
        int bottomRectHeight = getPaddingBottom();


        //draw end rectangles
        int mSideRectWidth = 10;
        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"));
        int boxWidth = (getWidth() - mSideRectWidth) / 7;


        int redRectWidth = boxWidth / 5;
        int redRectSpace = redRectWidth / 3;

        //draw text views
        for (int i = 0; i < 7; i++) {
            canvas.drawText(Integer.toString(i + 1), (i * boxWidth + 10) + (boxWidth / 2), ((canvas.getHeight() / 2) - ((mTextPaint.descent() + mTextPaint.ascent()) / 2)), mTextPaint);

            int baseStartX = i * boxWidth;

            //draw red windows
            for (int j = 0; j < 4; j++) {
                mWindowPaint.setStyle(Paint.Style.STROKE);//add this
                int left = mSideRectWidth + baseStartX + (j * (redRectWidth + redRectSpace));
                int right = left + redRectWidth;
                if (j == 1) {
                    mWindowPaint.setStyle(Paint.Style.FILL); // change to this
                }

                Rect rect = new Rect(left, 0, right, topRectHeight);
                canvas.drawRect(rect, mWindowPaint);
                Rect rect2 = new Rect(left, h - bottomRectHeight, right, h);
                canvas.drawRect(rect2, mWindowPaint);
            }
        }

        //draw black lines
        for (int i = 1; i < 7; i++) {

            int startX = mSideRectWidth + boxWidth * i;
            int startY = 0;
            int stopX = mSideRectWidth + boxWidth * i;
            int stopY = getHeight();
            canvas.drawLine(startX, startY, stopX, stopY, mBlackPaint);

        }
    }
}

由于某些原因,矩形在我的模拟器和设备上都没有显示出来。另外根据你的截图,那不是我要找的东西。我只想让2-6号框有顶部和底部各四个矩形,1号和7号框有顶部和底部各三个矩形。还需要填充特定的矩形,但我已经有了代码。 - wbk727

1
问题在于您只在屏幕宽度大小上创建了4个矩形,而不是在单元格数量大小上创建。 以下是代码:
public class RectangleTextView extends View {
    private final Paint mBlackPaint = new Paint();
    private final Paint mRedPaint = new Paint();
    private final TextPaint mTextPaint;

    public RectangleTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        int valueInDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
        int valueInSp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, getResources().getDisplayMetrics());

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

        mBlackPaint.setAntiAlias(false);
        mBlackPaint.setColor(Color.BLACK);
        mBlackPaint.setStrokeWidth(valueInDp);
        mBlackPaint.setStyle(Paint.Style.STROKE);

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

        mWindowPaint = new Paint();
        mWindowPaint.setColor(Color.parseColor("#CC3333"));
        mWindowPaint.setStrokeWidth(valueInDp);
    }

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

    @Override protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (getWidth() == 0)
            return;

        //initialise red rectangles
        int w = canvas.getWidth();
        int h = canvas.getHeight();

        int rectWidth = ((w - 20) / 7) / 5;
        int space = ((w - 20) / 7) / 15;
        int topRectHeight = getPaddingTop();
        int bottomRectHeight = getPaddingBottom();


        //draw end rectangles
        int mSideRectWidth = 10;
        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"));
        int boxWidth = (getWidth() - mSideRectWidth) / 7;

        //draw text views
        for (int i = 0; i < 7; i++) {
            canvas.drawText(Integer.toString(i + 1), (i * boxWidth + 10) + (boxWidth / 2), ((canvas.getHeight() / 2) - ((mTextPaint.descent() + mTextPaint.ascent()) / 2)), mTextPaint);
        }

        //draw black lines
        for (int i = 1; i < 7; i++) {
            canvas.drawLine(mSideRectWidth + boxWidth * i, 0, mSideRectWidth + boxWidth * i, getHeight(), mBlackPaint);
        }

        //draw red windows
        for (int index = 0; index < 7; index++) {

            if (index == 0 || index == 6) {
                for (int i = 0; i < 3; i++) {
                    mWindowPaint.setStyle(Paint.Style.STROKE);//add this

                    int left = (i * (rectWidth + space)) + (index * boxWidth) + 13 + rectWidth/2 + space/2;
                    int right = left + rectWidth;

                    rect.set(left, 0, right, topRectHeight);
                    canvas.drawRect(rect, mWindowPaint);

                    if (index == 0 && i == 1) {
                        mWindowPaint.setStyle(Paint.Style.FILL); // change to this
                    }
                    rect2.set(left, h - bottomRectHeight, right, h);
                    canvas.drawRect(rect2, mWindowPaint);

                }

            } else {
                for (int i = 0; i < 4; i++) {
                    mWindowPaint.setStyle(Paint.Style.STROKE);//add this
                    int left = (i * (rectWidth + space)) + (index * boxWidth) + 13;
                    int right = left + rectWidth;

                    rect.set(left, 0, right, topRectHeight);

                    canvas.drawRect(rect, mWindowPaint);

                    rect2.set(left, h - bottomRectHeight, right, h);
                    canvas.drawRect(rect2, mWindowPaint);
                }
            }
        }
    }
}

这是完美运行的全部代码。如果您有任何问题或疑问,请随时发布它 :)
我是这样看待它们的:在此输入图像描述

好的,但出于某种原因它们仍然没有出现,并且我还收到了一个警告“避免在绘制/布局操作期间进行对象分配(预先分配和重用)”。请参见我的证据屏幕截图链接:http://picpaste.com/Screen_Shot_2015-08-27_at_14.41.13-WKbVDEPA.png - wbk727
@MacaronLover 我在屏幕上发布了我看到它们的截图,即使我将你的代码复制到我的编辑器中,警告也一直存在,而不是在我的编辑后才出现:S - Pier Giorgio Misley
@MacaronLover 我正在修复它...一分钟。 - Pier Giorgio Misley
@MacaronLover 现在可以了吗?如果需要进行一点调整,你可以改变左右边距。 - Pier Giorgio Misley
@MacaronLover 我也解决了分配问题,你在 OnDraw 中初始化 Rect 是不正确的,所以我将它们移到外面了。 - Pier Giorgio Misley
显示剩余3条评论

1
你正在绘制所有的矩形,但看起来你想跳过所有的“奇数”矩形——或者每隔一个矩形...并确保将颜色更改为“红色”,就像这样:
    //draw red windows
    for (int i = 0; i < 4; i++) {
        mWindowPaint.setStyle(Paint.Style.STROKE);//add this
        int left = i * rectWidth;
        int right = left + rectWidth;
        if (i == 1){
            mWindowPaint.setStyle(Paint.Style.FILL); // change to this
        }

        if (i % 2 == 0) {
            Rect rect = new Rect(left, 0, right, topRectHeight);
            canvas.drawRect(rect, mRedPaint);
            Rect rect2 = new Rect(left, h - bottomRectHeight, right, h);
            canvas.drawRect(rect2, mRedPaint);
        }
    }
}

编辑:

我认为底部的“填充”矩形应该更像:

    //draw red windows
    for (int i = 0; i < 4; i++) {
        int left = i * rectWidth;
        int right = left + rectWidth;

        mWindowPaint.setStyle(Paint.Style.STROKE);//add this
        if (i % 2 == 0) {
            Rect rect = new Rect(left, 0, right, topRectHeight);
            canvas.drawRect(rect, mRedPaint);
            if (i == 1){
                mWindowPaint.setStyle(Paint.Style.FILL); // change to this
            }
            Rect rect2 = new Rect(left, h - bottomRectHeight, right, h);
            canvas.drawRect(rect2, mRedPaint);
        }
    }
}

实际问题是红色矩形本身,它们根本不像上面的“预期结果”图像中那样出现。 - wbk727
我进行了编辑...你的代码是否会产生一个红色矩形?最初我认为省略这个“new”代码会导致顶部/底部被截断。 - Jim
我所拥有的代码根本不会产生任何红色矩形。就像发布的截图中看到的那样。 - wbk727
是的,我现在明白了...我以为这只是一个简单的索引问题,但你的测量和定位都有误。我认为这需要一些工作来解决... - Jim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接