在学完了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. bzoj1231

    看到n<=16不难想到状压dp 我们用二进制表示前x个位置,哪些牛被已经被选过了 这里我们可以通过穷举二进制数的顺序来转移 所以二维就够了 ..] of longint;     f:.. sh ...

  2. C#语言的几个层次

    接到一位前不久C#培训学员的来信,这位学员虽然以前功底欠缺,但学习劲头很足,在培训中成长很快.即便基本吃透<.NET框架(修订版)>还嫌不够过瘾,一心要成为高手中的高手.来信的目的是希望我 ...

  3. Unity3D与iOS消息交互方法(1)--iOS接收Unity3D发出的消息

    跨平台这种事情不管多NB, 总要有些与原生系统交互的方法, 比如  Unity3D与iOS消息交互方法. 一: 建立一个空的Unity工程. File -->  New Project 二: 编 ...

  4. MOSS母板页制作 学习笔记(一)

    转:http://xiachanghao1990.blog.163.com/blog/static/4869602420114235536573/ 母版页制作其实应该算是一个比较基础的工作,但是熟练制 ...

  5. EXT 组件一些属性与方法(Tree)

    1.Ext.tree.TreePanel 主要配置项: root:树的根节点. rootVisible:是否显示根节点,默认为true. useArrows:是否在树中使用Vista样式箭头,默认为f ...

  6. Python Requests库

    背景 Requests is an elegant and simple HTTP library for Python, built for human beings. Requests是一个优雅简 ...

  7. hdoj 5461 Largest Point

    Largest Point Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tot ...

  8. javascript排序 查找算法大全

    在pptv的实习结束了, 忙着找工作的事,顺便把数据结构的那本书重新复习了一遍.为了加深印象,特意把里面的常用的排序.查找算法用js写了一遍 具体的实例在我的github上,大家可以访问的: http ...

  9. jQuery之事件even

    jQuery之事件       W3C:http://www.w3school.com.cn/jquery/jquery_ref_events.asp 一.事件列表 1.blur() 当失去焦点时触发 ...

  10. Excel中如何查找并列出所有链接(外部数据链接)?

    在 Excel 中,有时会需要创建外部链接来引用其他工作簿的单元格内容,但是如果想要找出所有链接并且还要将这些外部数据链接列在一个工作簿当中是有点难度的.下面我会介绍一些快捷方法,不仅能够快速帮你找出 ...