Reputation: 268
I would like to draw an 8 by 8 chess board dynamically in android studio using the canvas and by overriding method onDraw, I almost have succeeded but I am running into a very annoying problem.
I already made a custom view, my goal is to make the parent layout match the size of it's child custom view, so my chessboard can cover the entire screen. ( in XML file both parent and child are set to match_parent)
I want the chess board to cover the full height of the screen as well.
Check the picture below here's the result I am getting, notice that huge gap in the lower area, my purpose is to stretch the chessboard vertically and make it cover the entire screen to eliminate that space.
Here's what I managed to write so far but it's not doing what I want : Class ChessBoard:
public class ChessBoard extends View {
private static final String TAG = ChessBoard.class.getSimpleName();
private Rect rect;
private static final int COLS = 8;
private static final int ROWS = 8;
Tile tile;
private final Tile[][] mTiles;
private int x0 = 0;
private int y0 = 0;
private static final int DEF_SQUARE_SIZE=50;
private int squareSize=0;
private boolean flipped = false;
public ChessBoard(final Context context,AttributeSet attrs) {
super(context,attrs);
this.mTiles = new Tile[COLS][ROWS];
buildTiles();
rect=new Rect();
}
onDraw method:
protected void onDraw(final Canvas canvas)
{
int width = getWidth();
int height = getHeight();
squareSize=Math.min(getSquareSizeWidth(width),getSquareSizeHeight(height));
computeOrigins(width,height);
for (int c = 0; c < COLS; c++) {
for (int r = 0; r < ROWS; r++) {
final int xCoord = getXCoord(c);
final int yCoord = getYCoord(r);
mTiles[c][r].setTileRect(rect);
rect.left=xCoord;
rect.top=yCoord;
rect.right= rect.left+squareSize; // right
rect.bottom=rect.top + squareSize;
mTiles[c][r].draw(canvas);
}
}
Class Tile :
public final class Tile {
private static final String TAG = Tile.class.getSimpleName();
private final int col;
private final int row;
private final Paint squareColor;
private Rect tileRect;
public Tile(final int col, final int row) {
this.col = col;
this.row = row;
this.squareColor = new Paint();
squareColor.setColor(isDark() ? Color.BLACK : Color.WHITE);
squareColor.setAntiAlias(true);
}
public void draw(final Canvas canvas) {
canvas.drawRect(tileRect, squareColor);
}
public String getColumnString() {
switch (col) {
case 0: return "A";
case 1: return "B";
case 2: return "C";
case 3: return "D";
case 4: return "E";
case 5: return "F";
case 6: return "G";
case 7: return "H";
default: return null;
}
}
public String getRowString() {
// To get the actual row, add 1 since 'row' is 0 indexed.
return String.valueOf(row + 1);
}
public void handleTouch() {
Log.d(TAG, "handleTouch(): col: " + col);
Log.d(TAG, "handleTouch(): row: " + row);
}
public boolean isDark() {
return (col + row) % 2 == 0;
}
public boolean isTouched(final int x, final int y) {
return tileRect.contains(x, y);
}
public void setTileRect(final Rect tileRect) {
this.tileRect = tileRect;
}
public String toString() {
final String column = getColumnString();
final String row = getRowString();
return "<Tile " + column + row + ">";
}
}
onMeasure Mehtod:
protected void onMeasure(int widthMeasureSpec, int
heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
int sqSizeW = getSquareSizeWidth(width);
int sqSizeH = getSquareSizeHeight(height);
int sqSize = Math.min(sqSizeW, sqSizeH);
if (height > width) {
int p = getMaxHeightPercentage();
height = Math.min(getHeight(sqSize), height * p / 100);
} else {
width = Math.min(getWidth(sqSize), width * 65 / 100);
}
setMeasuredDimension(width, height);
}
Class ChessBoard methods:
protected int getWidth(int sqSize) {
return sqSize * 8;
}
protected int getHeight(int sqSize) {
return sqSize * 8;
}
private int getSquareSizeWidth(final int width) {
return (width)/ 8;
}
private int getSquareSizeHeight(final int height) {
return (height)/8;
}
private int getXCoord(final int x) {
return x0 + squareSize * (flipped ? 7 - x : x);
}
private int getYCoord(final int y) {
return y0 + squareSize * (flipped ? y : 7 - y);
}
private void computeOrigins(final int width, final int height) {
this.x0 = (width - squareSize *8)/2 ;
this.y0 = (height - squareSize *8)/2;
}
protected int getMaxHeightPercentage() {
return 75;
}
}
Kindly note that the onDraw method above is implemented in the Chess Board Class.
I am sure the solution for this problem lies in the onMeasure Method, I am thinking if I increase the height of each square then the chessboard will stretch horizontally and cover the whole screen ? Can anyone please tell me what I am doing wrong ?
Upvotes: 2
Views: 4931
Reputation: 1619
Well, not quite sure what you want to achieve by having a non-square chessboard which is not how usually it is represented. In any case, just looking at your code somehow following lines looks a bit suspicious:
squareSize=Math.min(getSquareSizeWidth(width),getSquareSizeHeight(height));
and
rect.right= rect.left+squareSize; // right
rect.bottom=rect.top + squareSize;
So, your tile rect always seems to be setting to same width and height, which is minimum of width and height as per these lines.
Upvotes: 0