今天来优化一下游戏界面,因为笔者希望做出来的东西能够有人会去参考或者使用。这个版本完善了一下界面,最终效果和最初的手稿设计有所不同,因为使用了ActionBar,又改了一些细节。同时也修复了上一版中快速反复单击移动块是可能出现的错乱问题的bug。运行效果如下:
一、大图片内存溢出问题
向这种图片列表,且列表中显示的是大图的情况。通常都需要处理内存溢出的问题,笔者之前也没注意,后来就频繁报内存溢出的问题。现在做了简单的处理,处理方法有两种:一是在保存图片时就将图片压缩到指定尺寸,这样在读取时就不需要做处理。二是在读取时将图片压缩到指定尺寸后再加载到内存。笔者这里用的是第二种方法:
/** * 从资源文件中得到指定大小的尺寸的图片 * @param res * @param resId * @param reqWidth * @param reqHeight * @return */ public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); } /** * 从SD卡中得到指定大小的尺寸的图片 * @param res * @param resId * @param reqWidth * @param reqHeight * @return */ public static Bitmap decodeSampledBitmapFromSD(Resources res, String filePath, int reqWidth, int reqHeight) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(filePath, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(filePath, options); } /** * 计算sampleSize * @param options * @param reqWidth * @param reqHeight * @return */ public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 4; if (height > reqHeight || width > reqWidth) { final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; }
以上主要有个步骤:1.计算sampleSize。2.根据计算得到的sampleSize和目标尺寸得到目标bitmap。
二、自定义组件的屏幕适配
自定义组件的屏幕适配,想本应用中的移动方格,就需要进行动态处理。实现的思路就是根据组件所在屏幕的宽高百分比进行组件的生成。有兴趣的朋友可以看一下笔者的另一篇将屏幕适配的博客:Android多屏幕适配技巧整理
三、组件截图的实现
本来问题列表是new了多个尺寸小一点的GamePanel组件实现的,但是发现这样的动态创建十分占用内存,导致程序运行速度受到很到的影响。现在的处理方法是在PuzzleDetailActivity的onPause中保存截图。然后在问题列表中读取缩略图图片。代码如下:
/** * 保存缩略图样式的puzzle * @param context * @param panel * @param puzzle */ public static void savePuzzleBitmap(Context context,GamePanel panel,Puzzle puzzle) { panel.setDrawingCacheEnabled(true); panel.buildDrawingCache(); Bitmap bitmap = panel.getDrawingCache(); bitmap = bitmap.createScaledBitmap(bitmap , Conf.snap_tile_size * 4 , Conf.snap_tile_size * 4, false); if(bitmap != null) { ImageTool.saveBitmapToSD(context, bitmap,puzzle.getSnapPath()); } }
注意使用getDrawingCache()方法获取组件截图时,如果组件包含透明像素,则透明像素会被黑色填充。
四、调用相机/相册的同时支持图片剪裁功能(保证显示效果的整齐,统一)
/** * 调用图片编辑界面 * @param activity * @param data * @param requestCode */ public static void editPicture(Activity activity,Uri data,int requestCode) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(data, "image/*"); intent.putExtra("crop", "true");//可裁剪 intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("outputX", 300); intent.putExtra("outputY", 300); intent.putExtra("scale", true); intent.putExtra(MediaStore.EXTRA_OUTPUT, data); intent.putExtra("return-data", true);//若为false则表示不返回数据 intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.putExtra("noFaceDetection", true); activity.startActivityForResult(intent, requestCode); }
剪切图片的代码参考博文:
http://my.eoe.cn/yaming/archive/89.html
好了,界面还是比较耗时的。不过总算基本整齐、干净了。至此拼图游戏的开发过程已基本结束,后面笔者还会例行写一篇总结。也许笔者还会再一些优化,比如做一个开场动画,考虑一下关卡设计之类的东西。不过这些已不再本系列博客的计划范围之内了,如果有新版本,笔者会上传效果的。
O啦~~~