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 
     17 package com.android.internal.policy.impl.keyguard;
     18 
     19 import android.animation.Animator;
     20 import android.animation.AnimatorListenerAdapter;
     21 import android.animation.ValueAnimator.AnimatorUpdateListener;
     22 import android.animation.ValueAnimator;
     23 import android.content.Context;
     24 import android.content.pm.UserInfo;
     25 import android.content.res.Resources;
     26 import android.graphics.Bitmap;
     27 import android.graphics.BitmapFactory;
     28 import android.graphics.Color;
     29 import android.util.AttributeSet;
     30 import android.util.Log;
     31 import android.view.LayoutInflater;
     32 import android.view.View;
     33 import android.widget.FrameLayout;
     34 import android.widget.ImageView;
     35 import android.widget.TextView;
     36 
     37 import com.android.internal.R;
     38 
     39 class KeyguardMultiUserAvatar extends FrameLayout {
     40     private static final String TAG = KeyguardMultiUserAvatar.class.getSimpleName();
     41     private static final boolean DEBUG = KeyguardHostView.DEBUG;
     42 
     43     private ImageView mUserImage;
     44     private TextView mUserName;
     45     private UserInfo mUserInfo;
     46     private static final float ACTIVE_ALPHA = 1.0f;
     47     private static final float INACTIVE_ALPHA = 1.0f;
     48     private static final float ACTIVE_SCALE = 1.5f;
     49     private static final float ACTIVE_TEXT_ALPHA = 0f;
     50     private static final float INACTIVE_TEXT_ALPHA = 0.5f;
     51     private static final int SWITCH_ANIMATION_DURATION = 150;
     52 
     53     private final float mActiveAlpha;
     54     private final float mActiveScale;
     55     private final float mActiveTextAlpha;
     56     private final float mInactiveAlpha;
     57     private final float mInactiveTextAlpha;
     58     private final float mShadowRadius;
     59     private final float mStroke;
     60     private final float mIconSize;
     61     private final int mFrameColor;
     62     private final int mFrameShadowColor;
     63     private final int mTextColor;
     64     private final int mHighlightColor;
     65 
     66     private boolean mTouched;
     67 
     68     private boolean mActive;
     69     private boolean mInit = true;
     70     private KeyguardMultiUserSelectorView mUserSelector;
     71     private KeyguardCircleFramedDrawable mFramed;
     72     private boolean mPressLock;
     73 
     74     public static KeyguardMultiUserAvatar fromXml(int resId, Context context,
     75             KeyguardMultiUserSelectorView userSelector, UserInfo info) {
     76         KeyguardMultiUserAvatar icon = (KeyguardMultiUserAvatar)
     77                 LayoutInflater.from(context).inflate(resId, userSelector, false);
     78 
     79         icon.init(info, userSelector);
     80         return icon;
     81     }
     82 
     83     public KeyguardMultiUserAvatar(Context context) {
     84         this(context, null, 0);
     85     }
     86 
     87     public KeyguardMultiUserAvatar(Context context, AttributeSet attrs) {
     88         this(context, attrs, 0);
     89     }
     90 
     91     public KeyguardMultiUserAvatar(Context context, AttributeSet attrs, int defStyle) {
     92         super(context, attrs, defStyle);
     93 
     94         Resources res = mContext.getResources();
     95         mTextColor = res.getColor(R.color.keyguard_avatar_nick_color);
     96         mIconSize = res.getDimension(R.dimen.keyguard_avatar_size);
     97         mStroke = res.getDimension(R.dimen.keyguard_avatar_frame_stroke_width);
     98         mShadowRadius = res.getDimension(R.dimen.keyguard_avatar_frame_shadow_radius);
     99         mFrameColor = res.getColor(R.color.keyguard_avatar_frame_color);
    100         mFrameShadowColor = res.getColor(R.color.keyguard_avatar_frame_shadow_color);
    101         mHighlightColor = res.getColor(R.color.keyguard_avatar_frame_pressed_color);
    102         mActiveTextAlpha = ACTIVE_TEXT_ALPHA;
    103         mInactiveTextAlpha = INACTIVE_TEXT_ALPHA;
    104         mActiveScale = ACTIVE_SCALE;
    105         mActiveAlpha = ACTIVE_ALPHA;
    106         mInactiveAlpha = INACTIVE_ALPHA;
    107 
    108         mTouched = false;
    109 
    110         setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    111     }
    112 
    113     protected String rewriteIconPath(String path) {
    114         if (!this.getClass().getName().contains("internal")) {
    115             return path.replace("system", "data");
    116         }
    117         return path;
    118     }
    119 
    120     public void init(UserInfo user, KeyguardMultiUserSelectorView userSelector) {
    121         mUserInfo = user;
    122         mUserSelector = userSelector;
    123 
    124         mUserImage = (ImageView) findViewById(R.id.keyguard_user_avatar);
    125         mUserName = (TextView) findViewById(R.id.keyguard_user_name);
    126 
    127         mFramed = (KeyguardCircleFramedDrawable)
    128                 KeyguardViewMediator.getAvatarCache().get(user.id);
    129 
    130         // If we can't find it or the params don't match, create the drawable again
    131         if (mFramed == null
    132                 || !mFramed.verifyParams(mIconSize, mFrameColor, mStroke, mFrameShadowColor,
    133                         mShadowRadius, mHighlightColor)) {
    134             Bitmap icon = null;
    135             try {
    136                 icon = BitmapFactory.decodeFile(rewriteIconPath(user.iconPath));
    137             } catch (Exception e) {
    138                 if (DEBUG) Log.d(TAG, "failed to open profile icon " + user.iconPath, e);
    139             }
    140 
    141             if (icon == null) {
    142                 icon = BitmapFactory.decodeResource(mContext.getResources(),
    143                         com.android.internal.R.drawable.ic_contact_picture);
    144             }
    145 
    146             mFramed = new KeyguardCircleFramedDrawable(icon, (int) mIconSize, mFrameColor, mStroke,
    147                     mFrameShadowColor, mShadowRadius, mHighlightColor);
    148             KeyguardViewMediator.getAvatarCache().put(user.id, mFramed);
    149         }
    150 
    151         mFramed.reset();
    152 
    153         mUserImage.setImageDrawable(mFramed);
    154         mUserName.setText(mUserInfo.name);
    155         setOnClickListener(mUserSelector);
    156         mInit = false;
    157     }
    158 
    159     public void setActive(boolean active, boolean animate, final Runnable onComplete) {
    160         if (mActive != active || mInit) {
    161             mActive = active;
    162 
    163             if (active) {
    164                 KeyguardLinearLayout parent = (KeyguardLinearLayout) getParent();
    165                 parent.setTopChild(this);
    166                 // TODO: Create an appropriate asset when string changes are possible.
    167                 setContentDescription(mUserName.getText()
    168                         + ". " + mContext.getString(R.string.user_switched, ""));
    169             } else {
    170                 setContentDescription(mUserName.getText());
    171             }
    172         }
    173         updateVisualsForActive(mActive, animate, SWITCH_ANIMATION_DURATION, onComplete);
    174     }
    175 
    176     void updateVisualsForActive(boolean active, boolean animate, int duration,
    177             final Runnable onComplete) {
    178         final float finalAlpha = active ? mActiveAlpha : mInactiveAlpha;
    179         final float initAlpha = active ? mInactiveAlpha : mActiveAlpha;
    180         final float finalScale = active ? 1f : 1f / mActiveScale;
    181         final float initScale = mFramed.getScale();
    182         final int finalTextAlpha = active ? (int) (mActiveTextAlpha * 255) :
    183                 (int) (mInactiveTextAlpha * 255);
    184         final int initTextAlpha = active ? (int) (mInactiveTextAlpha * 255) :
    185                 (int) (mActiveTextAlpha * 255);
    186         int textColor = mTextColor;
    187         mUserName.setTextColor(textColor);
    188 
    189         if (animate && mTouched) {
    190             ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
    191             va.addUpdateListener(new AnimatorUpdateListener() {
    192                 @Override
    193                 public void onAnimationUpdate(ValueAnimator animation) {
    194                     float r = animation.getAnimatedFraction();
    195                     float scale = (1 - r) * initScale + r * finalScale;
    196                     float alpha = (1 - r) * initAlpha + r * finalAlpha;
    197                     int textAlpha = (int) ((1 - r) * initTextAlpha + r * finalTextAlpha);
    198                     mFramed.setScale(scale);
    199                     mUserImage.setAlpha(alpha);
    200                     mUserName.setTextColor(Color.argb(textAlpha, 255, 255, 255));
    201                     mUserImage.invalidate();
    202                 }
    203             });
    204             va.addListener(new AnimatorListenerAdapter() {
    205                 @Override
    206                 public void onAnimationEnd(Animator animation) {
    207                     if (onComplete != null) {
    208                         onComplete.run();
    209                     }
    210                 }
    211             });
    212             va.setDuration(duration);
    213             va.start();
    214         } else {
    215             mFramed.setScale(finalScale);
    216             mUserImage.setAlpha(finalAlpha);
    217             mUserName.setTextColor(Color.argb(finalTextAlpha, 255, 255, 255));
    218             if (onComplete != null) {
    219                 post(onComplete);
    220             }
    221         }
    222 
    223         mTouched = true;
    224     }
    225 
    226     @Override
    227     public void setPressed(boolean pressed) {
    228         if (mPressLock && !pressed) {
    229             return;
    230         }
    231 
    232         if (mPressLock || !pressed || isClickable()) {
    233             super.setPressed(pressed);
    234             mFramed.setPressed(pressed);
    235             mUserImage.invalidate();
    236         }
    237     }
    238 
    239     public void lockPressed(boolean pressed) {
    240         mPressLock = pressed;
    241         setPressed(pressed);
    242     }
    243 
    244     public UserInfo getUserInfo() {
    245         return mUserInfo;
    246     }
    247 }
    248