2016-11-16 94 views
0

我正在使用Android的Fingerpaint演示[1]来试验Canvas和Bitmaps。我想在屏幕上绘制一个对象,并在屏幕旋转后继续绘制对象。 Fingerpaint演示会在屏幕旋转后擦除屏幕 - 我想保留屏幕内容并随屏幕一起旋转屏幕。Android:为什么不能在旋转屏幕后在画布位图上绘制?

用我的代码,我可以旋转屏幕和我绘制的图像。但是我不能再为位图添加任何其他路径标记。它变得像只读位图。有谁知道我是我做错了什么?

下面是我保存图像并在旋转后恢复的代码。请注意,我将其保存为一个字节数组PNG(可在的onSaveInstanceState()),然后创建从的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

回答

1

BitmapFactory.decodeByteArray()忽略,你问一个可变位的选项,给你一个不可变因为这是如何滚动。

https://developer.android.com/reference/android/graphics/BitmapFactory.html#decodeByteArray(byte[], int, int, android.graphics.BitmapFactory.Options)

decodeByteArray 
    Bitmap decodeByteArray (byte[] data, 
        int offset, 
        int length, 
        BitmapFactory.Options opts) 
    Decode an immutable bitmap from the specified byte array. 

你需要创建一个新的位图对象,使用创建一个可变的位图的方法之一。然后将不可变的位图绘制成可变的位图。然后扔你用那个函数加载的那个。

不可变性的原因是位图是从你给它的那些字节创建的。所以对于速度他们是由这些字节支持。他们是相同的记忆。实际位图对象的工作方式与此不同,并且您不能通过强制正常内存中的字节进入GPU来制作可变位图。您可以制作第二个位图对象并将数据绘制到第二个位图中。

相关问题