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

Commit a2d487e3 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add new line disappearing animation to LockPatternView."

parents 1adaa411 08e34241
Loading
Loading
Loading
Loading
+122 −25
Original line number Diff line number Diff line
@@ -19,16 +19,20 @@ package com.android.internal.widget;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.CanvasProperty;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.os.Bundle;
@@ -70,7 +74,9 @@ public class LockPatternView extends View {
    private static final int ASPECT_LOCK_HEIGHT = 2; // Fixed height; width will be minimum of (w,h)

    private static final boolean PROFILE_DRAWING = false;
    private static final float LINE_FADE_ALPHA_MULTIPLIER = 1.5f;
    private static final int LINE_END_ANIMATION_DURATION_MILLIS = 50;
    private static final int LINE_FADE_OUT_DURATION_MILLIS = 500;
    private static final int LINE_FADE_OUT_DELAY_MILLIS = 150;
    private final CellState[][] mCellStates;

    private final int mDotSize;
@@ -139,6 +145,7 @@ public class LockPatternView extends View {
    private float mSquareWidth;
    @UnsupportedAppUsage
    private float mSquareHeight;
    private final LinearGradient mFadeOutGradientShader;

    private final Path mCurrentPath = new Path();
    private final Rect mInvalidate = new Rect();
@@ -232,7 +239,10 @@ public class LockPatternView extends View {
        float alpha = 1f;
        public float lineEndX = Float.MIN_VALUE;
        public float lineEndY = Float.MIN_VALUE;
        public ValueAnimator lineAnimator;
        @Nullable
        ValueAnimator lineEndAnimator;
        @Nullable
        ValueAnimator lineDisappearingAnimator;
     }

    /**
@@ -361,6 +371,14 @@ public class LockPatternView extends View {
        mExploreByTouchHelper = new PatternExploreByTouchHelper(this);
        setAccessibilityDelegate(mExploreByTouchHelper);
        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);

        int fadeAwayGradientWidth = getResources().getDimensionPixelSize(
                R.dimen.lock_pattern_fade_away_gradient_width);
        // Set up gradient shader with the middle in point (0, 0).
        mFadeOutGradientShader = new LinearGradient(/* x0= */ -fadeAwayGradientWidth / 2f,
                /* y0= */ 0,/* x1= */ fadeAwayGradientWidth / 2f, /* y1= */ 0,
                Color.TRANSPARENT, pathColor, Shader.TileMode.CLAMP);

        a.recycle();
    }

@@ -791,8 +809,13 @@ public class LockPatternView extends View {
                });
        startLineEndAnimation(cellState, mInProgressX, mInProgressY,
                getCenterXForColumn(cell.column), getCenterYForRow(cell.row));
        startLineDisappearingAnimation(cellState);
    }

    /**
     * On the last frame before cell activates the end point of in progress line is not aligned
     * with dot center so we execute a short animation moving the end point to exact dot center.
     */
    private void startLineEndAnimation(final CellState state,
            final float startX, final float startY, final float targetX, final float targetY) {
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
@@ -808,13 +831,37 @@ public class LockPatternView extends View {
        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                state.lineAnimator = null;
                state.lineEndAnimator = null;
            }
        });
        valueAnimator.setInterpolator(mFastOutSlowInInterpolator);
        valueAnimator.setDuration(100);
        valueAnimator.setDuration(LINE_END_ANIMATION_DURATION_MILLIS);
        valueAnimator.start();
        state.lineAnimator = valueAnimator;
        state.lineEndAnimator = valueAnimator;
    }

    /**
     * Starts animator to fade out a line segment. It does only invalidate because all the
     * transitions are applied in {@code onDraw} method.
     */
    private void startLineDisappearingAnimation(final CellState state) {
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                invalidate();
            }
        });
        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                state.lineDisappearingAnimator = null;
            }
        });
        valueAnimator.setStartDelay(LINE_FADE_OUT_DELAY_MILLIS);
        valueAnimator.setDuration(LINE_FADE_OUT_DURATION_MILLIS);
        valueAnimator.start();
        state.lineDisappearingAnimator = valueAnimator;
    }

    private void startRadiusAnimation(float start, float end, long duration,
@@ -1051,11 +1098,16 @@ public class LockPatternView extends View {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                CellState state = mCellStates[i][j];
                if (state.lineAnimator != null) {
                    state.lineAnimator.cancel();
                if (state.lineEndAnimator != null) {
                    state.lineEndAnimator.cancel();
                    state.lineEndAnimator = null;
                    state.lineEndX = Float.MIN_VALUE;
                    state.lineEndY = Float.MIN_VALUE;
                }
                if (state.lineDisappearingAnimator != null) {
                    state.lineDisappearingAnimator.cancel();
                    state.lineDisappearingAnimator = null;
                }
            }
        }
    }
@@ -1195,29 +1247,19 @@ public class LockPatternView extends View {
                float centerX = getCenterXForColumn(cell.column);
                float centerY = getCenterYForRow(cell.row);
                if (i != 0) {
                   // Set this line segment to fade away animated.
                   int lineFadeVal = (int) Math.min((elapsedRealtime -
                           mLineFadeStart[i]) * LINE_FADE_ALPHA_MULTIPLIER, 255f);

                    CellState state = mCellStates[cell.row][cell.column];
                    currentPath.rewind();
                    currentPath.moveTo(lastX, lastY);
                    float endX;
                    float endY;
                    if (state.lineEndX != Float.MIN_VALUE && state.lineEndY != Float.MIN_VALUE) {
                        currentPath.lineTo(state.lineEndX, state.lineEndY);
                        if (mFadePattern) {
                            mPathPaint.setAlpha((int) 255 - lineFadeVal );
                        } else {
                            mPathPaint.setAlpha(255);
                        }
                    } else {
                        currentPath.lineTo(centerX, centerY);
                        if (mFadePattern) {
                            mPathPaint.setAlpha((int) 255 - lineFadeVal );
                        endX = state.lineEndX;
                        endY = state.lineEndY;
                    } else {
                            mPathPaint.setAlpha(255);
                        }
                        endX = centerX;
                        endY = centerY;
                    }
                    canvas.drawPath(currentPath, mPathPaint);
                    drawLineSegment(canvas, /* startX = */ lastX, /* startY = */ lastY, endX, endY,
                            mLineFadeStart[i], elapsedRealtime);
                }
                lastX = centerX;
                lastY = centerY;
@@ -1260,6 +1302,61 @@ public class LockPatternView extends View {
        }
    }

    private void drawLineSegment(Canvas canvas, float startX, float startY, float endX, float endY,
            long lineFadeStart, long elapsedRealtime) {
        float fadeAwayProgress;
        if (mFadePattern) {
            if (elapsedRealtime - lineFadeStart
                    >= LINE_FADE_OUT_DELAY_MILLIS + LINE_FADE_OUT_DURATION_MILLIS) {
                // Time for this segment animation is out so we don't need to draw it.
                return;
            }
            // Set this line segment to fade away animated.
            fadeAwayProgress = Math.max(
                    ((float) (elapsedRealtime - lineFadeStart - LINE_FADE_OUT_DELAY_MILLIS))
                            / LINE_FADE_OUT_DURATION_MILLIS, 0f);
            drawFadingAwayLineSegment(canvas, startX, startY, endX, endY, fadeAwayProgress);
        } else {
            mPathPaint.setAlpha(255);
            canvas.drawLine(startX, startY, endX, endY, mPathPaint);
        }
    }

    private void drawFadingAwayLineSegment(Canvas canvas, float startX, float startY, float endX,
            float endY, float fadeAwayProgress) {
        mPathPaint.setAlpha((int) (255 * (1 - fadeAwayProgress)));

        // To draw gradient segment we use mFadeOutGradientShader which has immutable coordinates
        // thus we will need to translate and rotate the canvas.
        mPathPaint.setShader(mFadeOutGradientShader);
        canvas.save();

        // First translate canvas to gradient middle point.
        float gradientMidX = endX * fadeAwayProgress + startX * (1 - fadeAwayProgress);
        float gradientMidY = endY * fadeAwayProgress + startY * (1 - fadeAwayProgress);
        canvas.translate(gradientMidX, gradientMidY);

        // Then rotate it to the direction of the segment.
        double segmentAngleRad = Math.atan((endY - startY) / (endX - startX));
        float segmentAngleDegrees = (float) Math.toDegrees(segmentAngleRad);
        if (endX - startX < 0) {
            // Arc tangent gives us angle degrees [-90; 90] thus to cover [90; 270] degrees we
            // need this hack.
            segmentAngleDegrees += 180f;
        }
        canvas.rotate(segmentAngleDegrees);

        // Pythagoras theorem.
        float segmentLength = (float) Math.hypot(endX - startX, endY - startY);

        // Draw the segment in coordinates aligned with shader coordinates.
        canvas.drawLine(/* startX= */ -segmentLength * fadeAwayProgress, /* startY= */
                0,/* stopX= */ segmentLength * (1 - fadeAwayProgress), /* stopY= */ 0, mPathPaint);

        canvas.restore();
        mPathPaint.setShader(null);
    }

    private float calculateLastSegmentAlpha(float x, float y, float lastX, float lastY) {
        float diffX = x - lastX;
        float diffY = y - lastY;
+2 −0
Original line number Diff line number Diff line
@@ -641,6 +641,8 @@
    <dimen name="lock_pattern_dot_line_width">22dp</dimen>
    <dimen name="lock_pattern_dot_size">14dp</dimen>
    <dimen name="lock_pattern_dot_size_activated">30dp</dimen>
    <!-- Width of a gradient applied to a lock pattern line while its disappearing animation. -->
    <dimen name="lock_pattern_fade_away_gradient_width">8dp</dimen>

    <dimen name="text_handle_min_size">40dp</dimen>

+1 −0
Original line number Diff line number Diff line
@@ -1318,6 +1318,7 @@
  <java-symbol type="dimen" name="lock_pattern_dot_line_width" />
  <java-symbol type="dimen" name="lock_pattern_dot_size" />
  <java-symbol type="dimen" name="lock_pattern_dot_size_activated" />
  <java-symbol type="dimen" name="lock_pattern_fade_away_gradient_width" />
  <java-symbol type="drawable" name="clock_dial" />
  <java-symbol type="drawable" name="clock_hand_hour" />
  <java-symbol type="drawable" name="clock_hand_minute" />