Android Canvas, несколько путей с различными значениями масштабирования

Он должен быть простым инструментом для доски, с эффектами масштабирования/панорамирования.

Все в порядке со всем рисунком пути, за исключением случаев, когда оно приближается к масштабированию/панорамированию.

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

Я постараюсь разоблачить детали как можно лучше, не показывая лишний код, но это довольно длинный пост, пожалуйста, несите меня.

Как изображение стоит тысячи слов, я проиллюстрирую ситуацию:

enter image description here

enter image description here

enter image description here

enter image description here

Итак, я пробовал много разных подходов, без каких-либо успехов.

Теперь, вплоть до технической части, это то, что я делаю прямо сейчас:

Он реализовал расширение представления.

Я использую метод onDraw только для выполнения "анимации" применяемых штрихов:

@Override
public void onDraw(Canvas canvas) 
{
    super.onDraw(canvas);

    if(isDrawing)
    {
        canvas.drawPath(mPath,  mPaint);
        canvas.drawBitmap(mBitmap, 0, 0, mPaint);   
    }
}

У меня есть два ImageViews, которые я использую для размещения полученного растрового изображения сразу после выполнения чертежа и масштабирования. Причина, по которой я использую два представления, - это обменять их, чтобы всегда иметь один доступный вид в момент рендеринга чертежа.

 <ImageView
 android:id="@+id/imageView"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:layout_alignParentLeft="true"  
 android:layout_alignParentTop="true"    
 android:visibility="visible"     
 android:scaleType="matrix" />

 <ImageView     
 android:id="@+id/imageView2"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:layout_alignParentLeft="true"          
 android:layout_alignParentTop="true"    
 android:visibility="visible"     
 android:scaleType="matrix" />

После того, как что-то нарисовано на холсте, я отправляю данный растровый рисунок на мой взгляд, затем очищаю холст, чтобы он стал новым для большего количества рисунков:

 private void sendImage2BackView()
 {
     //veeery extensive and boring code surpressed here

     //set the entire hocus-pocus' resulting bitmap as a resource for my view
     mView.setImageBitmap(tempBmp);
     mView.bringToFront();  


 }

Я реализую класс ScaleListener, который расширяет ScaleGestureDetector.SimpleOnScaleGestureListener

В моменты onScale я рассказываю моему холсту, что моя доля scalling:

@Override
public boolean onScale(ScaleGestureDetector detector) 
{   
    drawAction = ZOOM;      
    scaleFactor *= detector.getScaleFactor();
    scaleFactor = Math.max(MIN_ZOOM, Math.min(scaleFactor, MAX_ZOOM));

    canvas.setScaleFactor(scaleFactor);
    return true;
}

Затем, в моем представлении (canvas obj), я просто установил масштаб для используемого вида:

    mView.setScaleX(factor);
    mView.setScaleY(factor);     

Теперь, для самой важной части, в onScaleEnd, я вызываю метод, который я пытаюсь получить текущее растровое изображение canvas AS IS, и отправлю его на мой взгляд, чтобы мирно жить со своими братьями и сестрами, каждый из которых имеет свой собственный размер и смещение,

    public void setScaleEnd()
    {
         //Lots of more boring code surpressed here
         //....

         //I store the bitmap that was contained at the ImageView
         // IF anyone is present
         previousBmp = ((BitmapDrawable)mView.getDrawable()).getBitmap();

         //then, I create a brand new scaled bitmap,in order to 
         // acquire the same proportion of ZOOM that I've just applied
         tempBmp = Bitmap.createScaledBitmap(previousBmp,
            (int)(mView.getWidth()*scaleFactor),
            (int)(mView.getHeight()*scaleFactor), true);


         int height = (int)(mView.getHeight()*scaleFactor);
         int width = (int)(mView.getWidth()*scaleFactor);

         //set my matrix
         mMatrix = new Matrix();

         //give it the right proportion
         mMatrix.postScale(scaleFactor, scaleFactor);

         translationX = mView.getWidth() / 2 - width / 2;
         translationY = mView.getHeight() / 2 - height / 2;

         //give it some necessary translation amount
         mMatrix.postTranslate(translationX, translationY);

         //set the matrix to the view, and send the resized bitmap to my ImageView.
         mView.setImageMatrix(mMatrix);
         mView.setImageBitmap(tempBmp);
    }

Теперь я попробовал во время всего, что я только что показал прямо на холсте, придав ему значение масштаба/перевода; попробовав работать отдельно с растровыми изображениями, затем отправил их обратно на новый чистый холст.

Тем не менее, я продолжаю получать это перемещение по моим ударам после того, как будет применено заданное количество ZOOM!!! Я просто хочу быть в состоянии рисовать; придать ему зум; затем нарисуйте еще что-нибудь, и пусть штрихи останутся там, где я рисую!

Возможно ли это?

Я просто играл с приложением S Note, он делает именно то, что я пытаюсь достичь.

Ответ 1

Я хочу предложить вам какое-то решение, но я не уверен, что он сработает.

Сначала мне нужно уточнить, что вы совершили большую ошибку в этом коде:

     tempBmp = Bitmap.createScaledBitmap(previousBmp,
        (int)(mView.getWidth()*scaleFactor),
        (int)(mView.getHeight()*scaleFactor), true);

Предположим, что у вас есть планшет с 1280x800 пикселями и масштабным коэффициентом 4x или даже 10x. Вы попытаетесь выделить соответственно 16Mb и 40Mb Bitmap!

Так легко получить OutOfMemoryError, брошенный здесь, поэтому вам нужно использовать концептуально другой подход.

Я советую вам использовать Picture класс.

  • Вам нужно определить, какой размер оригинального изображения вы предоставляете пользователю?
  • После этого вам нужно создать объект Canvas вокруг вашего изображения, используя метод Picture.beginRecord(int width, int height)
  • Теперь вы можете применить масштабный коэффициент, перевести холст и выполнить операции рисования.
  • Внутри метода onDraw() вам необходимо нарисовать свое изображение, используя метод Picture.draw(Canvas canvas) с соответствующими настройками (масштабный коэффициент, перевод), применяемым к холст.

Я не пробовал это решение, но надеюсь, что класс Picture поможет вам.