Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4846032a authored by Chet Haase's avatar Chet Haase
Browse files

Fix bug with layout animations when apps are auto-scaled.

The pivot points in RotateAnimation and ScaleAnimation are in pixel coordinates. When an app is being autoscaled, these values are incorrect and should be adjusted for the current scale factor. The fix adds API to Animation to allow ViewGroup to pass in the scaling factor.

Change-Id: I978c48f9b5aea6760148435e74e1a8d49e2f785d
parent 48d98558
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -193434,6 +193434,17 @@
 visibility="public"
>
</method>
<method name="getScaleFactor"
 return="float"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="protected"
>
</method>
<method name="getStartOffset"
 return="long"
 abstract="false"
@@ -193471,6 +193482,23 @@
<parameter name="outTransformation" type="android.view.animation.Transformation">
</parameter>
</method>
<method name="getTransformation"
 return="boolean"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="currentTime" type="long">
</parameter>
<parameter name="outTransformation" type="android.view.animation.Transformation">
</parameter>
<parameter name="scale" type="float">
</parameter>
</method>
<method name="getZAdjustment"
 return="int"
 abstract="false"
+42 −21
Original line number Diff line number Diff line
@@ -86,10 +86,23 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
    // The view contained within this ViewGroup that has or contains focus.
    private View mFocused;

    // The current transformation to apply on the child being drawn
    private Transformation mChildTransformation;
    /**
     * A Transformation used when drawing children, to
     * apply on the child being drawn.
     */
    private final Transformation mChildTransformation = new Transformation();

    /**
     * Used to track the current invalidation region.
     */
    private RectF mInvalidateRegion;

    /**
     * A Transformation used to calculate a correct
     * invalidation area when the application is autoscaled.
     */
    private Transformation mInvalidationTransformation;

    // Target of Motion events
    private View mMotionTarget;
    private final Rect mTempRect = new Rect();
@@ -1482,21 +1495,25 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        final int flags = mGroupFlags;

        if ((flags & FLAG_CLEAR_TRANSFORMATION) == FLAG_CLEAR_TRANSFORMATION) {
            if (mChildTransformation != null) {
            mChildTransformation.clear();
            }
            mGroupFlags &= ~FLAG_CLEAR_TRANSFORMATION;
        }

        Transformation transformToApply = null;
        Transformation invalidationTransform;
        final Animation a = child.getAnimation();
        boolean concatMatrix = false;

        if (a != null) {
            if (mInvalidateRegion == null) {
                mInvalidateRegion = new RectF();
        boolean scalingRequired = false;
        boolean caching = false;
        if (!canvas.isHardwareAccelerated() &&
                (flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE ||
                (flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) {
            caching = true;
            if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
        }
            final RectF region = mInvalidateRegion;

        if (a != null) {

            final boolean initialized = a.isInitialized();
            if (!initialized) {
@@ -1505,10 +1522,17 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                child.onAnimationStart();
            }

            if (mChildTransformation == null) {
                mChildTransformation = new Transformation();
            more = a.getTransformation(drawingTime, mChildTransformation,
                    scalingRequired ? mAttachInfo.mApplicationScale : 1f);
            if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
                if (mInvalidationTransformation == null) {
                    mInvalidationTransformation = new Transformation();
                }
                invalidationTransform = mInvalidationTransformation;
                a.getTransformation(drawingTime, invalidationTransform, 1f);
            } else {
                invalidationTransform = mChildTransformation;
            }
            more = a.getTransformation(drawingTime, mChildTransformation);
            transformToApply = mChildTransformation;

            concatMatrix = a.willChangeTransformationMatrix();
@@ -1525,7 +1549,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                        invalidate(cl, ct, cr, cb);
                    }
                } else {
                    a.getInvalidateRegion(0, 0, cr - cl, cb - ct, region, transformToApply);
                    if (mInvalidateRegion == null) {
                        mInvalidateRegion = new RectF();
                    }
                    final RectF region = mInvalidateRegion;
                    a.getInvalidateRegion(0, 0, cr - cl, cb - ct, region, invalidationTransform);

                    // The child need to draw an animation, potentially offscreen, so
                    // make sure we do not cancel invalidate requests
@@ -1538,9 +1566,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
            }
        } else if ((flags & FLAG_SUPPORT_STATIC_TRANSFORMATIONS) ==
                FLAG_SUPPORT_STATIC_TRANSFORMATIONS) {
            if (mChildTransformation == null) {
                mChildTransformation = new Transformation();
            }
            final boolean hasTransform = getChildStaticTransformation(child, mChildTransformation);
            if (hasTransform) {
                final int transformType = mChildTransformation.getTransformationType();
@@ -1564,13 +1589,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        final int sx = child.mScrollX;
        final int sy = child.mScrollY;

        boolean scalingRequired = false;
        Bitmap cache = null;
        if (!canvas.isHardwareAccelerated() &&
                (flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE ||
                (flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) {
        if (caching) {
            cache = child.getDrawingCache(true);
            if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
        }

        final boolean hasNoCache = cache == null;
+39 −1
Original line number Diff line number Diff line
@@ -175,6 +175,12 @@ public abstract class Animation implements Cloneable {
     */
    private int mZAdjustment;

    /**
     * scalefactor to apply to pivot points, etc. during animation. Subclasses retrieve the
     * value via getScaleFactor().
     */
    private float mScaleFactor = 1f;

    /**
     * Don't animate the wallpaper.
     */
@@ -552,6 +558,19 @@ public abstract class Animation implements Cloneable {
        mZAdjustment = zAdjustment;
    }
    
    /**
     * The scale factor is set by the call to <code>getTransformation</code>. Overrides of 
     * {@link #getTransformation(long, Transformation, float)} will get this value
     * directly. Overrides of {@link #applyTransformation(float, Transformation)} can
     * call this method to get the value.
     * 
     * @return float The scale factor that should be applied to pre-scaled values in
     * an Animation such as the pivot points in {@link ScaleAnimation} and {@link RotateAnimation}.
     */
    protected float getScaleFactor() {
        return mScaleFactor;
    }

    /**
     * If detachWallpaper is true, and this is a window animation of a window
     * that has a wallpaper background, then the window will be detached from
@@ -735,6 +754,7 @@ public abstract class Animation implements Cloneable {
     * @return True if the animation is still running
     */
    public boolean getTransformation(long currentTime, Transformation outTransformation) {

        if (mStartTime == -1) {
            mStartTime = currentTime;
        }
@@ -807,6 +827,24 @@ public abstract class Animation implements Cloneable {
        return mMore;
    }
    
    /**
     * Gets the transformation to apply at a specified point in time. Implementations of this
     * method should always replace the specified Transformation or document they are doing
     * otherwise.
     *
     * @param currentTime Where we are in the animation. This is wall clock time.
     * @param outTransformation A tranformation object that is provided by the
     *        caller and will be filled in by the animation.
     * @param scale Scaling factor to apply to any inputs to the transform operation, such
     *        pivot points being rotated or scaled around.
     * @return True if the animation is still running
     */
    public boolean getTransformation(long currentTime, Transformation outTransformation,
            float scale) {
        mScaleFactor = scale;
        return getTransformation(currentTime, outTransformation);
    }

    /**
     * <p>Indicates whether this animation has started or not.</p>
     *
+1 −1
Original line number Diff line number Diff line
@@ -312,7 +312,7 @@ public class AnimationSet extends Animation {
            final Animation a = animations.get(i);

            temp.clear();
            more = a.getTransformation(currentTime, temp) || more;
            more = a.getTransformation(currentTime, temp, getScaleFactor()) || more;
            t.compose(temp);

            started = started || a.hasStarted();
+3 −2
Original line number Diff line number Diff line
@@ -148,11 +148,12 @@ public class RotateAnimation extends Animation {
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        float degrees = mFromDegrees + ((mToDegrees - mFromDegrees) * interpolatedTime);
        float scale = getScaleFactor();
        
        if (mPivotX == 0.0f && mPivotY == 0.0f) {
            t.getMatrix().setRotate(degrees);
        } else {
            t.getMatrix().setRotate(degrees, mPivotX, mPivotY);
            t.getMatrix().setRotate(degrees, mPivotX * scale, mPivotY * scale);
        }
    }

Loading