Рисование шахматной доски с динамическим пользовательским представлением в Android

Я хотел бы динамически нарисовать шахматную доску 8 на 8 в студии Android с помощью холст и путем переопределения метода onDraw, мне почти удалось, но я столкнулся с очень неприятной проблемой.

Я уже создал настраиваемый вид, моя цель - сделать так, чтобы родительский макет соответствовал размеру его дочернего настраиваемого представления, чтобы моя шахматная доска могла покрывать весь экран. (в XML-файле для родительского и дочернего элементов установлено значение match_parent)

Я хочу, чтобы шахматная доска также занимала всю высоту экрана.

Проверьте картинку ниже вот результат, который я получаю, обратите внимание на огромный разрыв в нижней части, моя цель - растянуть шахматную доску по вертикали и заставить ее покрыть весь экран, чтобы устранить это пространство.

Рисование шахматной доски с динамическим пользовательским представлением в Android

Вот что мне удалось написать, но это не то, что я хочу: Класс 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. Я думаю, что если я увеличу высоту каждого квадрата, шахматная доска растянется по горизонтали и покроет весь экран? Кто-нибудь может сказать мне, что я делаю не так?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
2 473
1

Ответы 1

Ну, я не совсем уверен, чего вы хотите достичь, имея неквадратную шахматную доску, а это не так, как обычно. В любом случае, даже если просто взглянуть на свой код, следующие строки выглядят немного подозрительно:

squareSize=Math.min(getSquareSizeWidth(width),getSquareSizeHeight(height));

а также

rect.right= rect.left+squareSize;  // right
rect.bottom=rect.top + squareSize;

Таким образом, прямоугольник вашей плитки всегда имеет одинаковую ширину и высоту, что составляет минимум ширины и высоты в соответствии с этими строками.

Нет, мне не нужна неквадратная шахматная доска. Как видите, у меня нет проблем динамически рисовать шахматную доску в обычном виде. Проблема в том, что шахматная доска не закрывает весь экран. Пожалуйста, проверьте картинку, которую я опубликовал. Вы видите белое пространство под шахматной доской? У меня вопрос: как сделать клетки достаточно большими, чтобы шахматная доска покрывала весь экран?

Coder992 26.10.2019 15:21

Ваша проблема по-прежнему связана со строкой, о которой я упоминал выше. Вместо Math.min вы должны использовать Math.max для закрытия экрана. Просто вы можете добавить это в представление прокрутки, чтобы иметь более разумный пользовательский интерфейс.

Knight Forked 03.11.2019 11:31

Кстати, код, который вы написали, очень похож на код Droid Fish (автор Perter Osterlund). Если вы действительно изменили этот код, убедитесь, что, по крайней мере, указали оригинального автора.

Knight Forked 03.11.2019 11:45

Я просто использую код для практики и для лучшего понимания динамических пользовательских представлений, но спасибо за напоминание.

Coder992 16.03.2020 17:52

Другие вопросы по теме