android - 基于父视图中的位置渲染位图
问题描述
我正在尝试制作一个简单的图像编辑器。一开始我认为将视图状态简单地保存为位图是个好主意,但事实证明,屏幕分辨率范围很广,这会导致巨大的质量(和内存使用)波动。
现在我正在尝试制作一个将视图状态转换为所需分辨率的模块。
在下面的代码中,我试图在画布中重新创建视图的当前状态:
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.id.test_1_1);
bitmap = Bitmap.createScaledBitmap(bitmap, parentView.getMeasuredWidth(), parentView.getMeasuredHeight(), true);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
for (View rootView : addedViews) {
ImageView imageView = rootView.findViewById(R.id.sticker);
float[] viewPosition = new float[2];
transformToAncestor(viewPosition, parentView, imageView);
Bitmap originalBitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
Matrix adjustMatrix = new Matrix();
adjustMatrix.postTranslate(viewPosition[0], viewPosition[1]);
adjustMatrix.postScale(
rootView.getScaleX(),
rootView.getScaleY(),
rootView.getWidth() / 2,
rootView.getHeight() / 2);
adjustMatrix.postRotate(rootView.getRotation(),
rootView.getWidth() / 2,
rootView.getHeight() / 2);
canvas.drawBitmap(originalBitmap, adjustMatrix, paint);
}
transformToAncestor
功能来自这里。
public static void transformToAncestor(float[] point, final View ancestor, final View descendant) {
final float scrollX = descendant.getScrollX();
final float scrollY = descendant.getScrollY();
final float left = descendant.getLeft();
final float top = descendant.getTop();
final float px = descendant.getPivotX();
final float py = descendant.getPivotY();
final float tx = descendant.getTranslationX();
final float ty = descendant.getTranslationY();
final float sx = descendant.getScaleX();
final float sy = descendant.getScaleY();
point[0] = left + px + (point[0] - px) * sx + tx - scrollX;
point[1] = top + py + (point[1] - py) * sy + ty - scrollY;
ViewParent parent = descendant.getParent();
if (descendant != ancestor && parent != ancestor && parent instanceof View) {
transformToAncestor(point, ancestor, (View) parent);
}
}
(作者写了一个说明,他的函数不支持旋转,但在我的例子中没有太多的旋转,所以我认为现在不重要)。
我的问题是:
第一个图像是通过保存父视图状态生成的。第二个是通过将视图位置、旋转和缩放转换到画布上生成的。如您所见,在画布上,未缩放的贴纸位置正确,但缩放的位置不正确。
如何正确定位这些缩放视图?
解决方案
我自己设法解决了这个问题。结果证明我的解决方案几乎没问题,但我没有考虑到我对矩阵的操作确实改变了原始点的排列,所以我的
rootView.getWidth() / 2,
rootView.getHeight() / 2
Matrix.postScale
调用或后不再适用于视图的中心Matrix.postRotation
。
我想:
- 在左上角应用带有枢轴的比例,
- 在视图中心应用带有枢轴的旋转。
给定假设,这是工作代码:
// setup variables for sizing and transformation
float position[] = new float[2];
transformToAncestor(position, rootView, imageView);
float desiredRotation = imageView.getRotation();
float sizeDeltaX = imageView.getMeasuredWidth() / (float) imageBitmap.getWidth();
float sizeDeltaY = imageView.getMeasuredHeight() / (float) imageBitmap.getHeight();
float desiredScaleX = imageView.getScaleX() * sizeDeltaX * scaleX;
float desiredScaleY = imageView.getScaleY() * sizeDeltaY * scaleY;
float imageViewWidth = imageView.getMeasuredWidth() * imageView.getScaleX();
float imageViewHeight = imageView.getMeasuredHeight() * imageView.getScaleY();
float rootViewWidth = rootView.getMeasuredWidth();
float rootViewHeight = rootView.getMeasuredHeight();
float percentXPos = position[0] / rootViewWidth;
float percentYPos = position[1] / rootViewHeight;
float percentXCenterPos = (position[0] + imageViewWidth/2)
/ rootViewWidth;
float percentYCenterPos = (position[1] + imageViewHeight/2)
/ rootViewHeight;
float desiredPositionX = background.getWidth() * percentXPos;
float desiredPositionY = background.getHeight() * percentYPos;
float desiredCenterX = background.getWidth() * percentXCenterPos;
float desiredCenterY = background.getHeight() * percentYCenterPos;
// apply above variables to matrix
Matrix matrix = new Matrix();
float[] points = new float[2];
matrix.postTranslate(
desiredPositionX,
desiredPositionY);
matrix.mapPoints(points);
matrix.postScale(
desiredScaleX,
desiredScaleY,
points[0],
points[1]);
matrix.postRotate(
desiredRotation,
desiredCenterX,
desiredCenterY);
// apply matrix to bitmap, then draw it on canvas
canvas.drawBitmap(imageBitmap, matrix, paint);
如您所见,该mapPoints
方法是我问题的答案 - 它只是在转换后返回点。
推荐阅读
- java - java.lang.ClassNotFoundException: com.amazonaws.transform.EnhancedJsonErrorUnmarshaller
- php - 如何在 foreach 循环中访问 PHP 中的变量?
- c - 并发非重叠 pwrite() 到使用多个 MPI 进程安装在 NFS 上的文件
- oracle - 在具有不同数据库服务器的客户端上安装 ORACLE APEX
- wordpress - 如果 url 等于 functions.php 中的某些内容,则在标题上添加元标记
- python - 我无法在 TKINTER 中播放 GIF
- arrays - array.map 不是函数,reactjs setState 错误
- vue.js - Nuxtjs中如何导出整个项目中的组件?
- python - 熊猫如何将_excel x读取到最后一列?
- java - Autowired Spring Bean 在抽象父类中为空