如何防止自定义视图覆盖自身?

时间:2020-06-26 16:10:15

标签: java android android-layout view android-custom-view

我正在Android上开发Sudoku应用程序,但不能阻止我的自定义视图(sudoku面板)覆盖自身。我对应用程序开发非常陌生,所以我无法理解正在发生的事情。基本上,当我将棋盘传递给GameActivity时,其中的自定义视图会在较旧的棋盘上绘制新棋盘。这不应该发生。任何帮助都会得到应用。

这是我的自定义视图。

public class SudokuBoardView extends View {

    private static final String TAG = "SUDOKUVIEWGRID";

    //Paints
    private Paint thinPaint;
    private Paint thickPaint;
    private Paint selectedCellPaint;
    private Paint textPaint;

    //Values
    private static int width;
    private static int height;
    private static final int padding = 64;
    private static final int SIZE = 9;
    private static final int SQRT_SIZE = 3;
    private float cellSizePixels;

    //Model
    private SudokuModel sudokuModel = null;

    public SudokuBoardView(Context context) {
        super(context);
        init(null);
    }

    public SudokuBoardView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    public SudokuBoardView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    public SudokuBoardView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(attrs);
    }

    public void init(@Nullable AttributeSet attributeSet) {

        //Paint più sottile per celle
        thinPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        thinPaint.setStrokeWidth(2);
        thinPaint.setStyle(Paint.Style.STROKE);
        thinPaint.setColor(Color.BLACK);

        //Paint più spesso per contorni
        thickPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        thickPaint.setStrokeWidth(10);
        thickPaint.setStyle(Paint.Style.STROKE);
        thickPaint.setColor(Color.BLACK);

        //Paint per celle selezionate
        selectedCellPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        selectedCellPaint.setColor(Color.BLUE);
        selectedCellPaint.setStyle(Paint.Style.FILL_AND_STROKE);

        //Paint per numeri
        textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setTextSize(32);
        textPaint.setColor(Color.BLACK);

        //Dimensioni della griglia e delle celle
        width = getResources().getDisplayMetrics().widthPixels;  //Dim. assoluta dello schermo
        height = getResources().getDisplayMetrics().heightPixels;
        cellSizePixels = (float) ((width - 2*padding)/ SIZE);

    }

    public void setSudokuModel(SudokuModel model) {
        this.sudokuModel = model;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(widthMeasureSpec, widthMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //Outside Border
        canvas.drawRoundRect(padding,padding, width - padding, width - padding, 20, 20, thickPaint);
        //Cells
        drawLines(canvas);
        if (sudokuModel.isNewGame()) {
            drawInitialBoard(canvas, sudokuModel.getBoard());
        }
    }

    public void cleanCells() {
        invalidate();
    }

    protected void drawLines(Canvas canvas){
        //Linee Verticali
        for (int i = 0; i < SIZE; i++) {
            //Linea più spessa ogni 3 linee (la prima viene saltata perché c'è già il bordo)
            if (i == 0) continue;
            if (i % SQRT_SIZE == 0) {
                canvas.drawLine( i*cellSizePixels + padding, padding, i*cellSizePixels + padding, width - padding, thickPaint);
            } else {
                canvas.drawLine( i*cellSizePixels + padding, padding, i*cellSizePixels + padding, width - padding, thinPaint);
            }
        }

        //Linee Orizzontali
        for (int i = 0; i < SIZE; i++) {
            //Linea più spessa ogni 3 linee (la prima viene saltata perché c'è già il bordo)
            if (i == 0) continue;
            if (i % SQRT_SIZE == 0) {
                canvas.drawLine( padding, i*cellSizePixels + padding, width - padding, i*cellSizePixels + padding, thickPaint);
            } else {
                canvas.drawLine(padding, i * cellSizePixels + padding, width - padding, i * cellSizePixels + padding, thinPaint);
            }
        }
    }

    public void drawInitialBoard(Canvas canvas, Board board) {
        for (Cell cell: board.getCellList()) {
            int value = cell.getValue();
            String valueText = Integer.toString(value);
            int row = cell.getRow();
            int col = cell.getCol();

            Rect textBounds = new Rect();
            textPaint.getTextBounds(valueText, 0, valueText.length(), textBounds);
            float textWidth = textPaint.measureText(valueText);
            float textHeight = textBounds.height();

            canvas.drawText((value == 0 ? "" : valueText), (row * cellSizePixels + cellSizePixels/2 - textWidth/2 + padding), (col*cellSizePixels + cellSizePixels/2 + thickPaint.getStrokeWidth() + padding), textPaint);
        }
    }


}


这是视图所在的GameActivity。


public class GameActivity extends AppCompatActivity {

    //Controls Buttons
    Button[] buttons = new Button[10];
    private static final int[] BUTTON_IDS = {
            R.id.button1,
            R.id.button2,
            R.id.button3,
            R.id.button4,
            R.id.button5,
            R.id.button6,
            R.id.button7,
            R.id.button8,
            R.id.button9,
            R.id.buttonCancel
    };

    NumbersOnClickListener numbersOnClickListener;
    private Board board;
    private SudokuModel sudokuModel;
    private SudokuBoardView sudokuBoardView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_game);

        /*
        * NEW GAME
        *
        * Board Setup
        * */
        Intent gameIntent = getIntent();
        boolean isNewGame = gameIntent.getBooleanExtra("new game", false);
        if (isNewGame) {
            board = gameIntent.getParcelableExtra("Board");
            sudokuModel = new SudokuModel(board, isNewGame);
            sudokuModel.getBoard().printBoard();
            sudokuBoardView = findViewById(R.id.sudokuView);
            sudokuBoardView.setSudokuModel(sudokuModel);
        }

        //Controls Setup
        numbersOnClickListener = new NumbersOnClickListener();
        for (int i = 0; i < 10; i++) {
            buttons[i] = findViewById(BUTTON_IDS[i]);
            buttons[i].setOnClickListener(numbersOnClickListener);
            GridLayout.LayoutParams params = (GridLayout.LayoutParams) buttons[i].getLayoutParams();
            params.width = getResources().getDisplayMetrics().widthPixels / 7;
            params.height = params.width;
            buttons[i].setLayoutParams(params);
        }

    }

    @Override
    protected void onPause() {
        super.onPause();
    }

 }

SudokuModel类。

public class SudokuModel {

   private Board board;
   private boolean isNewGame;
   private int selectedRow = -1;
   private int selectedCol = -1;

   public SudokuModel(Board board, boolean isNewGame) {
       this.board = board;
       this.isNewGame = isNewGame;
   }

   public Board getBoard() {
       return board;
   }

   public void setBoard(Board board) {
       this.board = board;
   }

   public boolean isNewGame() {
       return isNewGame;
   }

   public int getSelectedRow() {
       return selectedRow;
   }

   public int getSelectedCol() {
       return selectedCol;
   }

   public void setSelectedRow(int selectedRow) {
       this.selectedRow = selectedRow;
   }

   public void setSelectedCol(int selectedCol) {
       this.selectedCol = selectedCol;
   }
}

董事会课程。

public class Board implements Parcelable {

   private static final int SIZE = 9;
   private ArrayList<Cell> cellList = new ArrayList<>();

   public Board(ArrayList<Cell> cellList) {
       this.cellList = cellList;
   }

   public ArrayList<Cell> getCellList() {
       return cellList;
   }

   public void setCellList(ArrayList<Cell> cellList) {
       this.cellList = cellList;
   }

   public void printBoard () {
       for (Cell cell: cellList) {
           System.out.println("Cell " + cell.getRow() + ":" + cell.getCol() + " VALUE: " + cell.getValue());
       }
   }

   protected Board(Parcel in) {
       if (in.readByte() == 0x01) {
           cellList = new ArrayList<Cell>();
           in.readList(cellList, Cell.class.getClassLoader());
       } else {
           cellList = null;
       }
   }

   @Override
   public int describeContents() {
       return 0;
   }

   @Override
   public void writeToParcel(Parcel dest, int flags) {
       if (cellList == null) {
           dest.writeByte((byte) (0x00));
       } else {
           dest.writeByte((byte) (0x01));
           dest.writeList(cellList);
       }
   }

   @SuppressWarnings("unused")
   public static final Parcelable.Creator<Board> CREATOR = new Parcelable.Creator<Board>() {
       @Override
       public Board createFromParcel(Parcel in) {
           return new Board(in);
       }

       @Override
       public Board[] newArray(int size) {
           return new Board[size];
       }
   };
}

Cell类。

public class Cell implements Parcelable {

   private int row;
   private int col;
   private int value;

   public Cell(int row, int col, int value) {
       this.row = row;
       this.col = col;
       this.value = value;
   }

   public int getRow() {
       return row;
   }

   public void setRow(int row) {
       this.row = row;
   }

   public int getCol() {
       return col;
   }

   public void setCol(int col) {
       this.col = col;
   }

   public int getValue() {
       return value;
   }

   public void setValue(int value) {
       this.value = value;
   }

   protected Cell(Parcel in) {
       row = in.readInt();
       col = in.readInt();
       value = in.readInt();
   }

   @Override
   public int describeContents() {
       return 0;
   }

   @Override
   public void writeToParcel(Parcel dest, int flags) {
       dest.writeInt(row);
       dest.writeInt(col);
       dest.writeInt(value);
   }

   @SuppressWarnings("unused")
   public static final Parcelable.Creator<Cell> CREATOR = new Parcelable.Creator<Cell>() {
       @Override
       public Cell createFromParcel(Parcel in) {
           return new Cell(in);
       }

       @Override
       public Cell[] newArray(int size) {
           return new Cell[size];
       }
   };
}

在此处生成棋盘并将其传递到游戏活动中。

public class SudokuGenerator implements Response.ErrorListener, Response.Listener<JSONObject> {

    private static final String TAG = "SUDOKU_GENERATOR";
    private String url = "https://sugoku.herokuapp.com/board?difficulty=";
    public int[][] puzzle = new int[9][9];
    ArrayList<Cell> generatedPuzzleCells = new ArrayList<>();
    private RequestQueue requestQueue;
    private Context context;
    LoadingDialog loadingDialog;
    NewGameErrorDialog newGameErrorDialog;

    public SudokuGenerator(Context context) {
        requestQueue = Volley.newRequestQueue(context);
        this.context = context;
        this.loadingDialog = new LoadingDialog((Activity) context);
        this.newGameErrorDialog = new NewGameErrorDialog((Activity) context);
    }

    public int[][] getPuzzle() {
        return puzzle;
    }

    public void setPuzzle(int[][] puzzle) {
        this.puzzle = puzzle;
    }

    public void setDifficulty(int difficulty) {
        switch (difficulty){
            case Globals.EASY:
                url = url.concat("easy");
                break;
            case Globals.MEDIUM:
                url = url.concat("medium");
                break;
            case Globals.HARD:
                url = url.concat("hard");
                break;
            default:
                url = url.concat("random");
                break;
        }
    }

    public void puzzleGenerator (int difficulty) {
        loadingDialog.startLoadingDialog();
        setDifficulty(difficulty);
        System.out.println("Set Difficulty");
        JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url,null,this, this);
        requestQueue.add(request);
        System.out.println("Made request");
        url = "https://sugoku.herokuapp.com/board?difficulty=";
    }

    @Override
    public void onErrorResponse(VolleyError error) {
        System.out.println("ERROR Response");
        newGameErrorDialog.startErrorDialog();
        loadingDialog.dismissDialog();
    }


    @Override
    public void onResponse(JSONObject response) {

        System.out.println("Response");
        //Check if not empty
        if (response.length() == 0){

        } //Error Handling

        try {
            JSONArray board = response.getJSONArray("board");
            System.out.println("Board " + board);
            for (int i = 0; i < board.length(); i++) {
                JSONArray box = board.getJSONArray(i);
                for (int j = 0; j < box.length(); j++) {
                    int k = box.getInt(j);
                    Cell cell;
                    if (k == 0) {
                        cell = new Cell(i, j, k, 0);
                    } else {
                        cell = new Cell(i, j, k, 1);
                    }
                    Log.d(TAG, "onResponse: GENERATED CELL: " + i +" "+j+" : "+k+" "+cell.isStartingCell());
                    generatedPuzzleCells.add(cell);
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        Board generatedBoard = new Board(generatedPuzzleCells);
        generatedBoard.printBoard();
        loadingDialog.dismissDialog();
        Intent gameIntent = new Intent(context, GameActivity.class);
        gameIntent.putExtra("Board", generatedBoard);
        gameIntent.putExtra("new game",true);
        context.startActivity(gameIntent);
    }
}

下面是两个截图,分别是新游戏第一次点击时发生的情况(应该是这样)以及返回主活动(新游戏按钮所在的位置)并再次按下该按钮之后发生的情况。

First Tap

After other taps

0 个答案:

没有答案