我坚持在 android 的表面中添加放大和缩小功能,我的代码如下。我已经实现了 SurfaceView 和 SurfaceHoder.CallBack。我在 Xml 文件中使用这个自定义视图。并显示一个拼字游戏板,但我无法在游戏板中添加放大和缩小功能。
package com.scrabble.game.client.ui;
public class BoardView extends SurfaceView implements SurfaceHolder.Callback,
OnTouchListener {
private static int BOARD_SIZE = 15;
private static final float MIN_FONT_DIPS = 10.0f;
private static final int[] STACK_COLOR = { 0xFFFFFFFF, 0xFF2BC2AE,
0xFF2BC241, 0xFF9FA617, 0xFFC76B50 };
private Dimensions dimensions;
private DrawingThread thread;
class DrawingThread extends Thread implements OnTouchListener {
private static final int TRAY_AREA = 1;
private static final int BOARD_AREA = 2;
private static final int SCORE_AREA = 3;
// private static final String STACK_MESSAGE = "Tile Stack";
private boolean mRun;
private SurfaceHolder mSurfaceHolder;
private Dimensions dims;
private GameEngine ge;
private int defaultFontS;
private PopupWindow pw;
private int event;
private int eventX, eventY;
private int prevEventX, prevEventY;
private Handler mHandler;
private int selectedTileNum;
private int selectedBoardTileX, selectedBoardTileY;
private int movingTileX, movingTileY;
// private int topLeftX, topLeftY;
public DrawingThread(SurfaceHolder holder, Handler handler) {
mSurfaceHolder = holder;
mRun = false;
switchMode = false;
tileIsMoved = false;
boardTileIsMoved = false;
// stackOpen = false;
// openStack = new TileStack();
event = eventX = eventY = -1;
prevEventX = prevEventY = -1;
selectedTileNum = -1;
selectedBoardTileX = -1;
selectedBoardTileY = -1;
movingTileX = -1;
movingTileY = -1;
// topLeftX = -1;
// topLeftY = -1;
mHandler = handler;
dims = new Dimensions();
movingTile = new Tile();
defaultFontS = (int) BoardView.MIN_FONT_DIPS;
ge = null;
tilesTray = new Rect[1];
paintInitialisation();
setFocusable(true);
}
public void setRunning(boolean b) {
mRun = b;
}
@Override
public void run() {
while (mRun) {
Canvas c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
Rect bRect = new Rect(0, 0, dims.getTotalWidth(),
dims.getScoreHeight() + dims.getBoardheight());
// canvas.drawRect(bRect, fillBoardPaint);
Drawable drawableMain = getResources().getDrawable(
R.drawable.mainbg);
drawableMain.setBounds(bRect);
drawableMain.draw(c);
synchronized (mSurfaceHolder) {
updateGame();
doDraw(c);
}
} finally {
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
public void setSwitchMode(boolean b) {
synchronized (mSurfaceHolder) {
switchMode = b;
}
}
public void setGameEngine(GameEngine ge) {
synchronized (mSurfaceHolder) {
this.ge = ge;
}
}
public void setDimensions(Dimensions dimensions) {
synchronized (mSurfaceHolder) {
dims = dimensions;
}
}
public void setEventInfo(int evt, int x, int y) {
synchronized (mSurfaceHolder) {
event = evt;
eventX = x;
eventY = y;
}
}
public void setDefaultFontSize(int dfs) {
synchronized (mSurfaceHolder) {
defaultFontS = dfs;
}
}
public void setPopupWindow(PopupWindow popUp) {
synchronized (mSurfaceHolder) {
this.pw = popUp;
}
}
private void updateGame() {
if (ge == null)
return;
switch (event) {
case MotionEvent.ACTION_DOWN:
int area = getArea(eventX, eventY);
switch (area) {
case TRAY_AREA:
handleTrayClick(eventX, eventY);
if (switchMode && selectedTileNum != -1) {
switchMode = false;
pw.dismiss();
ge.makeSwitch(selectedTileNum);
selectedTileNum = -1;
}
break;
case BOARD_AREA:
handleBoardClick(eventX, eventY);
break;
case SCORE_AREA:
default:
break;
}
break;
case MotionEvent.ACTION_MOVE:
if (Math.abs(prevEventX - eventX) < dims.getCellSize() / 20)
return;
if (Math.abs(prevEventY - eventY) < dims.getCellSize() / 20)
return;
// stackOpen = false;
// openStack = null;
if (selectedTileNum != -1) {
int turn = ge.getPlayerTurn();
Tray t = ge.getPlayer(turn).getTray();
if (!tileIsMoved)
movingTile = t.temporaryRemoveTile(selectedTileNum);
tileIsMoved = true;
movingTileX = getMovingTileXPos(eventX);
movingTileY = getMovingTileYPos(eventY);
} else if (selectedBoardTileX != -1 && selectedBoardTileY != -1) {
Board b = ge.getBoard();
if (!tileIsMoved)
movingTile = b.removeTile(selectedBoardTileX,
selectedBoardTileY);
tileIsMoved = true;
boardTileIsMoved = true;
movingTileX = getMovingTileXPos(eventX);
movingTileY = getMovingTileYPos(eventY);
}
break;
case MotionEvent.ACTION_UP:
// stackOpen = false;
// openStack = null;
if (tileIsMoved) {
Board b = ge.getBoard();
int turn = ge.getPlayerTurn();
Tray t = ge.getPlayer(turn).getTray();
if (getArea(eventX, eventY) == BOARD_AREA) {
int i = findCellRow(eventY);
int j = findCellCol(eventX);
if (b.canAddTile(i, j, movingTile)) {
b.addTile(movingTile, i, j);
if (!boardTileIsMoved) {
t.addTempRemovedTile(movingTile,
selectedTileNum);
t.useTile(selectedTileNum);
}
SoundManager.playSound(2, 1, 0);
} else {
if (boardTileIsMoved) {
b.addTile(movingTile, selectedBoardTileX,
selectedBoardTileY);
} else {
t.addTempRemovedTile(movingTile,
selectedTileNum);
}
SoundManager.playSound(3, 1, 0);
}
} else if (getArea(eventX, eventY) == TRAY_AREA) {
if (boardTileIsMoved) {
t.addTile(movingTile);
SoundManager.playSound(3, 1, 0);
} else if (selectedTileNum != -1) {
t.addTempRemovedTile(movingTile, selectedTileNum);
SoundManager.playSound(3, 1, 0);
}
} else {
if (selectedTileNum != -1) {
t.addTempRemovedTile(movingTile, selectedTileNum);
SoundManager.playSound(3, 1, 0);
} else if (selectedBoardTileX != -1
&& selectedBoardTileY != -1) {
b.addTile(movingTile, selectedBoardTileX,
selectedBoardTileY);
SoundManager.playSound(3, 1, 0);
}
}
if (ge.getBoard().isValidPlacement()) {
Message msg = mHandler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putBoolean("clickable", true);
msg.setData(bundle);
mHandler.sendMessage(msg);
} else {
Message msg = mHandler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putBoolean("clickable", false);
msg.setData(bundle);
mHandler.sendMessage(msg);
}
undoMovingChanges();
} else {
undoMovingChanges();
}
break;
default:
break;
}
prevEventX = eventX;
prevEventY = eventY;
}
private void doDraw(Canvas canvas) {
if (ge == null)
return;
Rect bRect = new Rect(0, 0, dims.getTotalWidth(),
dims.getScoreHeight() + dims.getBoardheight());
Drawable drawable = getResources().getDrawable(R.drawable.board);
drawable.setBounds(bRect);
drawable.draw(canvas);
Rect tRect = new Rect(0, dims.getScoreHeight()
+ dims.getBoardheight(), dims.getTotalWidth(),
dims.getTotalHeight());
canvas.drawRect(tRect, fillTrayPaint);
int topHeight = dims.getScoreHeight() + dims.getBoardheight();
int bottom = (dims.getTotalHeight() + 5)
- (dims.getTotalWidth() / Tray.TRAY_SIZE);
Rect rect = new Rect(0, topHeight, dims.getTotalWidth(), bottom-7);
Drawable drawableTray = getResources().getDrawable(
R.drawable.mainbg);
drawableTray.setBounds(rect);
drawableTray.draw(canvas);
drawTray(canvas);
drawBoard(canvas);
// drawScore(canvas);
drawMovingTile(canvas);
}
Tile t;
private void drawMovingTile(Canvas canvas) {
if (tileIsMoved) {
tileTextPaint.setTextSize(defaultFontS * 2);
drawTile(canvas, movingTileX - 2 * dims.getCellSize(),
movingTileY - 2 * dims.getCellSize(), movingTileX + 2
* dims.getCellSize(),
movingTileY + 2 * dims.getCellSize(),
Character.toString(movingTile.getLetter()), 1);
}
}
// private void drawScore(Canvas canvas) {
// }
private void drawBoard(Canvas canvas) {
int bHeight = dims.getBoardheight();
int bWidth = bHeight;
int sHeight = dims.getScoreHeight();
int padding = dims.getPadding();
int left = dims.getPadding() + (BOARD_SIZE / 2)
* dims.getCellSize();
int top = dims.getScoreHeight() + (BOARD_SIZE / 2)
* dims.getCellSize();
int bottom = 1 * dims.getCellSize() + top;
int right = 1 * dims.getCellSize() + left;
if (ge == null)
return;
Board b = ge.getBoard();
TileStack[][] ts = b.getTilePlacement();
for (int i = 0; i < ts.length; i++) {
for (int j = 0; j < ts[i].length; j++) {
if (b.hasTile(i, j)) {
if (selectedBoardTileX == i && selectedBoardTileY == j)
tileFillPaint.setColor(Color.YELLOW);
else if (b.getTile(i, j).getAge() == b.getTurn())
tileFillPaint.setARGB(255, 160, 160, 200);
else
tileFillPaint
.setColor(BoardView.STACK_COLOR[ts[i][j]
.getNumTilesInStack() - 1]);
left = dims.getPadding() + j * dims.getCellSize();
right = left + dims.getCellSize();
top = dims.getScoreHeight() + i * dims.getCellSize();
bottom = top + dims.getCellSize();
tileTextPaint.setTextSize(2 * defaultFontS);
drawTile(canvas, left, top, right, bottom,
Character.toString(ts[i][j].getTop()
.getLetter()), 0);
tileFillPaint.setColor(Color.WHITE);
}
}
}
}
private void drawTray(Canvas canvas) {
// Draw the tray background
Rect tileFillRect;
tileFillRect = new Rect(0, (dims.getTotalHeight() - 8)
- (dims.getTotalWidth() / Tray.TRAY_SIZE),
dims.getTotalWidth(), dims.getTotalHeight());
Drawable drawableTray = getResources().getDrawable(
R.drawable.bg_footer_tray);
drawableTray.setBounds(tileFillRect);
drawableTray.draw(canvas);
// set text Size
tileTextPaint.setTextSize(2 * defaultFontS);
// fill the tray item
int turn = ge.getPlayerTurn();
Tray t = ge.getPlayer(turn).getTray();
int tileSize = dims.getTotalWidth() / (Tray.TRAY_SIZE - 1);
if (tileSize >= dims.getTrayHeight())
tileSize = (4 * dims.getTrayHeight() / 5) - 5;
int bot_border = 7;
int space = (dims.getTotalWidth() - (tileSize * Tray.TRAY_SIZE))
/ (Tray.TRAY_SIZE + 1);
int reps = t.getNumUnusedTiles();
tilesTray = new Rect[reps];
for (int i = 0; i < reps; i++) {
if (t.getTile(i) == null)
continue;
if (i == 0) {
tilesTray[i] = drawTile(canvas, i * tileSize + (i + 1)
* space - bot_border, dims.getTotalHeight()
- tileSize - 2 * bot_border, i * tileSize + (i + 1)
* space + tileSize + bot_border,
dims.getTotalHeight() - bot_border,
t.getTileLetter(i), 0);
} else if (i == 1) {
tilesTray[i] = drawTile(canvas, i * tileSize + (i + 1)
* space - bot_border, dims.getTotalHeight()
- tileSize - 2 * bot_border, i * tileSize + (i + 1)
* space + tileSize + bot_border,
dims.getTotalHeight() - bot_border,
t.getTileLetter(i), 0);
} else if (i == 2) {
tilesTray[i] = drawTile(canvas, i * tileSize + (i + 1)
* space - bot_border, dims.getTotalHeight()
- tileSize - 2 * bot_border, i * tileSize + (i + 1)
* space + tileSize + bot_border,
dims.getTotalHeight() - bot_border,
t.getTileLetter(i), 0);
} else if (i == 3) {
tilesTray[i] = drawTile(canvas, i * tileSize + (i + 1)
* space - bot_border, dims.getTotalHeight()
- tileSize - 2 * bot_border, i * tileSize + (i + 1)
* space + tileSize + bot_border,
dims.getTotalHeight() - bot_border,
t.getTileLetter(i), 0);
} else if (i == 4) {
tilesTray[i] = drawTile(canvas, i * tileSize + (i + 1)
* space - bot_border, dims.getTotalHeight()
- tileSize - 2 * bot_border, i * tileSize + (i + 1)
* space + tileSize + bot_border,
dims.getTotalHeight() - bot_border,
t.getTileLetter(i), 0);
} else if (i == 5) {
tilesTray[i] = drawTile(canvas, i * tileSize + (i + 1)
* space - bot_border, dims.getTotalHeight()
- tileSize - 2 * bot_border, i * tileSize + (i + 1)
* space + tileSize + bot_border,
dims.getTotalHeight() - bot_border,
t.getTileLetter(i), 0);
} else if (i == 6) {
tilesTray[i] = drawTile(canvas, i * tileSize + (i + 1)
* space - bot_border, dims.getTotalHeight()
- tileSize - 2 * bot_border, i * tileSize + (i + 1)
* space + tileSize + bot_border,
dims.getTotalHeight() - bot_border,
t.getTileLetter(i), 0);
} else {
tilesTray[i] = drawTile(canvas, i * tileSize + (i + 1)
* space, dims.getTotalHeight() - tileSize
- bot_border, i * tileSize + (i + 1) * space
+ tileSize, dims.getTotalHeight() - bot_border,
t.getTileLetter(i), 0);
}
t.getTileLetter(i));
tileFillPaint.setColor(Color.WHITE);
}
}
private Rect drawTile(Canvas canvas, int left, int top, int right,
int bottom, String text, int id) {
Rect tileRect;
tileRect = new Rect(left, top, right, bottom);
// by ashwani
Drawable drawableMain = getResources().getDrawable(
R.drawable.blankbtn);
drawableMain.setBounds(tileRect);
drawableMain.draw(canvas);
Paint p = new Paint();
Picture picture = new Picture();
picture.draw(canvas);
canvas.drawPicture(picture);
);
if (id == 0) {
canvas.drawText(text, left + (right - left) / 2, bottom
- (bottom - top) / 5, tileTextPaint);
} else {
int k = 9;
canvas.drawText(text, left + (right - left) / 2,
(bottom - (bottom - top) / 5) - 25, tileTextPaint);
int i = 0;
}
// canvas.drawText(text, left + (right - left) / 2, bottom
// - (bottom - top) / 5, tileTextPaint);
return tileRect;
}
private void undoMovingChanges() {
tileIsMoved = false;
boardTileIsMoved = false;
selectedTileNum = -1;
selectedBoardTileX = -1;
selectedBoardTileY = -1;
}
private int getMovingTileXPos(int x) {
if (x < dims.getCellSize() / 2)
return dims.getCellSize() / 2;
else if (x > dims.getTotalWidth() - dims.getCellSize() / 2)
return dims.getTotalWidth() - dims.getCellSize() / 2;
else
return x;
}
}
private void handleTrayClick(int x, int y) {
for (int i = 0; i < tilesTray.length; i++) {
try {
if (tilesTray[i].contains(x, y))
selectedTileNum = i;
} catch (NullPointerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void calculateStackCoords(int x, int y) {
}
@Override
public boolean onTouch(View v, MotionEvent event) {
System.out.println(" on touch event");
return false;
}
}
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
}
};
public BoardView(Context context, AttributeSet attrs) {
super(context, attrs);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
// endTurn=(ImageButton)findViewById(R.id.endturn_button_horizontal);
thread = new DrawingThread(holder, handler);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
final float scale1 = getResources().getDisplayMetrics().density;
defaultFontSize = (int) (MIN_FONT_DIPS * scale1 + 0.5f);
thread.setDefaultFontSize(defaultFontSize);
dimensions = calculateDimensions(getWidth(), getHeight());
thread.setDimensions(dimensions);
thread.setRunning(true);
thread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
thread.setRunning(false);
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println(" on touch event");
int evt = event.getAction();
int x = (int) event.getX();
int y = (int) event.getY();
thread.setEventInfo(evt, x, y);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}
public void setEndTurn(Button end) {
endTurn = end;
endTurn.setClickable(false);
}
public void setSwitchMode(boolean b) {
thread.setSwitchMode(b);
}
public Dimensions getDimensions() {
return dimensions;
}
public void setGameEngine(GameEngine ge) {
thread.setGameEngine(ge);
}
public void setPopupWindow(PopupWindow popUp) {
thread.setPopupWindow(popUp);
}
private Dimensions calculateDimensions(int width, int height) {
int cellSize, padding, top, bWidth, bHeight, scHeight, tHeight;
int maxCellSize;
Dimensions dims = new Dimensions();
dims.setTotalWidth(width);
dims.setTotalHeight(height);
cellSize = width / BOARD_SIZE;
maxCellSize = 3 * defaultFontSize;
if (maxCellSize < cellSize)
cellSize = maxCellSize;
bWidth = BOARD_SIZE * cellSize;
bHeight = bWidth;
padding = (width - bWidth) / 2;
scHeight = defaultFontSize * 2;
tHeight = cellSize * 4;
if (height >= bWidth + scHeight + tHeight) {
top = (height - bWidth - scHeight - tHeight) / 2;
} else {
top = 0;
tHeight = 4 * defaultFontSize;
if (height - bHeight - tHeight > tHeight) {
tHeight = height - bHeight - tHeight;
scHeight = height - bHeight - tHeight;
} else {
scHeight = height - bHeight - tHeight;
}
}
dims.setCellSize(cellSize);
dims.setBoardheight(bHeight);
dims.setPadding(padding);
dims.setScoreHeight(1);
dims.setTop(top);
dims.setTrayHeight(tHeight);
return dims;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return false;
}
}