最近在看Android群英传,跟着书里面写了个拼图小游戏。现在讲其记录下来。
首先看一下效果图
主要由两个界面组成,主界面和拼图界面
看一下结构图
步骤1 主界面
布局activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<LinearLayout
android:layout_centerHorizontal="true"
android:orientation="horizontal"
android:layout_margin="10dp"
android:id="@+id/ll_puzzle_main_spiner"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/select_type"
android:textSize="@dimen/text_title"/>
<TextView
android:id="@+id/select_level"
android:clickable="true"
android:background="@drawable/selector"
android:layout_marginLeft="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/type"
android:textSize="@dimen/text_title_type"/>
</LinearLayout>
<GridView
android:id="@+id/gv_xpuzzle_main_pic_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/ll_puzzle_main_spiner"
android:layout_centerHorizontal="true"
android:layout_margin="@dimen/pading"
android:numColumns="4"
android:horizontalSpacing="@dimen/pading"
android:verticalSpacing="@dimen/pading"
android:gravity="center_horizontal"></GridView>
</RelativeLayout>
这里用状态选择器的自定义TEXTVIEW
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" >
<shape android:shape="rectangle">
<corners android:radius="5dip"/>
<padding android:bottom="10dp"
android:left="10dp"
android:right="10dp"
android:top="10dp"
/>
<solid android:color="#33444444"/>
</shape>
</item>
<item >
<shape android:shape="rectangle">
<corners android:radius="5dip"/>
<padding android:bottom="10dp"
android:left="10dp"
android:right="10dp"
android:top="10dp"
/>
<solid android:color="#FFFFFF"/>
</shape>
</item>
</selector>
往GridView加载图片
for(int i=0;i<bitmaps.length;i++){
bitmaps[i]= BitmapFactory.decodeResource(getResources(),mResPicId[i]);
mPicList.add(bitmaps[i]);
}
mianGridView.setAdapter(new GridPicListAdapter(
MainActivity.this, mPicList));
设置GridView点击事件 点击最后一个弹出对话框 选择本地图片和拍照
mianGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (position == mResPicId.length - 1) {
System.out.println("dfasdfdas");
showDialogCustom();
} else {
// 选择默认图片
Intent intent = new Intent(
MainActivity.this,
PuzzleMainActivity.class);
intent.putExtra("picSelectedID", mResPicId[position]);
intent.putExtra("mType", mType);
startActivity(intent);
}
}
});
对话框 打开本地图片界面或者拍照界面 调用系统的
Intent i=new Intent(Intent.ACTION_PICK,null);
i.setDataAndType( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_TYPE )调用本地相册
这里用到了回调
AlertDialog.Builder builder = new AlertDialog.Builder(
MainActivity.this);
builder.setTitle("选择:");
builder.setItems(mCustomItems,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (0 == which) {
// 本地图册
Intent intent = new Intent(
Intent.ACTION_PICK, null);
intent.setDataAndType(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
IMAGE_TYPE);
startActivityForResult(intent, RESULT_IMAGE);
} else if (1 == which) {
// 系统相机
Intent intent = new Intent(
MediaStore.ACTION_IMAGE_CAPTURE);
Uri photoUri = Uri.fromFile(
new File(TEMP_IMAGE_PATH));
intent.putExtra(
MediaStore.EXTRA_OUTPUT,
photoUri);
startActivityForResult(intent, RESULT_CAMERA);
}
}
});
builder.create().show();
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == RESULT_IMAGE && data != null) {
// 相册
Cursor cursor = this.getContentResolver().query(
data.getData(), null, null, null, null);
cursor.moveToFirst();
String imagePath = cursor.getString(
cursor.getColumnIndex("_data"));
Intent intent = new Intent(
MainActivity.this,
PuzzleMainActivity.class);
intent.putExtra("mPicPath", imagePath); System.out.println("!!!!!!!!!!mPicPath=" + imagePath);
intent.putExtra("mType", mType);
cursor.close();
startActivity(intent);
} else if (requestCode == RESULT_CAMERA) {
// 相机
Intent intent = new Intent(
MainActivity.this,
PuzzleMainActivity.class);
intent.putExtra("mPicPath", TEMP_IMAGE_PATH);
intent.putExtra("mType", mType);
startActivity(intent);
}
}
}
这里用到了回调
startActivityForresult(intent,"回调标志位")然后在onActivityResult中判断标志位,然后做相应处理。 requestCode
到这里主界面的逻辑基本写完。
第二步:拼图界面
1 给每张图片设置一些基本属性,Bitmap Bitmapid ItemID 定义一个ItemBean来封装这些信息
2 在拼图界面 中首先 获取Intent信息 ,获取选择的图片信息
mResId = getIntent().getExtras().getInt("picSelectedID");
mPicPath = getIntent().getExtras().getString("mPicPath");
System.out.println("mResId="+mResId);
System.out.println("mPicPath="+mPicPath);
if (mResId != 0) {
picSelectedTemp = BitmapFactory.decodeResource(
getResources(), mResId);
} else {
picSelectedTemp = BitmapFactory.decodeFile(mPicPath);
}
已经获取到图片信息然后对图片进行处理,放大或者缩小来适应 屏幕。
/**
* 对图片处理 自适应大小
*
* @param bitmap bitmap
*/
private void handlerImage(Bitmap bitmap) {
// 将图片放大到固定尺寸
int screenWidth = ScreenUtil.getScreenSize(this).widthPixels;
int screenHeigt = ScreenUtil.getScreenSize(this).heightPixels;
mPicSelected = new ImagesUtil().resizeBitmap(
screenWidth * 0.8f, screenHeigt * 0.6f, bitmap);
}
/**
* 处理图片 放大、缩小到合适位置
*
* @param newWidth 缩放后Width
* @param newHeight 缩放后Height
* @param bitmap bitmap
* @return bitmap
*/
public Bitmap resizeBitmap(float newWidth, float newHeight, Bitmap bitmap) {
Matrix matrix = new Matrix();
matrix.postScale(
newWidth / bitmap.getWidth(),
newHeight / bitmap.getHeight());
Bitmap newBitmap = Bitmap.createBitmap(
bitmap, 0, 0,
bitmap.getWidth(),
bitmap.getHeight(),
matrix, true);
return newBitmap;
}
生成游戏数据
/**
* 生成游戏数据
*/
private void generateGame() {
// 切图 获取初始拼图数据 正常顺序
new ImagesUtil().createInitBitmaps(
TYPE, mPicSelected, PuzzleMainActivity.this);
// 生成随机数据
GameUtil.getPuzzleGenerator();
// 获取Bitmap集合
for (ItemBean temp : GameUtil.mItemBeans) {
mBitmapItemLists.add(temp.getBitmap());
}
// 数据适配器
mAdapter = new GridItemsAdapter(this, mBitmapItemLists);
mGvPuzzleMainDetail.setAdapter(mAdapter);
// 启用计时器
mTimer = new Timer(true);
// 计时器线程
mTimerTask = new TimerTask() {
@Override
public void run() {
Message msg = new Message();
msg.what = 1;
mHandler.sendMessage(msg);
}
};
// 每1000ms执行 延迟0s
mTimer.schedule(mTimerTask, 0, 1000);
}
拼图的主要逻辑
mGvPuzzleMainDetail.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View view,
int position, long arg3) {
// 判断是否可移动
if (GameUtil.isMoveable(position)) {
// 交换点击Item与空格的位置
GameUtil.swapItems(
GameUtil.mItemBeans.get(position),
GameUtil.mBlankItemBean);
// 重新获取图片
recreateData();
// 通知GridView更改UI
mAdapter.notifyDataSetChanged();
// 更新步数
COUNT_INDEX++;
mTvPuzzleMainCounts.setText("" + COUNT_INDEX);
// 判断是否成功
if (GameUtil.isSuccess()) {
// 将最后一张图显示完整
recreateData();
mBitmapItemLists.remove(TYPE * TYPE - 1);
mBitmapItemLists.add(mLastBitmap);
// 通知GridView更改UI
mAdapter.notifyDataSetChanged();
Toast.makeText(PuzzleMainActivity.this, "拼图成功!",
Toast.LENGTH_LONG).show();
mGvPuzzleMainDetail.setEnabled(false);
mTimer.cancel();
mTimerTask.cancel();
}
}
}
});
好了大概就是这样。源码下载