8

I'm trying to add some red rectangles within my existing canvas on top of specific boxes exactly like the expected result image but they don't appear at all as my code shows the current undesired outcome when I deploy my app. My code is to create 4 rectangles on the top row and 4 rectangles on the bottom row but I only want this to be added on top of boxes 2-6 but I know extra code needs to be added for the red rectangles on top of boxes 1 & 7. Does anyone know what I'm doing wrong and how to fix this? All help would be appreciated.

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);
    }
}
wbk727
  • 8,017
  • 12
  • 61
  • 125
  • You want 3x2 small rectangles i nthe first and last one wihle 4x2 in the 5 center ones? Will the rectangles act as buttons or just sprites? Will they change somehow based on input? – Emz Aug 16 '15 at 19:38
  • can you also post your activity? Ill give it a run... – Theo Aug 16 '15 at 21:10
  • Also the mainactivity? Such that i can run it and solve it.. – Theo Aug 16 '15 at 22:26
  • first of all you have compilation errors. mWindowPaint is not declared global, and the second for loop (where you are drawing red windows) is declaring a variable which is already declared. – Theo Aug 16 '15 at 22:43
  • @TeodorLiv What do you mean by that? – wbk727 Aug 16 '15 at 22:49
  • Nothing. Considering the previous post you had I don't see how you won't be able to do this. Just take it step by step.. – Theo Aug 16 '15 at 22:52
  • Bro, can you check [this](http://stackoverflow.com/questions/28460300/how-to-build-a-horizontal-listview-with-recyclerview) Your too many views error will be solved. The idea is to just make one box out of all those boxes with the maximum elements fitted in, then repeat it and show hide view based on an adapter or a datasource. This would be a listview only thing different is that it would be a horizontal list! – Skynet Aug 20 '15 at 04:00
  • @Skynet I don't want to use the list view method. I find it more efficient to use the canvas as it's easier for me to see what is going on in my code. Do you know how to solve this issue using the canvas? – wbk727 Aug 20 '15 at 10:25
  • @MacaronLover i edited my answer finishing the app, the code is perfectly working on my phone, let me know on yours! :) – Pier Giorgio Misley Aug 27 '15 at 12:17

3 Answers3

3

Try this:

enter image description here

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

        }
    }
}
dieter_h
  • 2,707
  • 1
  • 13
  • 19
  • For some reason, the rectangles don't show up on my emulator nor device at all. Also based on your screenshot, that's not what I'm looking for. I only want boxes 2-6 to have four rectangles on the top & bottom rows along with boxes 1 & 7 to have three rectangles on the top & bottom rows. A specific rectangle needs to be filled also but I've already got the code for that. – wbk727 Aug 22 '15 at 13:09
1

You are drawing all of the rectangles, but it looks like you want to skip all of the "odd" rectangles - or every second rectangle... and be sure to change the color to "red" - something like this:

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

EDIT:

I think the "filled" rectangle on the bottom is supposed to be more like:

    //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);
        }
    }
}
Jim
  • 10,172
  • 1
  • 27
  • 36
  • The actual problem is the red rectangles themselves as they are not appearing at all like in the **expected result** image above. – wbk727 Aug 17 '15 at 18:15
  • I made an edit... does any code you have produce a red rectangle? Originally I thought omitting this "new" code resulted in a truncated top / bottom. – Jim Aug 17 '15 at 18:18
  • The code I have does not produce any red rectangles whatsoever. Just the same thing seen in the posted screenshot. – wbk727 Aug 17 '15 at 18:19
  • yes, I think I see that now... I thought it was a simple index issue, but your measuring and placement are both off. I think this will take some work to sort out... – Jim Aug 17 '15 at 18:23
1

the problem was that you created only 4 rectangles in the screen witdh size, not in the number cell size. here is the code:

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

this is the full code perfectly working for me. if you have any question or doubt feel free to post it :)

this is how i see them: enter image description here

Pier Giorgio Misley
  • 5,305
  • 4
  • 27
  • 66
  • Ok but for some reason they still don't appear & I also get a warning `Avoid object allocations during draw/layout operations (preallocate and reuse instead)`. Please see this link to the screenshot of my evidence: http://picpaste.com/Screen_Shot_2015-08-27_at_14.41.13-WKbVDEPA.png – wbk727 Aug 27 '15 at 13:44
  • @MacaronLover i posted a screen on how i see them, the warningwas there even when i copied your code to my editor, not new after my edits :S – Pier Giorgio Misley Aug 27 '15 at 13:51
  • Boxes 1, 2, 6 & 7 are incorrect. Please have a look at the image under **expected result**. I want the drawing to look exactly like that. – wbk727 Aug 27 '15 at 13:53
  • @MacaronLover i'm fixing it.. one min – Pier Giorgio Misley Aug 27 '15 at 13:58
  • @MacaronLover is it ok now? for little adjustment you can change left-right margin.. – Pier Giorgio Misley Aug 27 '15 at 14:23
  • @MacaronLover i also fixed the alloc problem, you were initializating Rect inside OnDraw, and it is not correct, so i moved them out of it – Pier Giorgio Misley Aug 27 '15 at 14:24
  • Hmmm they're still not appearing on my emulator nor device. Do you think there is something wrong with my Android Studio? Please check this link: http://picpaste.com/Screen_Shot_2015-08-27_at_15.32.49-AzBOsXtD.png – wbk727 Aug 27 '15 at 14:33
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/88102/discussion-between-pier-giorgio-misley-and-macaronlover). – Pier Giorgio Misley Aug 27 '15 at 14:41