在学完了Android的基础之后,我开始尝试着写一些小项目练练手,同时进一步巩固自己的基础知识,而我选的的第一个项目就是做一个简单的人人对战的五子棋小游戏。

  首先,我们要新建一个自定义控件类Panel,这基本上涵盖着整个项目的大部分操作,比如棋盘的设计等等,下面开始Panel的编写,代码如下:

 public class Chess_Panel extends View{
private int myPanelWidth ; //棋盘宽度
private float myLineHeight; //行宽
private int maxLine = 10; //行数 private Paint myPaint; //画笔
private Bitmap myWhitePice; //白棋子
private Bitmap myBlackPice; //黑棋子
private float ratioPieceOfLineHight = 3 * 1.0f / 4; //棋子为行宽的3/4; private boolean isGemOver; //游戏结束
public static int WHITE_WIN = 0; //胜利为白方标志
public static int BLACK_WIN = 1; //胜利为黑方标志
private boolean isWhite = true; //判断是否是白棋先手,或当前为白棋下子 private List<Point> myWhiteArray = new ArrayList<Point>(); //白棋子位置信息
private List<Point> myBlackArray = new ArrayList<Point>(); //黑棋子位置信息 private onGameListener onGameListener; //回调接口
private int mUnder; //dialog的Y坐标 public Chess_Panel(Context context) {
this(context, null);
} public Chess_Panel(Context context ,AttributeSet attributeSet){ //构造函数
super(context , attributeSet); init();
} //初始化函数
private void init() {
myPaint = new Paint();
myPaint.setColor(0X44ff0000); //给画笔设置颜色
myPaint.setAntiAlias(true); //设置画笔是否使用抗锯齿
myPaint.setDither(true); //设置画笔是否防抖动
myPaint.setStyle(Paint.Style.STROKE); //设置画笔样式,这里使用描边 myWhitePice = BitmapFactory.decodeResource(getResources(),R.drawable.stone_w2); //设置棋子图片
myBlackPice = BitmapFactory.decodeResource(getResources(), R.drawable.stone_b1); }

  所谓自定义控件(或称组件)也就是编写自己的控件类型,而非Android中提供的标准的控件。构造函数中,使用AttributeSet来完成控件类的构造函数。

  Paint类:Android中的画笔类,用于绘制图形,它包含了很多方法对其属性进行设置,如下:

setAntiAlias: 设置画笔的锯齿效果。

setColor:
设置画笔颜色

setARGB: 
设置画笔的a,r,p,g值。

setAlpha: 
设置Alpha值

setTextSize:
设置字体尺寸。

setStyle: 
设置画笔风格,空心或者实心。

setStrokeWidth:
设置空心的边框宽度。

getColor: 
得到画笔的颜色

getAlpha: 
得到画笔的透明度。

  Bitmap指的是一张位图,而BitmapFactory是从文件,数据流,数组等的资源中生成一个Bitmap对象。                BitmapFactory.decodeResource(getResources(), R.drawable.stone_b1)正是从资源中获取一张图片生成一个Bitmap对象的方法。当然,还有其他的方法可以用来生成Bitmap对象,这里就不一一列举了。

  设置好画笔属性之后,我们就开始来设计我们的棋盘布局,以及棋盘的触摸动作等,代码如下:

     //触发动作
public boolean onTouchEvent(MotionEvent event){
if (isGemOver) {
return false;
} int action = event.getAction();
if (action == MotionEvent.ACTION_UP) { //判断触摸动作,ACTION_UP为单点触摸离开
int x = (int) event.getX();
int y = (int) event.getY();
Point p = getVaLidPiont(x,y);    //获取当前的坐标 if (myWhiteArray.contains(p)|| myBlackArray.contains(p)) {
return false;
} if (isWhite) {
myWhiteArray.add(p);
}else {
myBlackArray.add(p);
}
invalidate(); //invalidate()是用来刷新View的,必须在UI线程中使用
isWhite = !isWhite;
}
return true;
} private Point getVaLidPiont(int x , int y){
return new Point((int)(x/myLineHeight),(int)(y/myLineHeight));
} //计算布局大小
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec); int width = Math.min(widthSize, heightSize); if (widthMode == MeasureSpec.UNSPECIFIED) { //MeasureSpec.UNSPECIFIED表示未知大小
width = heightSize;
}else if (heightMode == MeasureSpec.UNSPECIFIED) {
width = widthSize;
} setMeasuredDimension(width, width); } protected void onSizeChanged(int w, int h ,int oldw , int oldh) { //当View大小发生改变的时候会被系统自动回调
super.onSizeChanged(w, h, oldw, oldh);
myPanelWidth = w;
myLineHeight = myPanelWidth*1.0f/maxLine;
mUnder = h - (h - myPanelWidth) / 2; int pieceWidth = (int) (myLineHeight*ratioPieceOfLineHight); //棋子大小占行宽的3/4
myWhitePice = Bitmap.createScaledBitmap(myWhitePice, pieceWidth, pieceWidth, false); //以src为原图,创建新的图像,指定新图像的高宽以及是否可变。
myBlackPice = Bitmap.createScaledBitmap(myBlackPice, pieceWidth, pieceWidth, false);
}

  要学好android触控,就要先了解MotionEvent,同时要对所用的MotionEvent常用的API要比较深入的了解。掌握MotionEvent事件是自定义控件中一个十分重要的部分。

  事件的主要动作类型有如下几种:

public static final int ACTION_DOWN             = 0;单点触摸动作

public static final int ACTION_UP               = 1;单点触摸离开动作
    public static final int ACTION_MOVE             = 2;触摸点移动动作
    public static final int ACTION_CANCEL           = 3;触摸动作取消
     public static final int ACTION_OUTSIDE          = 4;触摸动作超出边界
    public static final int ACTION_POINTER_DOWN     = 5;多点触摸动作
    public static final int ACTION_POINTER_UP       = 6;多点离开动作
   以下是一些非touch事件
    public static final int ACTION_HOVER_MOVE       = 7;
    public static final int ACTION_SCROLL           = 8;
    public static final int ACTION_HOVER_ENTER      = 9;
    public static final int ACTION_HOVER_EXIT       = 10;

  onMeasure()函数由包含这个View的具体的ViewGroup调用, onMeasure()当控件的父元素正要放置该控件时调用.onMesure向父元素中传入两个参数——widthMeasureSpec和heightMeasureSpec,这两个参数是由ViewGroup中的layout_width,layout_height和padding以及View自身的layout_margin共同决定,其中包含了Size和Mode信息。

  widthMeasureSpec和heightMeasureSpec的读取如下:

  int widthSize = MeasureSpec.getSize(widthMeasureSpec); 
  int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);     
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

  pecMode一共有三种可能:

  MeasureSpec.EXACTLY:父视图希望子视图的大小应该是specSize中指定的。

  MeasureSpec.AT_MOST:子视图的大小最多是specSize中指定的值,也就是说不建议子视图的大小超过specSize中给定的值。

  MeasureSpec.UNSPECIFIED:我们可以随意指定视图的大小。

  onSizeChanged(int w, int h ,int oldw , int oldh):当View大小发生改变(比如分辨率变化)的时候会被系统自动回调。

  Bitmap.createScaledBitmap(src,float, float, false) :以src为原图,创建新的图像,指定新图像的高宽以及是否可变。

接下来就开始设计棋盘线,代码如下:
     protected void  onDraw(Canvas canvas) {       //Canvas类相当于一块画布
super.onDraw(canvas);
drawBroad(canvas);
drawPiece(canvas);
checkGameOver();
} private void drawBroad(Canvas canvas){ //画出棋盘线
int w = myPanelWidth;
float lineHeight = myLineHeight;
int startX = (int) (lineHeight/2); //棋盘线起始X坐标
int endX = (int)(w-lineHeight/2); //棋盘终止X坐标
for(int i = 0; i< maxLine; i++){
int y = (int)((i+1.5)*lineHeight); //y坐标 canvas.drawLine(startX, y, endX, y, myPaint); //画棋盘横向线
canvas.drawLine(y, startX, y, endX, myPaint); //画棋盘纵向线
}
} //画棋子
private void drawPiece(Canvas canvas) {
int n1 = myWhiteArray.size();
int n2 = myBlackArray.size();
for(int i =0; i< n1 ;i++){
Point whitePoint = myWhiteArray.get(i);
canvas.drawBitmap(myWhitePice, (whitePoint.x+(1-ratioPieceOfLineHight)/2)*myLineHeight,
(whitePoint.y+(1-ratioPieceOfLineHight)/2)*myLineHeight, null);
//drawBitmap(Bitmap bitmap, float left, float top, Paint paint);Bitmap:图片对象,left:偏移左边的位置,top: 偏移顶部的位置
} for(int i =0; i< n2 ;i++){
Point blackPoint = myBlackArray.get(i);
canvas.drawBitmap(myBlackPice, (blackPoint.x+(1-ratioPieceOfLineHight)/2)*myLineHeight,
(blackPoint.y+(1-ratioPieceOfLineHight)/2)*myLineHeight, null);
}
}

  在Android中,Canvas类相当于画布,另外它也是显示位图(Bitmap类)的核心类,它的属性方法如下:

  Canvas(): 创建一个空的画布,可以使用setBitmap()方法来设置绘制具体的画布。
    Canvas(Bitmap bitmap): 以bitmap对象创建一个画布,则将内容都绘制在bitmap上,因此bitmap不得为null。
    Canvas(GL gl): 在绘制3D效果时使用,与OpenGL相关。
    drawColor: 设置Canvas的背景颜色。
    setBitmap:  设置具体画布。
    clipRect: 设置显示区域,即设置裁剪区。
                                     isOpaque:检测是否支持透明。                                         rotate:  旋转画布                                                 translate:移动画布                                             scale:缩放画布
    setViewport:  设置画布中显示窗口。
    skew:  设置偏移量。                                             restore: 用来恢复上一次save之前的状态                                    save:用来保存Canvas的当前状态

 注意: save方法、restore方法一般是成对出现的,save方法可多于restore方法,但restore方法不能多于save方法

  drawBitmap(Bitmap bitmap, float left, float top, Paint paint) Bitmap:图片对象,left:偏移左边的位置,top: 偏移顶部的位置,panit为我们设计的画笔

 接下来的就是游戏中的一些判断动作了:
     //检测游戏是否结束
private void checkGameOver(){
boolean whiteWin = checkFiveInLine(myWhiteArray);
boolean blackWin = checkFiveInLine(myBlackArray); if (whiteWin || blackWin) {
isGemOver = true;
if (onGameListener != null) {
onGameListener.onGameOver(whiteWin ? WHITE_WIN : BLACK_WIN);
}
}
}
//回调一个int数据用于设置Dialog的位置
public int getUnder() { return mUnder;
} //检测是否存在五棋子相连的情况
private boolean checkFiveInLine(List<Point> myArray){
for(Point p : myArray){
int x = p.x;
int y = p.y; boolean win_flag = //判断是否存在五子相连情况
checkHorizontal(x , y ,myArray)||checkVertical(x,y,myArray)
||checkLeftDiagonal(x,y,myArray)||checkRightDiagonal(x,y,myArray);
if (win_flag) {
return true;
}
}
return false;
} //横向检查是否满足五子相连
private boolean checkHorizontal(int x ,int y ,List<Point> myArray){
int count = 1;
for(int i = 1;i < 5; i++){
if (myArray.contains(new Point(x+i,y))) {
count++;
}else {
break;
}
}
if (count == 5) {
return true;
}
for(int i = 1;i < 5; i++){
if (myArray.contains(new Point(x-i,y))) {
count++;
}else {
break;
} if (count == 5) {
return true;
}
}
return false;
} //纵向检查是否满足五子相连
private boolean checkVertical(int x ,int y ,List<Point> myArray){
int count = 1;
for(int i = 1;i < 5; i++){
if (myArray.contains(new Point(x,y+i))) {
count++;
}else {
break;
} }
if (count == 5) {
return true;
}
for(int i = 1;i < 5; i++){
if (myArray.contains(new Point(x,y-i))) {
count++;
}else {
break;
}
if (count == 5) {
return true;
}
}
return false;
} //左斜向检查是否满足五子相连
private boolean checkLeftDiagonal(int x ,int y ,List<Point> myArray){
int count = 1;
for(int i = 1;i < 5; i++){
if (myArray.contains(new Point(x-i,y+i))) {
count++;
}else {
break;
} }
if (count == 5) {
return true;
}
for(int i = 1;i < 5; i++){
if (myArray.contains(new Point(x+i,y-i))) {
count++;
}else {
break;
}
if (count == 5) {
return true;
}
}
return false;
} //右斜向检查是否满足五子相连
private boolean checkRightDiagonal(int x ,int y ,List<Point> myArray){
int count = 1;
for(int i = 1;i < 5; i++){ //切记,i = 1 开始,否则就会只检测到三个子相连就结束了
if (myArray.contains(new Point(x-i,y-i))) {
count++;
}else {
break;
}
}
if (count == 5) {
return true;
}
for(int i = 1;i < 5; i++){
if (myArray.contains(new Point(x+i,y+i))) {
count++;
}else {
break;
}
if (count == 5) {
return true;
}
}
return false;
} //重新开始游戏
protected void restartGame(){
myWhiteArray.clear();
myBlackArray.clear();
isGemOver = false;
isWhite = false;
invalidate();  //刷新
}

  invalidate()是android中用于刷新View显示的一个方法。

  可以说重载onMeasure(),onLayout(),onDraw()三个函数构建了自定义View的外观形象。再加上onTouchEvent()等重载视图的行为,可以构建任何我们需要的可感知到的自定义View。

  另外,我们还应该暴露我们自定义的控件的接口,以方便调用:
     // 用于回调的接口
public interface onGameListener {
void onGameOver(int i);
} //自定义接口,用于显示dialog
public void setOnGameListener(Chess_Panel.onGameListener onGameListener) {
this.onGameListener = onGameListener;
}

   那么,完整的Chess_Panel代码如下所示:

 package com.example.fivechess;

 import java.util.ArrayList;
import java.util.List; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View; public class Chess_Panel extends View{
private int myPanelWidth ; //棋盘宽度
private float myLineHeight; //行宽
private int maxLine = 10; //行数 private Paint myPaint; //画笔
private Bitmap myWhitePice; //白棋子
private Bitmap myBlackPice; //黑棋子
private float ratioPieceOfLineHight = 3 * 1.0f / 4; //棋子为行宽的3/4; private boolean isGemOver; //游戏结束
public static int WHITE_WIN = 0; //胜利为白方标志
public static int BLACK_WIN = 1; //胜利为黑方标志
private boolean isWhite = true; //判断是否是白棋先手,或当前为白棋下子 private List<Point> myWhiteArray = new ArrayList<Point>(); //白棋子位置信息
private List<Point> myBlackArray = new ArrayList<Point>(); //黑棋子位置信息 private onGameListener onGameListener; //回调接口
private int mUnder; //dialog的Y坐标 public Chess_Panel(Context context) {
this(context, null);
} public Chess_Panel(Context context ,AttributeSet attributeSet){ //构造函数
super(context , attributeSet); init();
} // 用于回调的接口
public interface onGameListener {
void onGameOver(int i);
} //自定义接口,用于显示dialog
public void setOnGameListener(Chess_Panel.onGameListener onGameListener) {
this.onGameListener = onGameListener;
} //初始化函数
private void init() {
myPaint = new Paint();
myPaint.setColor(0X44ff0000); //给画笔设置颜色
myPaint.setAntiAlias(true); //设置画笔是否使用抗锯齿
myPaint.setDither(true); //设置画笔是否防抖动
myPaint.setStyle(Paint.Style.STROKE); //设置画笔样式,这里使用描边 myWhitePice = BitmapFactory.decodeResource(getResources(),R.drawable.stone_w2); //设置棋子图片
myBlackPice = BitmapFactory.decodeResource(getResources(), R.drawable.stone_b1); } //触发事件
public boolean onTouchEvent(MotionEvent event){
if (isGemOver) {
return false;
} int action = event.getAction();
if (action == MotionEvent.ACTION_UP) { //判断触摸动作,ACTION_UP为单点触摸离开
int x = (int) event.getX();
int y = (int) event.getY();
Point p = getVaLidPiont(x,y); if (myWhiteArray.contains(p)|| myBlackArray.contains(p)) {
return false;
} if (isWhite) {
myWhiteArray.add(p);
}else {
myBlackArray.add(p);
}
invalidate(); //invalidate()是用来刷新View的,必须在UI线程中使用
isWhite = !isWhite;
}
return true;
} private Point getVaLidPiont(int x , int y){
return new Point((int)(x/myLineHeight),(int)(y/myLineHeight));
} //计算布局大小
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec); int width = Math.min(widthSize, heightSize); if (widthMode == MeasureSpec.UNSPECIFIED) { //MeasureSpec.UNSPECIFIED表示未知大小
width = heightSize;
}else if (heightMode == MeasureSpec.UNSPECIFIED) {
width = widthSize;
} setMeasuredDimension(width, width); } protected void onSizeChanged(int w, int h ,int oldw , int oldh) { //当View大小发生改变的时候会被系统自动回调
super.onSizeChanged(w, h, oldw, oldh);
myPanelWidth = w;
myLineHeight = myPanelWidth*1.0f/maxLine;
mUnder = h - (h - myPanelWidth) / 2; int pieceWidth = (int) (myLineHeight*ratioPieceOfLineHight); //棋子大小占行宽的3/4
myWhitePice = Bitmap.createScaledBitmap(myWhitePice, pieceWidth, pieceWidth, false); //以src为原图,创建新的图像,指定新图像的高宽以及是否可变。
myBlackPice = Bitmap.createScaledBitmap(myBlackPice, pieceWidth, pieceWidth, false);
} protected void onDraw(Canvas canvas) { //Canvas类相当于一块画布
super.onDraw(canvas);
drawBroad(canvas);
drawPiece(canvas);
checkGameOver();
} private void drawBroad(Canvas canvas){ //画出棋盘线
int w = myPanelWidth;
float lineHeight = myLineHeight;
int startX = (int) (lineHeight/2); //棋盘线起始X坐标
int endX = (int)(w-lineHeight/2); //棋盘终止X坐标
for(int i = 0; i< maxLine; i++){
int y = (int)((i+1.5)*lineHeight); //y坐标 canvas.drawLine(startX, y, endX, y, myPaint); //画棋盘横向线
canvas.drawLine(y, startX, y, endX, myPaint); //画棋盘纵向线
}
} //画棋子
private void drawPiece(Canvas canvas) {
int n1 = myWhiteArray.size();
int n2 = myBlackArray.size();
for(int i =0; i< n1 ;i++){
Point whitePoint = myWhiteArray.get(i);
canvas.drawBitmap(myWhitePice, (whitePoint.x+(1-ratioPieceOfLineHight)/2)*myLineHeight,
(whitePoint.y+(1-ratioPieceOfLineHight)/2)*myLineHeight, null);
//drawBitmap(Bitmap bitmap, float left, float top, Paint paint);Bitmap:图片对象,left:偏移左边的位置,top: 偏移顶部的位置
} for(int i =0; i< n2 ;i++){
Point blackPoint = myBlackArray.get(i);
canvas.drawBitmap(myBlackPice, (blackPoint.x+(1-ratioPieceOfLineHight)/2)*myLineHeight,
(blackPoint.y+(1-ratioPieceOfLineHight)/2)*myLineHeight, null);
}
} //检测游戏是否结束
private void checkGameOver(){
boolean whiteWin = checkFiveInLine(myWhiteArray);
boolean blackWin = checkFiveInLine(myBlackArray); if (whiteWin || blackWin) {
isGemOver = true;
if (onGameListener != null) {
onGameListener.onGameOver(whiteWin ? WHITE_WIN : BLACK_WIN);
}
}
}
//回调一个int数据用于设置Dialog的位置
public int getUnder() { return mUnder;
} //检测是否存在五棋子相连的情况
private boolean checkFiveInLine(List<Point> myArray){
for(Point p : myArray){
int x = p.x;
int y = p.y; boolean win_flag = //判断是否存在五子相连情况
checkHorizontal(x , y ,myArray)||checkVertical(x,y,myArray)
||checkLeftDiagonal(x,y,myArray)||checkRightDiagonal(x,y,myArray);
if (win_flag) {
return true;
}
}
return false;
} //横向检查是否满足五子相连
private boolean checkHorizontal(int x ,int y ,List<Point> myArray){
int count = 1;
for(int i = 1;i < 5; i++){
if (myArray.contains(new Point(x+i,y))) {
count++;
}else {
break;
}
}
if (count == 5) {
return true;
}
for(int i = 1;i < 5; i++){
if (myArray.contains(new Point(x-i,y))) {
count++;
}else {
break;
} if (count == 5) {
return true;
}
}
return false;
} //纵向检查是否满足五子相连
private boolean checkVertical(int x ,int y ,List<Point> myArray){
int count = 1;
for(int i = 1;i < 5; i++){
if (myArray.contains(new Point(x,y+i))) {
count++;
}else {
break;
} }
if (count == 5) {
return true;
}
for(int i = 1;i < 5; i++){
if (myArray.contains(new Point(x,y-i))) {
count++;
}else {
break;
}
if (count == 5) {
return true;
}
}
return false;
} //左斜向检查是否满足五子相连
private boolean checkLeftDiagonal(int x ,int y ,List<Point> myArray){
int count = 1;
for(int i = 1;i < 5; i++){
if (myArray.contains(new Point(x-i,y+i))) {
count++;
}else {
break;
} }
if (count == 5) {
return true;
}
for(int i = 1;i < 5; i++){
if (myArray.contains(new Point(x+i,y-i))) {
count++;
}else {
break;
}
if (count == 5) {
return true;
}
}
return false;
} //右斜向检查是否满足五子相连
private boolean checkRightDiagonal(int x ,int y ,List<Point> myArray){
int count = 1;
for(int i = 1;i < 5; i++){ //切记,i = 1 开始,否则就会只检测到三个子相连就结束了
if (myArray.contains(new Point(x-i,y-i))) {
count++;
}else {
break;
}
}
if (count == 5) {
return true;
}
for(int i = 1;i < 5; i++){
if (myArray.contains(new Point(x+i,y+i))) {
count++;
}else {
break;
}
if (count == 5) {
return true;
}
}
return false;
} //重新开始游戏
protected void restartGame(){
myWhiteArray.clear();
myBlackArray.clear();
isGemOver = false;
isWhite = false;
invalidate();
}
}

终于,完成我们的自定义控件设计之后,我们就进入Activity的编写吧,代码如下:

 public class MainActivity extends Activity {

     private Chess_Panel panel;
private AlertDialog.Builder builder; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
panel = (Chess_Panel)findViewById(R.id.main_panel);
builder= new AlertDialog.Builder(MainActivity.this);
builder.setTitle("游戏结束");
builder.setNegativeButton("退出", new OnClickListener() { @Override
public void onClick(DialogInterface dialogInterface, int which) {
MainActivity.this.finish();
}
});
builder.setPositiveButton("再来一局", new OnClickListener() { @Override
public void onClick(DialogInterface interface1, int which) { panel.restartGame();
}
});
panel.setOnGameListener(new Chess_Panel.onGameListener() { @Override
public void onGameOver(int i) {
String str = "";
if (i== Chess_Panel.WHITE_WIN) {
str = "白方胜利!";
}else if (i== Chess_Panel.BLACK_WIN) {
str = "黑方胜利!";
}
builder.setMessage(str);
builder.setCancelable(false);    //不可用返回键取消
AlertDialog dialog = builder.create();
Window dialogWindow = dialog.getWindow();
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.x = 0;
params.y = panel.getUnder();
dialogWindow.setAttributes(params);    //设置Dialog显示的位置
dialog.setCanceledOnTouchOutside(false);  //不可点击取消
dialog.show();
}
} ); }
}
    这两句的作用是让游戏满屏显示,即不显示通知状态栏:  
   Window window = getWindow();
  window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
  另外注意,不要忘记在activity_main.xml中添加我们自定义的控件,代码如下:
 <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:background="@drawable/bg"
tools:context="com.example.fivechess.MainActivity" > <com.example.fivechess.Chess_Panel
android:id="@+id/main_panel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" /> </RelativeLayout>

   至此,我们的项目就完成了,接下来解释下载安装到手机上运行了,其效果如下:

Android学习之旅:五子棋的更多相关文章

  1. 我的Android学习之旅(转)

    去年大概在七月份的时候误打误撞接触了一阵子Android,之后由于工作时间比较忙,无暇顾及,九月份的时候自己空闲的时间比较多,公司相对来说加班情况没以前严重.开启了个人的Android学习之旅,初衷是 ...

  2. Android学习之旅(一)

    2017-02-27 今天开始,正式开启Android学习之旅,背景从事.Net平台开发快五年了,一直在用C#做Web开发. 前天选购了两本书:<Java 编程思想(第四版)>和<第 ...

  3. 衡量android开发者水平的面试问题-android学习之旅(91)

    一般面试时间短则30分钟,多则1个小时,这么点时间要全面考察一个人难度很大,需要一些技巧,这里我不局限于回答题主的问题,而是分享一下我个人关于如何做好Android技术面试的一些经验: 面试前的准备 ...

  4. My Android 学习之旅--开始

    其实,很早就想写写博客了,一直懒到现在. 学习android也不是今天才开始的,大概在2月份过完年之后就开始了,买了我认为还可以的书<Android从入门到精通>,花了不到一个月的时间,把 ...

  5. 【Android学习之旅】1、Android入门介绍

    1.Android介绍 1.1 Android的系统架构 下面这张图展示了Android的系统架构: 图中可见,Android大致可以分为四层架构,五块区域: Linux内核层(Linux Kerne ...

  6. Android的Toast介绍-android学习之旅(三十六)

    Toast简单介绍 Toast是一个很方便的消息提示框.会在桌面显示一个短暂的消息提示.有两个特点: 1.消息不会获得焦点. 2.过一段时间会自己主动消失. Toast的生成步骤 1.调用构造器或者静 ...

  7. Android的Bitmap和BitmapDrawable类解析-android学习之旅(六十)

    使用简单图片 使用Drawable对象 bitmap和BitmapDrawable对象 package peng.liu.test; import android.app.Activity; impo ...

  8. Intent启动系统组件(activity,service,BroadReceiver)-android学习之旅(四十九)

    android提供了统一的编程模型Intent来启动系统的组件,这样提供了松耦合性.是一种mvc的编程模式 $(function () { $('pre.prettyprint code').each ...

  9. Android触摸屏幕时间-android学习之旅(三)

    android的多点触摸是经常遇到的编程技巧,这一篇可以将详细的介绍这个问题. 简单实例 android的触摸需要实现OnTouchListener接口,继承里面方法. 布局代码: <?xml ...

随机推荐

  1. Python爬虫处理抓取数据中文乱码问题

    乱码原因:因为你的文件声明为utf-8,并且也应该是用utf-8的编码保存的源文件.但是windows的本地默认编码是cp936,也就是gbk编码,所以在控制台直接打印utf-8的字符串当然是乱码了. ...

  2. poj3415

    很久以前写的,忘补结题报告了两串相连中间用特殊的分隔符然后求height,由于要求求公共子串大于等于k的个数,并且只要位置不同即可因此不难想到在名次上对height分组,一组内的height保证> ...

  3. 推荐一个Xcode插件: KSImageNamed (自动补全图片文件名称, 并显示图片大小)

    http://www.csdn.net/article/2014-05-04/2819586-the-best-xcode-plugins 5. KSImageNamed KSImageNamed是一 ...

  4. 豆约翰博客备份专家博客导出示例(PDF,CHM)

    示例1: CSDN博客: 示例博客主页:http://blog.csdn.net/shenyisyn/ CHM文件图示:下载地址 PDF文件图示:下载地址 示例2: 新浪博客: 示例博客主页:http ...

  5. java常用重构优化总结--自己亲身体验

    代码重构  6大原则:    单一职责原则(一个类最好最好只有一种行为动机,太多承担职责会导致耦合度太高).    开放封闭原则(功能可以扩展,但是不可以内部修改).    依赖倒转原则(应该依赖抽象 ...

  6. 作品第二课----点击DIV显示其内容

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. js 打印网页指定内容

    function doPrint() { setTimeout(function() { bdhtml=window.document.body.innerHTML; sprnstr="&l ...

  8. 删除顺序链表中重复的数 (一) leecode

    Given a sorted linked list, delete all duplicates such that each element appear only once. For examp ...

  9. vijosP1388 二叉树数

    vijosP1388 二叉树数 链接:https://vijos.org/p/1388 [思路] Catalan数.根据公式h=C(2n,n)/(n+1)计算.首先化简为 (n+i)/i的积(1< ...

  10. 大文件遍历shell脚本

    要求说明: 一.普通方法 无读写磁盘优化 有写磁盘优化 有读写磁盘优化 问题:脚本执行越来越慢 top ps aux vmstat 查看系统运行情况正常. 二.AWK 三.perl