Я хотел бы динамически нарисовать шахматную доску 8 на 8 в студии Android с помощью холст и путем переопределения метода onDraw, мне почти удалось, но я столкнулся с очень неприятной проблемой.
Я уже создал настраиваемый вид, моя цель - сделать так, чтобы родительский макет соответствовал размеру его дочернего настраиваемого представления, чтобы моя шахматная доска могла покрывать весь экран. (в XML-файле для родительского и дочернего элементов установлено значение match_parent)
Я хочу, чтобы шахматная доска также занимала всю высоту экрана.
Проверьте картинку ниже вот результат, который я получаю, обратите внимание на огромный разрыв в нижней части, моя цель - растянуть шахматную доску по вертикали и заставить ее покрыть весь экран, чтобы устранить это пространство.
Вот что мне удалось написать, но это не то, что я хочу: Класс 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 метод:
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);
}
}
Плитка класса:
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:
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);
}
Методы класса ChessBoard:
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;
}
}
Обратите внимание, что приведенный выше метод onDraw реализован в классе Chess Board.
Я уверен, что решение этой проблемы заключается в методе onMeasure. Я думаю, что если я увеличу высоту каждого квадрата, шахматная доска растянется по горизонтали и покроет весь экран? Кто-нибудь может сказать мне, что я делаю не так?




Ну, я не совсем уверен, чего вы хотите достичь, имея неквадратную шахматную доску, а это не так, как обычно. В любом случае, даже если просто взглянуть на свой код, следующие строки выглядят немного подозрительно:
squareSize=Math.min(getSquareSizeWidth(width),getSquareSizeHeight(height));
а также
rect.right= rect.left+squareSize; // right
rect.bottom=rect.top + squareSize;
Таким образом, прямоугольник вашей плитки всегда имеет одинаковую ширину и высоту, что составляет минимум ширины и высоты в соответствии с этими строками.
Ваша проблема по-прежнему связана со строкой, о которой я упоминал выше. Вместо Math.min вы должны использовать Math.max для закрытия экрана. Просто вы можете добавить это в представление прокрутки, чтобы иметь более разумный пользовательский интерфейс.
Кстати, код, который вы написали, очень похож на код Droid Fish (автор Perter Osterlund). Если вы действительно изменили этот код, убедитесь, что, по крайней мере, указали оригинального автора.
Я просто использую код для практики и для лучшего понимания динамических пользовательских представлений, но спасибо за напоминание.
Нет, мне не нужна неквадратная шахматная доска. Как видите, у меня нет проблем динамически рисовать шахматную доску в обычном виде. Проблема в том, что шахматная доска не закрывает весь экран. Пожалуйста, проверьте картинку, которую я опубликовал. Вы видите белое пространство под шахматной доской? У меня вопрос: как сделать клетки достаточно большими, чтобы шахматная доска покрывала весь экран?