[英]Android: Why can't I paint on my canvas bitmap after rotating screen?
我正在使用Android的Fingerpaint演示[1]来测试Canvas和Bitmap。 我想在屏幕上绘制对象,并在屏幕旋转后继续绘制对象。 在屏幕旋转后,Fingerpaint演示会擦除屏幕-我想保留屏幕内容,并随屏幕一起旋转。
使用我的代码,我可以旋转屏幕和绘制的图像。 但是我不再能够向位图添加任何其他路径标记。 它变得像只读位图。 有人知道我在做什么错吗?
这是我保存图像并在旋转后还原它的代码。 请注意,我将其另存为字节数组(在onSaveInstanceState()中)为PNG,然后从onCreate()中的字节数组创建了一个新的位图(我认为可以吗?):
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
Log.d("TAG", "Saving state...");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
canvasView.mBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
imageByteArray = stream.toByteArray();
savedInstanceState.putSerializable("ByteArray", imageByteArray);
super.onSaveInstanceState(savedInstanceState);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
canvasView = new MyView(this);
setContentView(canvasView);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFF00FF00);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.MITER);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
if (savedInstanceState != null) {
Log.d("TAG", "Restoring any bitmaps...");
byte[] imageByteArray = (byte[]) savedInstanceState.getSerializable("ByteArray");
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inMutable = true;
Bitmap savedImage = BitmapFactory.decodeByteArray(imageByteArray, 0, imageByteArray.length, opt);
canvasView.mBitmap = savedImage;
}
}
在我的自定义视图MyView中,这是在屏幕变化时旋转位图的代码:
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int orientation = display.getRotation();
Log.d("CANVAS", "Rotation: " + orientation);
if (mBitmap == null) {
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
} else {
Matrix rotator = new Matrix();
rotator.postRotate(orientation * 3);
Bitmap rotatedBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), rotator, true);
mCanvas = new Canvas(rotatedBitmap);
mCanvas.drawBitmap(rotatedBitmap, 0, 0, mPaint);
}
}
几乎所有其他内容都与Fingerpaint演示中的相同。 我可以按下以在屏幕上进行标记,但是当我抬起手指时,我创建的路径不会应用于位图。
这是onTouchEvent()的重复说明(我没有对其进行修改):
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
预先感谢您的任何见解。 我怀疑我对Canvas应该如何工作的理解是不正确的,因此我感到困惑!
[1]完整的Fingerpaint演示位于此处: https : //android.googlesource.com/platform/development/+/master/samples/ApiDemos/src/com/example/android/apis/graphics/FingerPaint.java
BitmapFactory.decodeByteArray()忽略了您要求可变位图的选项,并为您提供了一个不可变的位图,因为它就是这样滚动的。
decodeByteArray
Bitmap decodeByteArray (byte[] data,
int offset,
int length,
BitmapFactory.Options opts)
Decode an immutable bitmap from the specified byte array.
您需要使用一种创建可变位图的方法之一来创建一个新的位图对象。 然后将不可变位图绘制为可变位图。 然后把那个加载了那个功能的那个扔掉。
不可变性的原因是,位图是根据您提供的字节创建的。 因此,为了提高速度,它们由这些字节支持。 它们是相同的记忆。 实际的位图对象的工作方式与此不同,您不能仅仅通过将正常内存中的这些字节强制进入GPU来神奇地制作可变的位图。 您可以只创建第二个位图对象并将数据绘制到该第二个位图中。
您必须控制活动的配置更改。
<activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name">
有关更多详细信息,请访问https://developer.android.com/guide/topics/resources/runtime-changes.html
希望能帮助到你..
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.