Rotating Wheel with rotating icons - java

Now these days i am working on Rotating wheel likely attached screenshot.
I've found code from github https://github.com/R4md4c/AndroidRotaryWheelView
The difficulty is that i am not able to keep icons in vertical position during rotation of the wheel. Icons being rotated in form of its Wheel's Segment While it is required to keep them in vertical position as they are being displayed initially (as per screenshot-1).
I have to customize the following code where i need to change the Bounds for particular drawable's rect.
I find myself unable to achieve the exact calculation in the reference.
Any help would be highly appreciated.
#Override
public void onDraw(Canvas canvas) {
// set the height of Wheel childs items
canvas.scale(getWidth() / mViewRect.width(), getHeight() / 2
/ mViewRect.width(), xPosition, yPosition);
canvas.save(Canvas.MATRIX_SAVE_FLAG); // Saving the canvas and later
// restoring it so only this
// image will be rotated.
canvas.rotate((float) mRotationAngle, xPosition, yPosition);
for (int i = 0; i < mWedges.length; i++) {
Wedge f = mWedges[i];
mPaint.setColor(SEGMENT_COLOR);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawPath(f, mPaint);
Rect rf = iconRect[i];
if ((mMenuEntries.get(i).getIcon() != 0)
&& (mMenuEntries.get(i).getLabel() != null)) {
System.out.println("the canvasd drawn ........");
// This will look for a "new line" and split into multiple lines
String menuItemName = mMenuEntries.get(i).getLabel();
String[] stringArray = menuItemName.split("\n");
mPaint.setColor(textColor);
mPaint.setStyle(Paint.Style.FILL);
// mPaint.setTextSize(textSize);
Rect rect = new Rect();
float textHeight = 0;
for (int j = 0; j < stringArray.length; j++) {
mPaint.getTextBounds(stringArray[j], 0,
stringArray[j].length(), rect);
textHeight = textHeight + (rect.height() + 3);
}
Rect rf2 = new Rect();
rf2.set(rf.left, rf.top - ((int) textHeight / 2), rf.right,
rf.bottom - ((int) textHeight / 2));
float textBottom = rf2.bottom;
for (int j = 0; j < stringArray.length; j++) {
mPaint.getTextBounds(stringArray[j], 0,
stringArray[j].length(), rect);
float textLeft = rf.centerX() - rect.width() / 2;
textBottom = textBottom + (rect.height() + 3);
mPaint.setTextSize(scalePX(8));
canvas.drawText(stringArray[j], textLeft - rect.left,
textBottom - rect.bottom, mPaint);
}
// canvas.rotate((float)mRotationAngle,
// rf.top-((int)textHeight/2), rf.bottom-((int)textHeight/2));
int index = checkSelection(canvas);
rf2 = rotaionRf(rf2, mRotationAngle);
if (i == index) {
// Puts in the Icon
Drawable drawable = getResources().getDrawable(
mMenuEntries.get(i).getIconSelected());
drawable.setBounds(rf2);
drawable.draw(canvas);
} else {
// Puts in the Icon
Drawable drawable = getResources().getDrawable(
mMenuEntries.get(i).getIcon());
drawable.setBounds(rf2);
drawable.draw(canvas);
}
// Icon Only
} else if (mMenuEntries.get(i).getIcon() != 0) {
System.out.println("the canvasd drawn ELSE........");
// Puts in the Icon
Drawable drawable = getResources().getDrawable(
mMenuEntries.get(i).getIconSelected());
drawable.setBounds(rf);
drawable.draw(canvas);
// Text Only
} else {
// Puts in the Text if no Icon
mPaint.setColor(this.textColor);
/*
* if (f != enabled && Wedge2Shown == true) {
* mPaint.setAlpha(disabledAlpha); } else {
* mPaint.setAlpha(textAlpha); }
*/
// mPaint.setAlpha(textAlpha);
mPaint.setStyle(Paint.Style.FILL);
// mPaint.setTextSize(textSize);
// This will look for a "new line" and split into multiple lines
String menuItemName = mMenuEntries.get(i).getLabel();
String[] stringArray = menuItemName.split("\n");
// gets total height
Rect rect = new Rect();
float textHeight = 0;
for (int j = 0; j < stringArray.length; j++) {
mPaint.getTextBounds(stringArray[j], 0,
stringArray[j].length(), rect);
textHeight = textHeight + (rect.height() + 3);
}
float textBottom = rf.centerY() - (textHeight / 2);
for (int j = 0; j < stringArray.length; j++) {
mPaint.getTextBounds(stringArray[j], 0,
stringArray[j].length(), rect);
float textLeft = rf.centerX() - rect.width() / 2;
textBottom = textBottom + (rect.height() + 3);
canvas.drawText(stringArray[j], textLeft - rect.left,
textBottom - rect.bottom, mPaint);
}
// canvas.drawTextOnPath(text, path, hOffset, vOffset, paint)
// canvas.rotate((float)mRotationAngle, xPosition, yPosition );
// canvas.drawRect(rf, mPaint);
}
// canvas.restore();
}
// canvas.restore();
canvas.restore();
// System.out.println()
canvas.save();
canvas.restore();
mPaint.setShader(mShader);
// mPaint.setAlpha(0x66);
// Draw the Selection Segment
if (mSelectionWedge != null) {
canvas.drawPath(mSelectionWedge, mPaint);
// canvas.drawRect(mSelectionWedge.getWedgeRegion().getBounds(),
// mPaint);
}
mPaint.setShader(null);
int index = checkSelection(canvas);
System.out.println("the index=====" + index);
if (checkSelection(canvas) != -1) {
}
}

on using canvas.rotate u have to make sure the x&y values u give it are the MAIN wheel center.

Related

How to make object dissapear when hit

I was working on a brick breaker game in proccessing, and was trying to create the collision system for the game. I was able to identify when a collision happens between the ball and the brick, but I was not able to to make the brick dissapear when it gets hit by the ball. How do I do this? I would also appreciate a explanation, as I am a beginner.
Thanks.
color black = color(0,0,0);
color red = color(255,0,0);
color white = color(255,255,255);
float ballx = 412.5, bally = 600, balld = 20, ballr = balld/2, paddleX = 362.5, paddleY = 650;
float paddleW = 100, paddleH = 15;
float ballspdX, ballspdY;
boolean ball_drop = true;
float direction_choice;
float[] brickX = new float[10];
float[] brickY = new float[5];
float brickW = 50, brickH = 25;
void setup(){
size(825,800);
surface.setTitle("Brick breaker");
noCursor();
smooth();
brickX[0] = 50;
brickX[1] = 125;
brickX[2] = 200;
brickX[3] = 275;
brickX[4] = 350;
brickX[5] = 425;
brickX[6] = 500;
brickX[7] = 575;
brickX[8] = 650;
brickX[9] = 725;
brickY[0] = 50;
brickY[1] = 125;
brickY[2] = 200;
brickY[3] = 275;
brickY[4] = 350;
}
void paddle(){
noStroke();
fill(white);
rect(paddleX, paddleY, paddleW, paddleH);
}
void ball(){
noStroke();
fill(red);
circle(ballx, bally, balld);
}
void draw(){
background(black);
paddle();
ball();
if (bally + ballr == paddleY && ballx > paddleX && ballx < paddleX + (paddleW / 2)){
ball_drop = false;
ballspdY = -ballspdY;
ballspdX = -4;
}
/*
if (bally + ballr == paddleY && ballx > paddleX && ballx < paddleX + paddleW){
ball_drop = false;
ballspdY = -ballspdY;
direction_choice = int(random(1,3));
if (direction_choice == 1){
ballspdX = 4;
}
if (direction_choice == 2){
ballspdX = -4;
}
}
println(direction_choice);
*/
if (bally + ballr == paddleY && ballx > paddleX + (paddleW /2) && ballx < paddleX + paddleW){
ball_drop = false;
ballspdY = -ballspdY;
ballspdX = 4;
}
if (ballx + ballr > width || ballx - ballr < 0){
ballspdX = -ballspdX;
}
if (bally - ballr < 0){
ballspdY = -ballspdY;
}
if (ball_drop){
ballspdX = 0;
ballspdY = 1;
}
for (int i = 0; i < brickX.length; i ++){
for(int j = 0; j < brickY.length; j ++){
fill(red);
rect(brickX[i], brickY[j], brickW, brickH);
if (collideLineCircle(brickX[i], brickY[j] + brickH, brickX[i] + brickW, brickY[j] + brickH, ballx, bally, ballr)){
ballspdY = -ballspdY;
}
}
}
if (bally >= 800){
bally = 600;
ballx = 412.5;
ball_drop = true;
}
bally += ballspdY;
ballx += ballspdX;
}
boolean collideLineCircle(float x1, float y1, float x2, float y2, float cx, float cy, float cr){
float A = y2 - y1, B = x1 - x2, C = x2*y1 - x1+y2;
float denom = A+A + B*B;
if (denom == 0){
return dist(x1,y1, cx, cy) < cr;
}
float Ix = (B*B*cx-A*B*cy - A*C)/denom, Iy = (A*A*cy-A*B*cx - B*C)/denom;
if (Ix >= min(x1,x2) && Ix <= max(x1,x2) & Iy >= min(y1,y2) && Iy <= max(y1,y2)) {
return abs (A*cx + B*cy + C)/sqrt(denom) < cr;
}
float d1 = dist(x1,y1,cx,cy), d2 = dist(x2,y2,cx,cy);
return min(d1,d2) < cr;
}
void mouseMoved(MouseEvent evt){
paddleX = evt.getX();
}
There are a number of ways this can be done. Perhaps the simplest change, given the data structures you already have is to create another array, this time a boolean array, and call it something like brickIsVisible.
Then you can use a simple if statement, e.g., if (brickIsVisible[i]) in your loops to determine how to color the brick. The same variable can be used to tell whether or not to do a collision test between the ball and the brick.
As for the coloring itself, there are a couple options.
I'm not sure how you are drawing your board. If you redraw the entire board with each gameloop frame, then presumably you first draw the background (which covers over the bricks) and then you draw the bricks. If this what is happening, then if brickIsVisible[i] is false you can simply omit drawing that brick on top of the background.
Another technique that is sometimes used is to make use of a transparent color. This is done by adding an alpha channel value to the color definition. Thus there are four variables instead of three. They are referred to as RGBA instead of RGB. If the fourth variable is 0, the color will be transparent. If it is 255 it will be fully visible. Intermediate values in sequence can be used if you want to create a fade in or fade out.
I am guessing you are using java.awt.Color. Following is an example that uses the four argument constructor, with the fourth being the alpha channel.
Color invisiblePurple = new Color(255, 0, 255, 0);
If the color is invisible, the RGB values don't really matter.
These days I mostly use JavaFX for graphics, so I might not be up on all the tricks of the trade with AWT/Swing. With JavaFX, one can directly set an opacity property for a graphic being displayed, which is pretty convenient. I think part of the reason that this is available in JavaFX is that screen graphics are structured more like a DOM tree (like an HTML domain object model), and the redrawing is handled behind the scenes on the current state of the tree, rather than explicitly for each object, as it is with AWT/Swing.
Another possible technique shown below uses a brick class array. The class has a 'show' boolean associated with it and the bricks are only displayed when brick[id].show is true. In this demo when the brick is selected with a mouse brick[id].show is set to false and that brick is not displayed. For your project you would have to do this when a brick is hit by the ball.
/*
Creates a grid of rectangles from a Brick class array.
Syntax: brick[id] = new Brick( x, y, w, h, "title", bkgrndColor, txtColor);
ID is taken from position in array.
*/
final int _brickGridX = 40;
final int _brickGridY = 60;
final int _brickW = 120;
final int _brickH = 60;
color BLUE = color(64, 124, 188);
color LTGRAY = color(185, 180, 180);
color YELLOW = color(245, 250, 13);
color RED = color(255, 0, 0);
color BLACK = color(0, 0, 0);
color WHITE = color(255, 255, 255);
Brick[] brick;
class Brick {
float x, y, w, h;
String title;
color bkgrnd;
color txtColor;
boolean show;
// Constructor
Brick(int xpos, int ypos, float wt, float ht, String titleStr, color background, color foreground) {
x = xpos;
y = ypos;
w = wt;
h = ht;
title = titleStr;
bkgrnd = background;
txtColor = foreground;
}
void display(int id) {
if (brick[id].show) {
fill(bkgrnd); // background color
stroke(0);
rect(x, y, w, h);
fill(txtColor); // text color
textSize(42);
textAlign(CENTER, CENTER);
text(title, x, y, w, h);
}
}
void press(int id) {
println("brick id = ", id + ": show =", brick[id].show);
}
}
void brickGrid() {
int left = 0;
int top = 0;
int vg = 0; // Space between cols (vert.gutter)
int hg = 0; // Space between rows (horz.gutter)
int rows = 5;
int cols = 5;
int id = 0;
brick = new Brick[rows*cols]; // creates brick array
for (int k = 0; k < cols; k++) {
for (int j = 0; j < rows; j++) {
left = _brickGridX + j * (_brickW + vg);
top = _brickGridY + k * (_brickH + hg);
brick[id] = new Brick(left, top, _brickW, _brickH, str(id), LTGRAY, BLACK);
brick[id].show = true;
id++;
}
}
}
void setup() {
size(800, 600);
background(BLUE);
brickGrid();
}
void draw() {
background(BLUE);
for (int i = 0; i < brick.length; i++) {
brick[i].display(i);
}
}
void mousePressed() {
for (int i = 0; i < brick.length; i++) {
if ((mouseX >= brick[i].x) && (mouseX <= brick[i].x + _brickW) && (mouseY >= brick[i].y) && (mouseY <= brick[i].y + _brickH)) {
brick[i].show = false;
// brick[i].press(i);
}
}
}

How to Place Bitmaps Vertically

I've got some code from user xil3 where it merges the bitmaps horizontally. Does anyone know how I can make it to do it vertically instead?
public Bitmap combineImages(Bitmap c, Bitmap s, String loc) { // can add a 3rd parameter 'String loc' if you want to save the new image - left some code to do that at the bottom
Bitmap cs = null;
int width, height = 0;
if (c.getHeight() > s.getHeight()) {
width = c.getWidth() + s.getWidth();
height = c.getHeight();
} else {
width = c.getWidth() + s.getWidth();
height = s.getHeight();
}
cs = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
Canvas comboImage = new Canvas(cs);
comboImage.drawBitmap(c, 0f, 0f, null);
comboImage.drawBitmap(s, c.getHeight(), 0f, null);
// this is an extra bit I added, just incase you want to save the new image somewhere and then return the location
String tmpImg = String.valueOf(System.currentTimeMillis()) + ".png";
OutputStream os = null;
try {
os = new FileOutputStream(loc + tmpImg);
cs.compress(Bitmap.CompressFormat.PNG, 100, os);
} catch (IOException e) {
Log.e("combineImages", "problem combining images", e);
}
return cs;
}
I ended up finding a new piece of code here which saves them vertically-
private Bitmap mergeMultiple(ArrayList<Bitmap> parts) {
int w = 0, h = 0;
for (int i = 0; i < parts.size(); i++) {
if (i < parts.size() - 1) {
w = parts.get(i).getWidth() > parts.get(i + 1).getWidth() ? parts.get(i).getWidth() : parts.get(i + 1).getWidth();
}
h += parts.get(i).getHeight();
}
Bitmap temp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(temp);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
int top = 0;
for (int i = 0; i < parts.size(); i++) {
top = (i == 0 ? 0 : top + parts.get(i).getHeight() + 100);
canvas.drawBitmap(parts.get(i), 0f, top,paint );
}
return temp;
}

Java OpenCV Layer small image onto larger image with transparency

I am trying to write a function that overlays an image at a rectangle with transparency over top of another image, However it doesn't layer the images it just erases the section that I overlay and the transparency cuts through the entire image. Here is my code.
public static void overlayImage(String imagePath, String overlayPath, int x, int y, int width, int height) {
Mat overlay = Imgcodecs.imread(overlayPath, Imgcodecs.IMREAD_UNCHANGED);
Mat image = Imgcodecs.imread(imagePath, Imgcodecs.IMREAD_UNCHANGED);
Rectangle rect = new Rectangle(x, y, width, height);
Imgproc.resize(overlay, overlay, rect.size());
Mat submat = image.submat(new Rect(rect.x, rect.y, overlay.cols(), overlay.rows()));
overlay.copyTo(submat);
Imgcodecs.imwrite(imagePath, image);
}
EDIT: Here are some example pictures:
Before:
After:
Found this function that does exactly what I needed.
public static void overlayImage(Mat background,Mat foreground,Mat output, Point location){
background.copyTo(output);
for(int y = (int) Math.max(location.y , 0); y < background.rows(); ++y){
int fY = (int) (y - location.y);
if(fY >= foreground.rows())
break;
for(int x = (int) Math.max(location.x, 0); x < background.cols(); ++x){
int fX = (int) (x - location.x);
if(fX >= foreground.cols()){
break;
}
double opacity;
double[] finalPixelValue = new double[4];
opacity = foreground.get(fY , fX)[3];
finalPixelValue[0] = background.get(y, x)[0];
finalPixelValue[1] = background.get(y, x)[1];
finalPixelValue[2] = background.get(y, x)[2];
finalPixelValue[3] = background.get(y, x)[3];
for(int c = 0; c < output.channels(); ++c){
if(opacity > 0){
double foregroundPx = foreground.get(fY, fX)[c];
double backgroundPx = background.get(y, x)[c];
float fOpacity = (float) (opacity / 255);
finalPixelValue[c] = ((backgroundPx * ( 1.0 - fOpacity)) + (foregroundPx * fOpacity));
if(c==3){
finalPixelValue[c] = foreground.get(fY,fX)[3];
}
}
}
output.put(y, x,finalPixelValue);
}
}
}

Java - Tracing outline of abstract shapes and making outer pixels transparent

I want to layer two images together. A background and foreground. The foreground is stitched together as a grid of smaller images (3x3). I have been able to make all white pixels transparent as a workaround, however the inside of the shapes are white and I only want pixels outside the shapes transparent.
Say for example the grid of images contained a circle or square in each grid location. Is there a way I can iterate over each pixel and create two arrays of pixel locations - those outside the images making them transparent, and those inside the images where I can set the colour?
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
// Stitches a grid of images together, scales a background image to fit and layers them.
public class Layer {
public static void layerImages() {
// Grid layout of images to stitch.
int rows = 3;
int cols = 3;
int chunks = rows * cols;
int chunckWidth, chunkHeight;
// Image files to stitch
File[] imgFiles = new File[chunks];
for(int i = 0; i < chunks; i++) {
imgFiles[i] = new File("ocarina_sprite" + (i + 1) + ".png");
}
// Read images into array.
try {
BufferedImage[] buffImages = new BufferedImage[chunks];
for (int i = 0; i < chunks; i++) {
buffImages[i] = ImageIO.read(imgFiles[i]);
}
chunckWidth = buffImages[0].getWidth();
chunkHeight = buffImages[0].getHeight();
BufferedImage finalImage = new BufferedImage(chunckWidth * cols, chunkHeight*rows, BufferedImage.TYPE_INT_ARGB);
// Calculate background width and height to cover stitched image.
int bwidth = 0;
int bheight = 0;
for(int i = 0; i < rows; i++) {
bwidth += buffImages[i].getWidth();
}
for(int i = 0; i < cols; i++) {
bheight += buffImages[i].getHeight();
}
// Background image
File dory = new File("dory.png");
BufferedImage original = ImageIO.read(dory);
// Scale background image.
BufferedImage background = scale(original, bwidth, bheight);
// Prepare final image by drawing background first.
Graphics2D g = finalImage.createGraphics();
g.drawImage(background, 0, 0, null);
// Prepare foreground image.
BufferedImage foreground = new BufferedImage(chunckWidth * cols, chunkHeight*rows, BufferedImage.TYPE_INT_ARGB);
// Stitch foreground images together
int num = 0;
for(int i = 0; i < rows; i++) {
for(int j = 0; j < rows; j++) {
foreground.createGraphics().drawImage(buffImages[num],chunckWidth * j, chunkHeight * i, null);
num++;
}
}
// Set white pixels to transparent.
for (int y = 0; y < foreground.getHeight(); ++y) {
for (int x = 0; x < foreground.getWidth(); ++x) {
int argb = foreground.getRGB(x, y);
if ((argb & 0xFFFFFF) > 0xFFFFEE) {
foreground.setRGB(x, y, 0x00FFFFFF);
}
}
}
// Draw foreground image to final image.
Graphics2D g3 = finalImage.createGraphics();
g3.drawImage(foreground, 0, 0, null);
// Output final image
ImageIO.write(finalImage, "png", new File("finalImage.png"));
}
catch (Exception e) {
System.out.println(e);
}
}
// Scale image
public static BufferedImage scale(BufferedImage imageToScale, int dWidth, int dHeight) {
BufferedImage scaledImage = null;
if (imageToScale != null) {
scaledImage = new BufferedImage(dWidth, dHeight, imageToScale.getType());
Graphics2D graphics2D = scaledImage.createGraphics();
graphics2D.drawImage(imageToScale, 0, 0, dWidth, dHeight, null);
graphics2D.dispose();
}
return scaledImage;
}
}
The floodfill solution mentioned in the comment was what I needed to solve the problem, however the recursion over a million+ pixels didn't work out so I implemented the forest fire algorithm which is floodfill using queues instead of recursion.
public static void forestFire(int width, int height, int x, int y) {
// Check if already set
int argb = foreground.getRGB(x, y);
if (((argb >> 24) & 0xFF) == 0) {
return;
}
coords.add(new Point(x, y));
// Set transparent pixel
foreground.setRGB(x, y, 0x00FFFFFF);
Point currentCoord = new Point();
while(!coords.isEmpty()) {
currentCoord.setLocation(coords.poll());
// Get current coordinates
x = (int)currentCoord.getX();
y = (int)currentCoord.getY();
// North
if(y != 0) {
int north = foreground.getRGB(x, y - 1);
// Check if transparent (already set) and check target colour (white)
if (((north >> 24) & 0xFF) > 0 && (north & 0xFFFFFF) > 0x111100) {
// Set transparent pixel
foreground.setRGB(x, y - 1, 0x00FFFFFF);
coords.add(new Point(x, y - 1));
}
}
// East
if(x != width - 1) {
int east = foreground.getRGB(x + 1, y);
if (((east >> 24) & 0xFF) > 0 && (east & 0xFFFFFF) > 0x111100) {
foreground.setRGB(x + 1, y, 0x00FFFFFF);
coords.add(new Point(x + 1, y));
}
}
// South
if(y != height - 1) {
int south = foreground.getRGB(x, y + 1);
if (((south >> 24) & 0xFF) > 0 && (south & 0xFFFFFF) > 0x111100) {
foreground.setRGB(x, y + 1, 0x00FFFFFF);
coords.add(new Point(x, y + 1));
}
}
// West
if(x != 0) {
int west = foreground.getRGB(x - 1, y);
if (((west >> 24) & 0xFF) > 0 && (west & 0xFFFFFF) > 0x111100) {
foreground.setRGB(x - 1, y, 0x00FFFFFF);
coords.add(new Point(x - 1, y));
}
}
}

How to add rectangles on top of existing rectangle in canvas

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
current undesired outcome
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);
}
}
Try this:
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);
}
}
}
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:
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);
}
}
}

Categories