Home | History | Annotate | Download | only in keyguard
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.keyguard;
     17 
     18 import android.animation.Animator;
     19 import android.animation.AnimatorListenerAdapter;
     20 import android.animation.ValueAnimator;
     21 import android.animation.ValueAnimator.AnimatorUpdateListener;
     22 import android.content.Context;
     23 import android.content.res.TypedArray;
     24 import android.graphics.Canvas;
     25 import android.graphics.drawable.Drawable;
     26 import android.util.AttributeSet;
     27 import android.view.animation.DecelerateInterpolator;
     28 import android.view.animation.Interpolator;
     29 import android.view.animation.LinearInterpolator;
     30 import android.widget.LinearLayout;
     31 
     32 /**
     33  * A layout which animates a strip of horizontal, pulsing dots on request. This is used
     34  * to indicate the presence of pages to the left / right.
     35  */
     36 public class KeyguardGlowStripView extends LinearLayout {
     37     private static final int DURATION = 500;
     38 
     39     private static final float SLIDING_WINDOW_SIZE = 0.4f;
     40     private int mDotStripTop;
     41     private int mHorizontalDotGap;
     42 
     43     private int mDotSize;
     44     private int mNumDots;
     45     private Drawable mDotDrawable;
     46     private boolean mLeftToRight = true;
     47 
     48     private float mAnimationProgress = 0f;
     49     private boolean mDrawDots = false;
     50     private ValueAnimator mAnimator;
     51     private Interpolator mDotAlphaInterpolator = new DecelerateInterpolator(0.5f);
     52 
     53     public KeyguardGlowStripView(Context context) {
     54         this(context, null, 0);
     55     }
     56 
     57     public KeyguardGlowStripView(Context context, AttributeSet attrs) {
     58         this(context, attrs, 0);
     59     }
     60 
     61     public KeyguardGlowStripView(Context context, AttributeSet attrs, int defStyle) {
     62         super(context, attrs, defStyle);
     63 
     64         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.KeyguardGlowStripView);
     65         mDotSize = a.getDimensionPixelSize(R.styleable.KeyguardGlowStripView_dotSize, mDotSize);
     66         mNumDots = a.getInt(R.styleable.KeyguardGlowStripView_numDots, mNumDots);
     67         mDotDrawable = a.getDrawable(R.styleable.KeyguardGlowStripView_glowDot);
     68         mLeftToRight = a.getBoolean(R.styleable.KeyguardGlowStripView_leftToRight, mLeftToRight);
     69     }
     70 
     71     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
     72         int availableWidth = w - getPaddingLeft() - getPaddingRight();
     73         mHorizontalDotGap = (availableWidth - mDotSize * mNumDots) /  (mNumDots - 1);
     74         mDotStripTop = getPaddingTop();
     75         invalidate();
     76     }
     77 
     78     @Override
     79     protected void dispatchDraw(Canvas canvas) {
     80         super.dispatchDraw(canvas);
     81 
     82         if (!mDrawDots) return;
     83 
     84         int xOffset = getPaddingLeft();
     85         mDotDrawable.setBounds(0, 0, mDotSize, mDotSize);
     86 
     87         for (int i = 0; i < mNumDots; i++) {
     88             // We fudge the relative position to provide a fade in of the first dot and a fade
     89             // out of the final dot.
     90             float relativeDotPosition = SLIDING_WINDOW_SIZE / 2 + ((1.0f * i) / (mNumDots - 1)) *
     91                     (1 - SLIDING_WINDOW_SIZE);
     92             float distance = Math.abs(relativeDotPosition - mAnimationProgress);
     93             float alpha = Math.max(0, 1 - distance / (SLIDING_WINDOW_SIZE / 2));
     94 
     95             alpha = mDotAlphaInterpolator.getInterpolation(alpha);
     96 
     97             canvas.save();
     98             canvas.translate(xOffset, mDotStripTop);
     99             mDotDrawable.setAlpha((int) (alpha * 255));
    100             mDotDrawable.draw(canvas);
    101             canvas.restore();
    102             xOffset += mDotSize + mHorizontalDotGap;
    103         }
    104     }
    105 
    106     public void makeEmGo() {
    107         if (mAnimator != null) {
    108             mAnimator.cancel();
    109         }
    110         float from = mLeftToRight ? 0f : 1f;
    111         float to = mLeftToRight ? 1f : 0f;
    112         mAnimator = ValueAnimator.ofFloat(from, to);
    113         mAnimator.setDuration(DURATION);
    114         mAnimator.setInterpolator(new LinearInterpolator());
    115         mAnimator.addListener(new AnimatorListenerAdapter() {
    116             @Override
    117             public void onAnimationEnd(Animator animation) {
    118                 mDrawDots = false;
    119                 // make sure we draw one frame at the end with everything gone.
    120                 invalidate();
    121             }
    122 
    123             @Override
    124             public void onAnimationStart(Animator animation) {
    125                 mDrawDots = true;
    126             }
    127         });
    128         mAnimator.addUpdateListener(new AnimatorUpdateListener() {
    129             @Override
    130             public void onAnimationUpdate(ValueAnimator animation) {
    131                 mAnimationProgress = (Float) animation.getAnimatedValue();
    132                 invalidate();
    133             }
    134         });
    135         mAnimator.start();
    136     }
    137 }
    138