I'm implementing 3d card flip animation for android (api > 14) and have an issue with big screen tablets (> 2048 dpi). During problem investigation i've come to the following basic block:
Tried to just transform a view (simple ImageView) using matrix and rotateY of camera by some angle and it works ok for angle < 60 and angle > 120 (transformed and displayed) but image disappears (just not displayed) when angle is between 60 and 120. Here is the code I use:
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);
}
And here is my layout 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>
So I have the following cases:
Please tell what I'm doing wrong and advise some workaround... thank you!!!
This problem is caused by the camera distance used to calculate the transformation. While the Camera
class itself doesn't say much about the subject, it is better explained in the documentation for the View.setCameraDistance()
method (emphasis mine):
Sets the distance along the Z axis (orthogonal to the X/Y plane on which views are drawn) from the camera to this view. The camera's distance affects 3D transformations, for instance rotations around the X and Y axis. (...)
The distance of the camera from the view plane can have an affect on the perspective distortion of the view when it is rotated around the x or y axis. For example, a large distance will result in a large viewing angle, and there will not be much perspective distortion of the view as it rotates. A short distance may cause much more perspective distortion upon rotation, and can also result in some drawing artifacts if the rotated view ends up partially behind the camera (which is why the recommendation is to use a distance at least as far as the size of the view, if the view is to be rotated.)
To be honest, I hadn't seen this particular effect (not drawing at all) before, but I suspected it could be related to this question related to perspective distortion I'd encountered in the past. :)
Therefore, the solution is to use the Camera.setLocation()
method to ensure this doesn't happen.
An important distinction with the View.setCameraDistance()
method is that the units are not the same, since setLocation()
doesn't use pixels. While setCameraDistance()
adjusts for density, setLocation()
does not. Therefore, if you wanted to calculate an appropriate z-distance based on the view's dimensions, remember to adjust for density. For example:
float cameraDistance = Math.max(image1.getMeasuredHeight(), image1.getMeasuredWidth()) * 5;
float densityDpi = getResources().getDisplayMetrics().densityDpi;
camera.setLocation(0, 0, -cameraDistance / densityDpi);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With