/* * Copyright (C) 2014 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.systemui.statusbar.policy; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; import android.database.DataSetObserver; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewStub; import android.view.animation.AnimationUtils; import android.widget.TextView; import com.android.keyguard.AppearAnimationUtils; import com.android.systemui.R; import com.android.systemui.qs.tiles.UserDetailItemView; import com.android.systemui.statusbar.phone.KeyguardStatusBarView; import com.android.systemui.statusbar.phone.NotificationPanelView; import com.android.systemui.statusbar.phone.PhoneStatusBar; import com.android.systemui.statusbar.phone.StatusBarHeaderView; import com.android.systemui.statusbar.phone.UserAvatarView; /** * Manages the user switcher on the Keyguard. */ public class KeyguardUserSwitcher { private static final String TAG = "KeyguardUserSwitcher"; private static final boolean ALWAYS_ON = false; private final ViewGroup mUserSwitcher; private final KeyguardStatusBarView mStatusBarView; private final Adapter mAdapter; private final AppearAnimationUtils mAppearAnimationUtils; private final KeyguardUserSwitcherScrim mBackground; private ObjectAnimator mBgAnimator; private UserSwitcherController mUserSwitcherController; public KeyguardUserSwitcher(Context context, ViewStub userSwitcher, KeyguardStatusBarView statusBarView, NotificationPanelView panelView, UserSwitcherController userSwitcherController) { if (context.getResources().getBoolean(R.bool.config_keyguardUserSwitcher) || ALWAYS_ON) { mUserSwitcher = (ViewGroup) userSwitcher.inflate(); mBackground = new KeyguardUserSwitcherScrim(mUserSwitcher); mUserSwitcher.setBackground(mBackground); mStatusBarView = statusBarView; mStatusBarView.setKeyguardUserSwitcher(this); panelView.setKeyguardUserSwitcher(this); mAdapter = new Adapter(context, userSwitcherController); mAdapter.registerDataSetObserver(mDataSetObserver); mUserSwitcherController = userSwitcherController; mAppearAnimationUtils = new AppearAnimationUtils(context, 400, -0.5f, 0.5f, AnimationUtils.loadInterpolator( context, android.R.interpolator.fast_out_slow_in)); } else { mUserSwitcher = null; mStatusBarView = null; mAdapter = null; mAppearAnimationUtils = null; mBackground = null; } } public void setKeyguard(boolean keyguard, boolean animate) { if (mUserSwitcher != null) { if (keyguard && shouldExpandByDefault()) { show(animate); } else { hide(animate); } } } /** * @return true if the user switcher should be expanded by default on the lock screen. * @see android.os.UserManager#isUserSwitcherEnabled() */ private boolean shouldExpandByDefault() { return (mUserSwitcherController != null) && mUserSwitcherController.isSimpleUserSwitcher(); } public void show(boolean animate) { if (mUserSwitcher != null && mUserSwitcher.getVisibility() != View.VISIBLE) { cancelAnimations(); mUserSwitcher.setVisibility(View.VISIBLE); mStatusBarView.setKeyguardUserSwitcherShowing(true, animate); if (animate) { startAppearAnimation(); } } } public void hide(boolean animate) { if (mUserSwitcher != null && mUserSwitcher.getVisibility() == View.VISIBLE) { cancelAnimations(); if (animate) { startDisappearAnimation(); } else { mUserSwitcher.setVisibility(View.GONE); } mStatusBarView.setKeyguardUserSwitcherShowing(false, animate); } } private void cancelAnimations() { int count = mUserSwitcher.getChildCount(); for (int i = 0; i < count; i++) { mUserSwitcher.getChildAt(i).animate().cancel(); } if (mBgAnimator != null) { mBgAnimator.cancel(); } mUserSwitcher.animate().cancel(); } private void startAppearAnimation() { int count = mUserSwitcher.getChildCount(); View[] objects = new View[count]; for (int i = 0; i < count; i++) { objects[i] = mUserSwitcher.getChildAt(i); } mUserSwitcher.setClipChildren(false); mUserSwitcher.setClipToPadding(false); mAppearAnimationUtils.startAppearAnimation(objects, new Runnable() { @Override public void run() { mUserSwitcher.setClipChildren(true); mUserSwitcher.setClipToPadding(true); } }); mBgAnimator = ObjectAnimator.ofInt(mBackground, "alpha", 0, 255); mBgAnimator.setDuration(400); mBgAnimator.setInterpolator(PhoneStatusBar.ALPHA_IN); mBgAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mBgAnimator = null; } }); mBgAnimator.start(); } private void startDisappearAnimation() { mUserSwitcher.animate() .alpha(0f) .setDuration(300) .setInterpolator(PhoneStatusBar.ALPHA_OUT) .withEndAction(new Runnable() { @Override public void run() { mUserSwitcher.setVisibility(View.GONE); mUserSwitcher.setAlpha(1f); } }); } private void refresh() { final int childCount = mUserSwitcher.getChildCount(); final int adapterCount = mAdapter.getCount(); final int N = Math.max(childCount, adapterCount); for (int i = 0; i < N; i++) { if (i < adapterCount) { View oldView = null; if (i < childCount) { oldView = mUserSwitcher.getChildAt(i); } View newView = mAdapter.getView(i, oldView, mUserSwitcher); if (oldView == null) { // We ran out of existing views. Add it at the end. mUserSwitcher.addView(newView); } else if (oldView != newView) { // We couldn't rebind the view. Replace it. mUserSwitcher.removeViewAt(i); mUserSwitcher.addView(newView, i); } } else { int lastIndex = mUserSwitcher.getChildCount() - 1; mUserSwitcher.removeViewAt(lastIndex); } } } public final DataSetObserver mDataSetObserver = new DataSetObserver() { @Override public void onChanged() { refresh(); } }; public static class Adapter extends UserSwitcherController.BaseUserAdapter implements View.OnClickListener { private Context mContext; public Adapter(Context context, UserSwitcherController controller) { super(controller); mContext = context; } @Override public View getView(int position, View convertView, ViewGroup parent) { UserSwitcherController.UserRecord item = getItem(position); if (!(convertView instanceof UserDetailItemView) || !(convertView.getTag() instanceof UserSwitcherController.UserRecord)) { convertView = LayoutInflater.from(mContext).inflate( R.layout.keyguard_user_switcher_item, parent, false); convertView.setOnClickListener(this); } UserDetailItemView v = (UserDetailItemView) convertView; String name = getName(mContext, item); if (item.picture == null) { v.bind(name, getDrawable(mContext, item)); } else { v.bind(name, item.picture); } convertView.setActivated(item.isCurrent); convertView.setTag(item); return convertView; } @Override public void onClick(View v) { switchTo(((UserSwitcherController.UserRecord)v.getTag())); } } }