/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.policy.impl.keyguard; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator.AnimatorUpdateListener; import android.animation.ValueAnimator; import android.content.Context; import android.content.pm.UserInfo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; import com.android.internal.R; class KeyguardMultiUserAvatar extends FrameLayout { private static final String TAG = KeyguardMultiUserAvatar.class.getSimpleName(); private static final boolean DEBUG = KeyguardHostView.DEBUG; private ImageView mUserImage; private TextView mUserName; private UserInfo mUserInfo; private static final float ACTIVE_ALPHA = 1.0f; private static final float INACTIVE_ALPHA = 1.0f; private static final float ACTIVE_SCALE = 1.5f; private static final float ACTIVE_TEXT_ALPHA = 0f; private static final float INACTIVE_TEXT_ALPHA = 0.5f; private static final int SWITCH_ANIMATION_DURATION = 150; private final float mActiveAlpha; private final float mActiveScale; private final float mActiveTextAlpha; private final float mInactiveAlpha; private final float mInactiveTextAlpha; private final float mShadowRadius; private final float mStroke; private final float mIconSize; private final int mFrameColor; private final int mFrameShadowColor; private final int mTextColor; private final int mHighlightColor; private boolean mTouched; private boolean mActive; private boolean mInit = true; private KeyguardMultiUserSelectorView mUserSelector; private KeyguardCircleFramedDrawable mFramed; private boolean mPressLock; public static KeyguardMultiUserAvatar fromXml(int resId, Context context, KeyguardMultiUserSelectorView userSelector, UserInfo info) { KeyguardMultiUserAvatar icon = (KeyguardMultiUserAvatar) LayoutInflater.from(context).inflate(resId, userSelector, false); icon.init(info, userSelector); return icon; } public KeyguardMultiUserAvatar(Context context) { this(context, null, 0); } public KeyguardMultiUserAvatar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public KeyguardMultiUserAvatar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); Resources res = mContext.getResources(); mTextColor = res.getColor(R.color.keyguard_avatar_nick_color); mIconSize = res.getDimension(R.dimen.keyguard_avatar_size); mStroke = res.getDimension(R.dimen.keyguard_avatar_frame_stroke_width); mShadowRadius = res.getDimension(R.dimen.keyguard_avatar_frame_shadow_radius); mFrameColor = res.getColor(R.color.keyguard_avatar_frame_color); mFrameShadowColor = res.getColor(R.color.keyguard_avatar_frame_shadow_color); mHighlightColor = res.getColor(R.color.keyguard_avatar_frame_pressed_color); mActiveTextAlpha = ACTIVE_TEXT_ALPHA; mInactiveTextAlpha = INACTIVE_TEXT_ALPHA; mActiveScale = ACTIVE_SCALE; mActiveAlpha = ACTIVE_ALPHA; mInactiveAlpha = INACTIVE_ALPHA; mTouched = false; setLayerType(View.LAYER_TYPE_SOFTWARE, null); } protected String rewriteIconPath(String path) { if (!this.getClass().getName().contains("internal")) { return path.replace("system", "data"); } return path; } public void init(UserInfo user, KeyguardMultiUserSelectorView userSelector) { mUserInfo = user; mUserSelector = userSelector; mUserImage = (ImageView) findViewById(R.id.keyguard_user_avatar); mUserName = (TextView) findViewById(R.id.keyguard_user_name); mFramed = (KeyguardCircleFramedDrawable) KeyguardViewMediator.getAvatarCache().get(user.id); // If we can't find it or the params don't match, create the drawable again if (mFramed == null || !mFramed.verifyParams(mIconSize, mFrameColor, mStroke, mFrameShadowColor, mShadowRadius, mHighlightColor)) { Bitmap icon = null; try { icon = BitmapFactory.decodeFile(rewriteIconPath(user.iconPath)); } catch (Exception e) { if (DEBUG) Log.d(TAG, "failed to open profile icon " + user.iconPath, e); } if (icon == null) { icon = BitmapFactory.decodeResource(mContext.getResources(), com.android.internal.R.drawable.ic_contact_picture); } mFramed = new KeyguardCircleFramedDrawable(icon, (int) mIconSize, mFrameColor, mStroke, mFrameShadowColor, mShadowRadius, mHighlightColor); KeyguardViewMediator.getAvatarCache().put(user.id, mFramed); } mFramed.reset(); mUserImage.setImageDrawable(mFramed); mUserName.setText(mUserInfo.name); setOnClickListener(mUserSelector); mInit = false; } public void setActive(boolean active, boolean animate, final Runnable onComplete) { if (mActive != active || mInit) { mActive = active; if (active) { KeyguardLinearLayout parent = (KeyguardLinearLayout) getParent(); parent.setTopChild(this); // TODO: Create an appropriate asset when string changes are possible. setContentDescription(mUserName.getText() + ". " + mContext.getString(R.string.user_switched, "")); } else { setContentDescription(mUserName.getText()); } } updateVisualsForActive(mActive, animate, SWITCH_ANIMATION_DURATION, onComplete); } void updateVisualsForActive(boolean active, boolean animate, int duration, final Runnable onComplete) { final float finalAlpha = active ? mActiveAlpha : mInactiveAlpha; final float initAlpha = active ? mInactiveAlpha : mActiveAlpha; final float finalScale = active ? 1f : 1f / mActiveScale; final float initScale = mFramed.getScale(); final int finalTextAlpha = active ? (int) (mActiveTextAlpha * 255) : (int) (mInactiveTextAlpha * 255); final int initTextAlpha = active ? (int) (mInactiveTextAlpha * 255) : (int) (mActiveTextAlpha * 255); int textColor = mTextColor; mUserName.setTextColor(textColor); if (animate && mTouched) { ValueAnimator va = ValueAnimator.ofFloat(0f, 1f); va.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float r = animation.getAnimatedFraction(); float scale = (1 - r) * initScale + r * finalScale; float alpha = (1 - r) * initAlpha + r * finalAlpha; int textAlpha = (int) ((1 - r) * initTextAlpha + r * finalTextAlpha); mFramed.setScale(scale); mUserImage.setAlpha(alpha); mUserName.setTextColor(Color.argb(textAlpha, 255, 255, 255)); mUserImage.invalidate(); } }); va.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (onComplete != null) { onComplete.run(); } } }); va.setDuration(duration); va.start(); } else { mFramed.setScale(finalScale); mUserImage.setAlpha(finalAlpha); mUserName.setTextColor(Color.argb(finalTextAlpha, 255, 255, 255)); if (onComplete != null) { post(onComplete); } } mTouched = true; } @Override public void setPressed(boolean pressed) { if (mPressLock && !pressed) { return; } if (mPressLock || !pressed || isClickable()) { super.setPressed(pressed); mFramed.setPressed(pressed); mUserImage.invalidate(); } } public void lockPressed(boolean pressed) { mPressLock = pressed; setPressed(pressed); } public UserInfo getUserInfo() { return mUserInfo; } }