I am new on Android. I am working on simple Sudoku solver and I have problem with my view. My SolverView contain on Custom View embedded into a layout that contains 2 buttons. When I click on a cell of sudoku grid, a keypad dialog appear that allow me to choose the number for that cell. However, after click on a number on keypad, my sudoku grid not display it immediately although the onDraw() method was called. Instead, it only update on the next time I touch screen. Following is the code
public class SolverView extends View{
private String TAG = "Solver View";
private int size;
private Solver solver;
private static int selU, selV;
public SolverView(Context context) {
super(context);
this.solver = (Solver) context;
setFocusable(true);
setFocusableInTouchMode(true);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
public SolverView(Context context, AttributeSet attrs) {
super(context, attrs);
this.solver = (Solver) context;
setFocusable(true);
setFocusableInTouchMode(true);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
public SolverView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.solver = (Solver) context;
setFocusable(true);
setFocusableInTouchMode(true);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
public int getBoardSize() {
int height = getHeight();
int width = getWidth();
return Math.min(height, width);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
size = getBoardSize();
int cellSize = size / 9;
Paint light = new Paint();
light.setColor(getResources().getColor(R.color.puzzle_light));
Paint dark = new Paint();
dark.setColor(getResources().getColor(R.color.puzzle_dark));
dark.setTypeface(Typeface.DEFAULT_BOLD);
for (int i = 0; i <= 9; i++) {
canvas.drawLine(i * cellSize, 0, i * cellSize, size, light);
if (i % 3 == 0)
canvas.drawLine(i * cellSize, 0, i * cellSize, size, dark);
}
for (int i = 0; i <= 9; i++) {
canvas.drawLine(0, i * cellSize, size, i * cellSize, light);
if (i % 3 == 0)
canvas.drawLine(0, i * cellSize, size, i * cellSize, dark);
}
Paint foreground = new Paint(Paint.ANTI_ALIAS_FLAG);
foreground.setColor(getResources().getColor(R.color.puzzle_dark));
foreground.setStyle(Style.FILL);
foreground.setTextSize(cellSize * 0.75f);
foreground.setTextAlign(Paint.Align.CENTER);
FontMetrics fm = foreground.getFontMetrics();
float x = cellSize / 2 - (fm.ascent + fm.descent) / 2;
float y = cellSize / 2 ;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
canvas.drawText(this.solver.getCellString(i, j), j * cellSize + y, i * cellSize + x, foreground);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() != MotionEvent.ACTION_DOWN)
return super.onTouchEvent(event);
int cellSize = size / 9;
int i = (int)event.getY() / cellSize;
int j = (int)event.getX() / cellSize;
if (i < 0 || i > 8 || j < 0 || j > 8)
return false;
this.selU = i;
this.selV = j;
Log.d(TAG, "onTouchEvent: " + selU + " , " + selV);
this.solver.showKeypad(i, j);
invalidate();
return true;
}
public void setCell(int t) {
Log.d(TAG, "in setCell: t = " + t);
Log.d(TAG, "in setCell: selU = " + selU);
Log.d(TAG, "in setCell: selV = " + selV);
if (solver.setCellIfValid(selU, selV, t)) {
Log.d(TAG, "setCell: going to invalidate()");
Log.d(TAG, "setCell: value change: " + solver.a[selU][selV]);
invalidate();
}
}
}
And this is the structure of layout:
<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:paddingBottom="@dimen/zero"
android:paddingLeft="@dimen/zero"
android:paddingRight="@dimen/zero"
android:paddingTop="@dimen/zero"
tools:context="com.trungkienioicamp.helloworld.Solver" >
<com.trungkienioicamp.helloworld.SolverView
android:id="@+id/board"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true" />
<Button
android:id="@+id/clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="74dp"
android:layout_marginLeft="29dp"
android:text="Clear" />
<Button
android:id="@+id/solve"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/clear"
android:layout_alignBottom="@+id/clear"
android:layout_alignParentRight="true"
android:layout_marginRight="61dp"
android:text="Solve" />
Can anyone suggest me the solution for this one? Thank for reading
UPDATED: The problem gone when I set the content view of main activity as solverView instance
setContentView(solverView);
But it will not work when I set the content view as a layout
setContentView(R.layout.activity_solver);
Try to call
invalidate
your instance ofSolverView
after click on a number on keypad.