【问题标题】:Android view 3d rotate transformation on big resolution screensAndroid 在大分辨率屏幕上查看 3d 旋转变换
【发布时间】:2015-02-26 13:43:45
【问题描述】:

我正在为 android (api > 14) 实现 3d 卡片翻转动画,但大屏幕平板电脑 (> 2048 dpi) 存在问题。在问题调查期间,我来到了以下基本块:

尝试仅使用矩阵和旋转相机的某个角度来转换视图(简单的 ImageView),对于角度 120(已转换和显示)可以正常工作,但是当角度为时图像消失(只是不显示)在 60 到 120 之间。这是我使用的代码:

private void applyTransform(float degree) 
{
     float [] values = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
     float centerX = image1.getMeasuredWidth() / 2.0f;
     float centerY = image1.getMeasuredHeight() / 2.0f;

     Matrix m = new Matrix();
     m.setValues(values);

     Camera camera = new Camera();
     camera.save();

     camera.rotateY(degree);
     camera.getMatrix(m);

     camera.restore();

     m.preTranslate(-centerX, -centerY); // 1 draws fine without these 2 lines
     m.postTranslate(centerX, centerY);  // 2 

    image1.setImageMatrix(m);
}

这是我的布局 XML

   <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout     xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/ImageView01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@drawable/naponer"
        android:clickable="true"
        android:scaleType="matrix">
    </ImageView>
</FrameLayout>  

所以我有以下几种情况:

  • 如果在 800X480、1024x720 等小屏幕上运行,则适用于任何角度、任何中心点...
  • 在大屏幕设备 2048x1536、2560x1600...上运行时,角度 120 可以正常工作...
  • 如果旋转未居中,则在任何设备上的任何角度都可以正常工作(矩阵前后翻译已注释掉)
  • 在大屏幕设备上运行时失败(图像消失),旋转居中,角度在 60 到 120 度之间。

请告诉我做错了什么并建议一些解决方法...谢谢!!!

【问题讨论】:

  • 如果您在 AndroidManifest.xml 中为活动定义 android:hardwareAccelerated="false",问题会消失吗?
  • 无效,测试了硬件加速启用和禁用情况
  • 你试过玩相机距离吗(例如camera.setLocation(0, 0, -20f)
  • 是的!有效!!!谢谢!!!默认值为 0, 0, -8f...现在正在尝试查找有关此设置的更多信息...请解释它如何影响绘图,以便从默认相机位置旋转时图像消失?
  • @matiash 您可以回答这个问题,提供有关它如何影响问题的更多详细信息。

标签: android matrix rotation transform resolution


【解决方案1】:

这个问题是由用于计算变换的相机距离引起的。虽然Camera 类本身并没有对这个主题进行太多说明,但View.setCameraDistance() method 的文档中得到了更好的解释(强调我的):

设置沿 Z 轴的距离(垂直于 X/Y 平面 哪些视图被绘制)从相机到这个视图。相机的 距离会影响 3D 变换,例如围绕 X 和 Y 轴。 (...)

相机与视图平面的距离可能会影响 围绕 x 旋转时视图的透视变形 或 y 轴。例如,一个大的距离将导致一个大的 视角,不会有太大的透视畸变 旋转时的视图。短距离可能会导致更多 旋转时的透视变形,也可能导致一些 如果旋转后的视图部分位于 相机(这就是为什么建议使用距离 如果要旋转视图,则至少与视图的大小一样。)

说实话,我以前没有见过这种特殊的效果(根本没有画出来),但我怀疑它可能与我过去遇到的this question related to perspective distortion 有关。 :)

因此,解决方案是使用Camera.setLocation() 方法来确保不会发生这种情况。

View.setCameraDistance() 方法的一个重要区别是单位不一样,因为setLocation() 不使用像素。 setCameraDistance() 会调整密度,setLocation() 不会。因此,如果您想根据视图的尺寸计算适当的 z 距离,请记住调整密度。例如:

float cameraDistance = Math.max(image1.getMeasuredHeight(), image1.getMeasuredWidth()) * 5;
float densityDpi = getResources().getDisplayMetrics().densityDpi;
camera.setLocation(0, 0, -cameraDistance / densityDpi);

【讨论】:

  • 很好的解决方案...对我有用...但是我使用较小的设备这种方法会改变我的分辨率和相机角度...有什么建议吗?
【解决方案2】:

你可以在第一行实现这个,而不是使用 12 行来创建旋转矩阵 http://en.wikipedia.org/wiki/Rotation_matrix

根据您想要的效果,您可能希望将图像居中到要旋转的轴。 http://en.wikipedia.org/wiki/Transformation_matrix

嗯,对于图像消失,我猜它与内存(内存不足 - 尽管这会带来异常)或舍入问题有关。也许您可以尝试将精度提高到双精度?

想到的一件事是,当 alpha 趋于 PI/2 时,cos(alpha) 趋于 0。除此之外,我没有看到角度之间的任何相关性以及为什么它不适用于大图像。

【讨论】:

  • 确保矩阵计算可以优化到 1-2 行,但这对我来说现在并不重要......问题是在我上面描述的范围内应用最终矩阵后图像消失了精度在这里不起作用......如果它在 PI/2 度时消失(就像在其他设备上一样),我没问题。似乎问题与部分图像超出屏幕范围的范围有关,但我无法弄清楚为什么它必须消失????
  • 每次精确到 60 度和 120 度时它都会消失吗?还是有点随机,有时是62,有时是58?
  • 前/后翻译的另一件事。你说它没有那些行?问题可能是您在旋转之前没有将图像居中。也许尝试翻译(中心)-> 旋转-> 翻译(后退)。尝试使用 Camera.translate(x,y,z) developer.android.com/reference/android/graphics/Camera.html
  • 1.不精确的 60 和 120,我以 5 度的步长进行测试,它在 60 时消失并在 120 时重新出现...
  • 2.没有前/后翻译图像旋转轴不居中,并且它永远不会超出屏幕边界,这就是它起作用的原因......当旋转轴以某种方式居中时出现问题(前/后翻译或预先计算的矩阵)
【解决方案3】:

您需要调整翻译坐标。在计算图像的平移时,您还需要考虑图像大小。当您执行矩阵计算时,您为您的ImageView 设置android:scaleType="matrix"。默认情况下,这会将您的图像对齐在左上角。然后,当您应用预/后翻译时,您的图像可能会超出您的ImageView 的范围(尤其是如果ImageView 相对较大而您的图像相对较小,例如 beeg 屏幕平板电脑)。

以下平移导致图像围绕其中心 Y 轴旋转并保持图像与左上角对齐:

m.preTranslate(-imageWidth/2, 0);
m.postTranslate(imageWidth/2, 0);

以下替代方法会导致图像围绕其中心 Y/X 轴旋转并将图像与ImageView 的中心对齐:

m.preTranslate(-imageWidth/2, -imageHeight/2);
m.postTranslate(centerX, centerY);

如果您的图像是位图,您可以使用固有宽度/高度:

Drawable drawable = image1.getDrawable();
imageHeight = drawable.getIntrinsicHeight();
imageWidth = drawable.getIntrinsicWidth();

【讨论】:

  • 实际上我看不出这两个中心点之间有任何区别...但是测试了您的建议,结果完全相同 - 图像在同一范围内消失...
  • 您能提供您的活动布局 XML 吗?我正在使用包含单个 ImageView 的简单布局被拉伸以填充整个屏幕,它工作正常 :)
  • 当然,将其添加到原始帖子中...还使用拉伸以填满整个屏幕的 ImageView 进行了测试-不起作用...我怀疑您没有在高分辨率设备上进行测试 > 2048x1536跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多