Creating the Keypad

The keypad is handy for phones that don't have keyboards. It displays a grid of the numbers 1 through 9 in an activity that appears on top of the puzzle. The whole purpose of the keypad dialog box is to return a number selected by the player.

Here's the user interface layout from res/layout/keypad.xml:

Download Sudokuv2/res/layout/keypad.xml

<?xml version="1.0" encoding="utf-8"?>

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/keypad"

android:orientation= "vertical"

android:layout_width= "'wrap_content"

android:layout_height= "'wrap_content"

android:stretchColumns="*">

<TableRow>

<Button android:id="@+id/keypad_1"

<Button android:id="@+id/keypad_2"

<Button android:id="@+id/keypad_3"

android:text="3"> </Button> </TableRow> <TableRow>

<Button android:id="@+id/keypad_4"

<Button android:id="@+id/keypad_5"

<Button android:id="@+id/keypad_6"

android:text="6"> </Button> </TableRow> <TableRow>

<Button android:id="@+id/keypad_7"

<Button android:id="@+id/keypad_8"

<Button android:id="@+id/keypad_9"

android:text="9"> </Button> </TableRow>

</TableLayout>

Next let's define the Keypad class.

Here's the outline:

Download Sudokuv2/src/org/example/sudoku/Keypad.java

package org.example.sudoku;

import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.view.KeyEvent; import android.view.View;

public class Keypad extends Dialog {

protected static final String TAG = "Sudoku";

private final View keys[] = new View[9]; private View keypad;

private final int useds[]; private final PuzzleView puzzleView;

public Keypad(Context context, int useds[], PuzzleView puzzleView) { super(context); this.useds = useds; this.puzzleView = puzzleView;

@Override protected void onCreate(Bundle savedlnstanceState) { super.onCreate(savedlnstanceState);

setTitle(R.string.keypad_title); setContentView(R.layout.keypad); findViews();

keys[element - 1].setVisibility(View.INVISIBLE);

setListeners();

If a particular number is not valid (for example, the same number already appears in that row), then we make the number invisible in the grid so the player can't select it (see Figure 4.7, on the next page).

Figure 4.7: Invalid values are hidden in the keypad view.

The findViews() method fetches and saves the views for all the keypad keys and the main keypad window:

Download Sudokuv2/src/org/example/sudoku/Keypad.java

private void findViews() {

keypad = findViewByld(R.id.keypad); keys[0] = findViewById(R.id.keypad_1); keys[1] = findViewById(R.id.keypad_2); keys[2] = findViewById(R.id.keypad_3); keys[3] = findViewById(R.id.keypad_4); keys[4] = findViewById(R.id.keypad_5); keys[5] = findViewById(R.id.keypad_6); keys[6] = findViewById(R.id.keypad_7); keys[7] = findViewById(R.id.keypad_8); keys[8] = findViewById(R.id.keypad_9);

setListeners( ) loops through all the keypad keys and sets a listener for each one. It also sets a listener for the main keypad window.

Download Sudokuv2/src/org/example/sudoku/Keypad.java

private void setListeners() {

for (int i =0; i < keys.length; i++) { final int t = i +1;

keys[i].setOnClickListener(new View.OnClickListener(){ public void onClick(View v) {

keypad.setOnClickListener(new View.OnClickListener(){ public void onClick(View v) {

When the player selects one of the buttons on the keypad, it calls the returnResult() method with the number for that button. If the player selects a place that doesn't have a button, then returnResult() is called with a zero, indicating the tile should be erased.

onKeyDown() is called when the player uses the keyboard to enter a number:

Download Sudokuv2/src/org/example/sudoku/Keypad.java

@Override public boolean onKeyDown(int keyCode, KeyEvent event) { int tile = 0; switch (keyCode) {

case

KeyEvent

KEYCODE_

O

case

KeyEvent

KEYCODE_

_SPACE: tile =

O

break

case

KeyEvent

KEYCODE_

l

tile =

l

break

case

KeyEvent

KEYCODE_

2

tile =

2

break

case

KeyEvent

KEYCODE_

_3

tile =

3

break

case

KeyEvent

KEYCODE_

4

tile =

4

break

case

KeyEvent

KEYCODE_

_5

tile =

5

break

case

KeyEvent

KEYCODE_

_6

tile =

6

break

case

KeyEvent

KEYCODE_

_7

tile =

7

break

case

KeyEvent

KEYCODE_

B

tile =

B

break

case

KeyEvent

KEYCODE_

9

tile =

9

return super.onKeyDown(keyCode, event);

default:

return super.onKeyDown(keyCode, event);

if (isValid(tile)) { returnResult(tile);

return true;

If the number is valid for the current tile, then it calls returnResult(); otherwise, the keystroke is ignored.

The isValid() method checks to see whether the given number is valid for the current position:

Download Sudokuv2/src/org/example/sudoku/Keypad.java

private boolean isValid(int tile) { for (int t : useds) { if (tile == t) return false;

return true;

If it appears in the used array, then it's not valid because the same number is already used in the current row, column, or block.

The returnResult() method is called to return the number selected to the calling activity:

Download Sudokuv2/src/org/example/sudoku/Keypad.java

private void returnResult(int tile) { puzzleView.setSelectedTile(tile); dismiss();

We call the PuzzleView.setSelectedTile() method to change the puzzle's current tile. The dismiss call terminates the Keypad dialog box. Now that we have the activity, let's call it in the Game class and retrieve the result:

Download Sudokuv2/src/org/example/sudoku/Game.java

protected void showKeypadOrError(int x, int y) { int tiles[] = getUsedTiles(x, y); if (tiles.length == 9) {

Toast toast = Toast.makeText(this,

R.string.no_moves_label, Toast.LENGTH_SHORT); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); } else {

Log.d(TAG, "showKeypad: used=" + toPuzzleString(tiles)); Dialog v = new Keypad(this, tiles, puzzleView); v.show();

To decide which numbers are possible, we pass the Keypad a string in the extraData area containing all the numbers that have already been used.

0 0

Post a comment