Merge "Add 3D rotation to View"

This commit is contained in:
Chet Haase
2010-08-10 11:01:42 -07:00
committed by Android (Google) Code Review
3 changed files with 211 additions and 20 deletions

View File

@@ -193711,6 +193711,28 @@
visibility="public"
>
</method>
<method name="getRotationX"
return="float"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="getRotationY"
return="float"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="getScaleX"
return="float"
abstract="false"
@@ -195881,6 +195903,32 @@
<parameter name="rotation" type="float">
</parameter>
</method>
<method name="setRotationX"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="rotationX" type="float">
</parameter>
</method>
<method name="setRotationY"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="rotationY" type="float">
</parameter>
</method>
<method name="setSaveEnabled"
return="void"
abstract="false"
@@ -213266,6 +213314,17 @@
visibility="public"
>
</method>
<method name="getVisibleTitleHeight"
return="int"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="getZoomControls"
return="android.view.View"
abstract="false"

View File

@@ -16,6 +16,7 @@
package android.view;
import android.graphics.Camera;
import com.android.internal.R;
import com.android.internal.view.menu.MenuBuilder;
@@ -1536,6 +1537,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
*/
private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
/**
* Indicates that pivotX or pivotY were explicitly set and we should not assume the center
* for transform operations
*
* @hide
*/
private static final int PIVOT_EXPLICITLY_SET = 0x10000000;
/**
* The parent this view is attached to.
* {@hide}
@@ -1626,6 +1635,42 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
*/
private boolean mMatrixIsIdentity = true;
/**
* The Camera object is used to compute a 3D matrix when rotationX or rotationY are set.
*/
private Camera mCamera = null;
/**
* This matrix is used when computing the matrix for 3D rotations.
*/
private Matrix matrix3D = null;
/**
* These prev values are used to recalculate a centered pivot point when necessary. The
* pivot point is only used in matrix operations (when rotation, scale, or translation are
* set), so thes values are only used then as well.
*/
private int mPrevWidth = -1;
private int mPrevHeight = -1;
/**
* Convenience value to check for float values that are close enough to zero to be considered
* zero.
*/
private static float NONZERO_EPSILON = .001f;
/**
* The degrees rotation around the vertical axis through the pivot point.
*/
@ViewDebug.ExportedProperty
private float mRotationY = 0f;
/**
* The degrees rotation around the horizontal axis through the pivot point.
*/
@ViewDebug.ExportedProperty
private float mRotationX = 0f;
/**
* The degrees rotation around the pivot point.
*/
@@ -4887,6 +4932,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
return mMatrix;
}
/**
* Utility function to determine if the value is far enough away from zero to be
* considered non-zero.
* @param value A floating point value to check for zero-ness
* @return whether the passed-in value is far enough away from zero to be considered non-zero
*/
private static boolean nonzero(float value) {
return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON);
}
/**
* Recomputes the transform matrix if necessary.
*
@@ -4896,10 +4951,34 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
if (mMatrixDirty) {
// transform-related properties have changed since the last time someone
// asked for the matrix; recalculate it with the current values
// Figure out if we need to update the pivot point
if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
if ((mRight - mLeft) != mPrevWidth && (mBottom - mTop) != mPrevHeight) {
mPrevWidth = mRight - mLeft;
mPrevHeight = mBottom - mTop;
mPivotX = (float) mPrevWidth / 2f;
mPivotY = (float) mPrevHeight / 2f;
}
}
mMatrix.reset();
mMatrix.setTranslate(mTranslationX, mTranslationY);
mMatrix.preRotate(mRotation, mPivotX, mPivotY);
mMatrix.preScale(mScaleX, mScaleY, mPivotX, mPivotY);
if (nonzero(mRotationX) || nonzero(mRotationY)) {
if (mCamera == null) {
mCamera = new Camera();
matrix3D = new Matrix();
}
mCamera.save();
mCamera.rotateX(mRotationX);
mCamera.rotateY(mRotationY);
mCamera.getMatrix(matrix3D);
matrix3D.preTranslate(-mPivotX, -mPivotY);
matrix3D.postTranslate(mPivotX, mPivotY);
mMatrix.postConcat(matrix3D);
mCamera.restore();
}
mMatrixDirty = false;
mMatrixIsIdentity = mMatrix.isIdentity();
mInverseMatrixDirty = true;
@@ -4954,6 +5033,64 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
}
/**
* The degrees that the view is rotated around the vertical axis through the pivot point.
*
* @see #getPivotX()
* @see #getPivotY()
* @return The degrees of Y rotation.
*/
public float getRotationY() {
return mRotationY;
}
/**
* Sets the degrees that the view is rotated around the vertical axis through pivot point.
*
* @param rotationY The degrees of Y rotation.
* @see #getPivotX()
* @see #getPivotY()
*/
public void setRotationY(float rotationY) {
if (mRotationY != rotationY) {
// Double-invalidation is necessary to capture view's old and new areas
invalidate();
mRotationY = rotationY;
mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate();
}
}
/**
* The degrees that the view is rotated around the horizontal axis through the pivot point.
*
* @see #getPivotX()
* @see #getPivotY()
* @return The degrees of X rotation.
*/
public float getRotationX() {
return mRotationX;
}
/**
* Sets the degrees that the view is rotated around the horizontal axis through pivot point.
*
* @param rotationX The degrees of X rotation.
* @see #getPivotX()
* @see #getPivotY()
*/
public void setRotationX(float rotationX) {
if (mRotationX != rotationX) {
// Double-invalidation is necessary to capture view's old and new areas
invalidate();
mRotationX = rotationX;
mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate();
}
}
/**
* The amount that the view is scaled in x around the pivot point, as a proportion of
* the view's unscaled width. A value of 1, the default, means that no scaling is applied.
@@ -5035,6 +5172,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
/**
* Sets the x location of the point around which the view is
* {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
* By default, the pivot point is centered on the object.
* Setting this property disables this behavior and causes the view to use only the
* explicitly set pivotX and pivotY values.
*
* @param pivotX The x location of the pivot point.
* @see #getRotation()
@@ -5043,6 +5183,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* @see #getPivotY()
*/
public void setPivotX(float pivotX) {
mPrivateFlags |= PIVOT_EXPLICITLY_SET;
if (mPivotX != pivotX) {
// Double-invalidation is necessary to capture view's old and new areas
invalidate();
@@ -5069,7 +5210,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
/**
* Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
* and {@link #setScaleY(float) scaled}.
* and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
* Setting this property disables this behavior and causes the view to use only the
* explicitly set pivotX and pivotY values.
*
* @param pivotY The y location of the pivot point.
* @see #getRotation()
@@ -5078,6 +5221,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* @see #getPivotY()
*/
public void setPivotY(float pivotY) {
mPrivateFlags |= PIVOT_EXPLICITLY_SET;
if (mPivotY != pivotY) {
// Double-invalidation is necessary to capture view's old and new areas
invalidate();
@@ -5312,15 +5456,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* is still within the view.
*/
private boolean pointInView(float localX, float localY, float slop) {
if (!hasIdentityMatrix() && mAttachInfo != null) {
// non-identity matrix: transform the point into the view's coordinates
final float[] localXY = mAttachInfo.mTmpTransformLocation;
localXY[0] = localX;
localXY[1] = localY;
getInverseMatrix().mapPoints(localXY);
localX = localXY[0];
localY = localXY[1];
}
return localX > -slop && localY > -slop && localX < ((mRight - mLeft) + slop) &&
localY < ((mBottom - mTop) + slop);
}

View File

@@ -905,19 +905,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
// Calculate the offset point into the target's local coordinates
float xc;
float yc;
if (target.hasIdentityMatrix() || mAttachInfo == null) {
xc = scrolledXFloat - (float) target.mLeft;
yc = scrolledYFloat - (float) target.mTop;
} else {
float xc = scrolledXFloat - (float) target.mLeft;
float yc = scrolledYFloat - (float) target.mTop;
if (!target.hasIdentityMatrix() && mAttachInfo != null) {
// non-identity matrix: transform the point into the view's coordinates
final float[] localXY = mAttachInfo.mTmpTransformLocation;
localXY[0] = scrolledXFloat;
localXY[1] = scrolledYFloat;
localXY[0] = xc;
localXY[1] = yc;
target.getInverseMatrix().mapPoints(localXY);
xc = localXY[0] - (float) target.mLeft;
yc = localXY[1] - (float) target.mTop;
xc = localXY[0];
yc = localXY[1];
}
// if have a target, see if we're allowed to and want to intercept its