我正在开发一款类似于最著名的文字游戏。棋盘有 15 x 15 块。瓷砖有 5 种可能的颜色。
棋盘可以放大。也就是说,您可以看到棋盘的全视图,也可以放大 2 倍。
我已经在我的活动中实现了两种绘制板的方法。两者都在我的 Galaxy S 和各种模拟器上测试过。两者似乎都可以在绝大多数设备上正常工作。但是,它们都会给少数用户带来问题(这是我在这里试图解决的问题)。
以下是对 2 种设计的描述:
选项 1:“大图”
描述:
这是最简单的一种。该板是一个独特的ImageView
(子类以处理双击缩放和拖动)。图片PNG资源是高分辨率的:大约。最大屏幕尺寸的两倍,以避免放大时放大。
问题: 有时在大屏幕上似乎会出现 OutOfMemory 问题,尤其是在 10" Asus TF101 平板电脑上。
评论: TF101 的测试表明 RAM 使用率是 Galaxy S 的 3 倍。考虑到必须绘制的巨大比例位图,这似乎是合乎逻辑的。
选项 2:重复 5 个小图像
描述: 我试图减少位图使用的 RAM,并利用板只是 5 种小方块的重复这一事实。为了方便调整板视图的大小,我选择将其设为自定义 LinearLayout,其中包含 15 个嵌套的 LinearLayout,每个包含 15 个图像(这当然不是性能方面的最佳选择)。
这是我的 XML 布局对于 4 x 4 板的样子:
<MyCustomLinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal" >
<ImageView
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1" >
</ImageView>
<ImageView
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1" >
</ImageView>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal" >
<ImageView
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1" >
</ImageView>
<ImageView
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1" >
</ImageView>
</LinearLayout>
</MyCustomLinearLayout>
问题: 某些用户的一些崩溃或视觉故障。(我仍然没有太多关于这个的信息)
评论: 优点:选项之一是优化了内存占用: 5 个小位图中的每一个只有一个实例保存在内存中。调整板的大小很简单:当我调整 MyCustomLinearLayout 的大小时,Android 会调整位图和嵌套的 LinearLayouts 的大小。
缺点:视图太多,系统必须在每次缩放时重新计算哪些尺寸。
如何改进选项 2 以保持较低的 RAM 占用,同时尊重其他性能良好实践(例如没有数百个视图)?
编辑:最终(?)实施
而不是一个SurfaceView
,我去一个简单的自定义View
。
怕在方法中做大量的位图绘制onDraw()
会导致板子的拖拽滞后(因为onDraw()
板子移动的时候不断调用)。
事实证明它非常平滑(甚至可能比选项 2 更平滑)。至于 RAM 使用率,它只是比选项 2 重一点(使用 Eclipse Memory Analyzer 进行的比较),因此令人满意。我仍然有一些关于 OutOfMemory 错误的报告(“位图超出最大 VM 堆大小”),但我认为使用位图是不可避免的。
这是最重要的代码,我在其中绘制 15x15 位图(从视图构造函数中的资源初始化)来构建游戏板:
public void drawTileAtCoordsOnCanvas(Bitmap bm, Canvas canvas, int x, int y) {
_rect.set(x * _sizeOfTile, y * _sizeOfTile, (x + 1) * _sizeOfTile, (y + 1) * _sizeOfTile);
canvas.drawBitmap(bm, null, _rect, _paint);
}
public void onDraw(Canvas canvas) {
for (int i = 0; i < _rules.BOARD_SIZE; i++) {
for (int j = 0; j < _rules.BOARD_SIZE; j++) {
switch (_rules._boardOfMultiplicators.get(i).get(j)) {
case NL:
drawTileAtCoordsOnCanvas(_bitmapNormalTile, canvas, i, j);
break;
case DL:
drawTileAtCoordsOnCanvas(_bitmapDlTile, canvas, i, j);
break;
case TL:
drawTileAtCoordsOnCanvas(_bitmapTlTile, canvas, i, j);
break;
case DW:
drawTileAtCoordsOnCanvas(_bitmapDwTile, canvas, i, j);
break;
case TW:
drawTileAtCoordsOnCanvas(_bitmapTwTile, canvas, i, j);
break;
}
}
}
drawTileAtCoordsOnCanvas(_bitmapStarTile, canvas, 7, 7);
}