2016-11-16 4 views
0

Я использую демонстрацию Fingerpaint от Android [1], чтобы экспериментировать с Canvas и Bitmaps. Я хочу нарисовать объект на экране и продолжить рисовать объект после поворота экрана. Демоверсия Fingerpaint стирает экран после поворота экрана - я хочу сохранить содержимое экрана и просто повернуть его вместе с экраном.Android: Почему я не могу рисовать на своем растровом изображении после поворота экрана?

С моим кодом я могу повернуть экран и изображение, которое я нарисовал. Но я больше не могу добавлять какие-либо дополнительные метки пути к растровому изображению. Он становится как битмап только для чтения. Кто-нибудь знает, что я делаю неправильно?

Вот код, где я хочу сохранить изображение и восстановить его после вращения. Обратите внимание на то, что я спасаю его как PNG в массив байтов (в onSaveInstanceState()), а затем создать новый Bitmap из этого байтового массива в 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; 
     } 

Заранее спасибо за любую проницательность. Я подозреваю, что мое понимание того, как работает Холст, неверно, и, следовательно, мое замешательство!

[1] Полный Fingerpaint демо здесь: https://android.googlesource.com/platform/development/+/master/samples/ApiDemos/src/com/example/android/apis/graphics/FingerPaint.java

ответ

0

Вы должны контролировать ваши изменения конфигурации для деятельности.

<activity android:name=".MyActivity" 
     android:configChanges="orientation|keyboardHidden" 
     android:label="@string/app_name"> 

Для получения более подробной информации просто пойти на https://developer.android.com/guide/topics/resources/runtime-changes.html

Надеются, что это помогает ..

+0

Это не сработало. Я попытался восстановить свой проект после внесения изменений, но проблема все еще существует. –

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. 

Вам нужно создать новый растровый объект, используя один из способов создать изменяемую битовую карту. Затем нарисуйте неизменяемое растровое изображение в изменчивое. Затем бросьте ту, которую вы загрузили с помощью этой функции.

Причина неизменности в том, что растровое изображение было создано из тех байтов, которые вы ему дали. Поэтому для скорости они поддерживаются этими байтами. Они - одна и та же память. И то, как работают действительные объекты растровых изображений, отличается от этого, и вы не можете просто волшебным образом сделать изменчивое растровое изображение, заставив эти байты из обычной памяти в графический процессор. Вы можете просто сделать второй объект растрового изображения и покрасить данные в это второе растровое изображение.

Смежные вопросы