它应该是一种简单的白板工具,具有缩放/平移效果。
路径部分的整个绘图都没有问题,除了涉及缩放/平移的时候。
当对白板应用缩放时,无论我采用何种方式,应用缩放后出现的所有线条都会相对于我实际进行描边的位置发生位移。
我会尽量公开细节,不显示不必要的代码,仍然是一篇很长的文章,请耐心等待。
一图胜一千,我来举例说明一下:
所以,我尝试了很多不同的方法,但都没有成功。
现在回到技术部分,这就是我现在正在做的:
实现了扩展View。
我只使用 onDraw 方法来执行正在应用的笔画的“动画”:
@Override
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
if(isDrawing)
{
canvas.drawPath(mPath, mPaint);
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
}
}
我有两个 ImageView,用于在执行绘图和缩放后立即放置生成的位图。我使用两个 View 的原因是交换它们,以便在绘图渲染时刻始终有一个可用 View 。
<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" />
在 Canvas 上绘制了一些东西后,我将给定的位图发送到我的 View ,然后清理 Canvas 以将其设置为全新以供更多绘图使用:
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();
}
我实现了一个扩展 ScaleGestureDetector.SimpleOnScaleGestureListener 的 ScaleListener 类
在 onScale 时刻,我告诉 Canvas 我的缩放比例是多少:
@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;
}
然后,在我的 View (canvas obj) 中,我只是将比例设置为正在使用的 View :
mView.setScaleX(factor);
mView.setScaleY(factor);
现在,对于最重要的部分,在 onScaleEnd,我调用了一个方法,我尝试按原样获取当前 Canvas 位图并将其发送到我的 View 以与其 sibling 和平相处,每个 sibling 都有自己的大小和偏移量.
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);
}
现在,我已经尝试过直接在 Canvas 上展示的所有内容,给它一个缩放/平移量;尝试单独处理位图,然后将它们发送回新的干净 Canvas 。
在应用一定量的 ZOOM 后,我的笔画仍然会出现这种位移!!! 我只想画画;放大它;然后再画一些东西,让笔画留在我画的地方!
这可能吗?
我只是在玩 S Note 应用程序,它完全符合我的要求。
最佳答案
我想向您提出一些解决方案,但我不确定它是否有效。
首先我需要澄清一下,你在这段代码中犯了一个大错误:
tempBmp = Bitmap.createScaledBitmap(previousBmp,
(int)(mView.getWidth()*scaleFactor),
(int)(mView.getHeight()*scaleFactor), true);
假设您的平板电脑具有 1280x800
像素和比例因子 4x
甚至 10x
。您将尝试相应地分配 16Mb
和 40Mb
位图!
很容易在此处抛出 OutOfMemoryError
,因此您需要在概念上使用另一种方法。
我建议你使用 Picture
类。
- 您需要确定向用户提供哪种尺寸的原始图片?
- 之后,您需要使用方法
Picture.beginRecord(int width, int height)
在图片周围创建Canvas
对象。 - 现在您可以应用比例因子、平移 Canvas 并执行绘图操作。
- 在
onDraw()
方法中,您需要使用方法Picture.draw(Canvas canvas)
绘制图片。将相应的设置(比例因子、翻译)应用于 Canvas 。
我没有尝试过这个解决方案,但我希望 Picture
类对您有所帮助。
关于java - Android Canvas,具有不同缩放量的多个路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26391911/