1 /* 2 * Copyright (C) 2021 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.systemui.statusbar.policy; 18 19 import android.content.Context; 20 import android.util.AttributeSet; 21 import android.util.Log; 22 import android.view.View; 23 24 import com.android.keyguard.AlphaOptimizedLinearLayout; 25 import com.android.keyguard.KeyguardConstants; 26 import com.android.settingslib.animation.AppearAnimationUtils; 27 import com.android.settingslib.animation.DisappearAnimationUtils; 28 import com.android.systemui.animation.Interpolators; 29 30 /** 31 * The container for the user switcher on Keyguard. 32 */ 33 public class KeyguardUserSwitcherListView extends AlphaOptimizedLinearLayout { 34 35 private static final String TAG = "KeyguardUserSwitcherListView"; 36 private static final boolean DEBUG = KeyguardConstants.DEBUG; 37 38 private boolean mAnimating; 39 private final AppearAnimationUtils mAppearAnimationUtils; 40 private final DisappearAnimationUtils mDisappearAnimationUtils; 41 KeyguardUserSwitcherListView(Context context, AttributeSet attrs)42 public KeyguardUserSwitcherListView(Context context, AttributeSet attrs) { 43 super(context, attrs); 44 mAppearAnimationUtils = new AppearAnimationUtils(context, 45 AppearAnimationUtils.DEFAULT_APPEAR_DURATION, 46 -0.5f /* translationScaleFactor */, 47 0.5f /* delayScaleFactor */, 48 Interpolators.FAST_OUT_SLOW_IN); 49 mDisappearAnimationUtils = new DisappearAnimationUtils(context, 50 AppearAnimationUtils.DEFAULT_APPEAR_DURATION, 51 0.2f /* translationScaleFactor */, 52 0.2f /* delayScaleFactor */, 53 Interpolators.FAST_OUT_SLOW_IN_REVERSE); 54 } 55 56 /** 57 * Set the amount (ratio) that the device has transitioned to doze. 58 * 59 * @param darkAmount Amount of transition to doze: 1f for doze and 0f for awake. 60 */ setDarkAmount(float darkAmount)61 void setDarkAmount(float darkAmount) { 62 int childCount = getChildCount(); 63 for (int i = 0; i < childCount; i++) { 64 View v = getChildAt(i); 65 if (v instanceof KeyguardUserDetailItemView) { 66 ((KeyguardUserDetailItemView) v).setDarkAmount(darkAmount); 67 } 68 } 69 } 70 isAnimating()71 boolean isAnimating() { 72 return mAnimating; 73 } 74 75 /** 76 * Update visibilities of this view and child views for when the user list is open or closed. 77 * If closed, this hides everything but the first item (which is always the current user). 78 */ updateVisibilities(boolean open, boolean animate)79 void updateVisibilities(boolean open, boolean animate) { 80 if (DEBUG) { 81 Log.d(TAG, String.format("updateVisibilities: open=%b animate=%b childCount=%d", 82 open, animate, getChildCount())); 83 } 84 85 mAnimating = false; 86 87 int childCount = getChildCount(); 88 KeyguardUserDetailItemView[] userItemViews = new KeyguardUserDetailItemView[childCount]; 89 for (int i = 0; i < childCount; i++) { 90 userItemViews[i] = (KeyguardUserDetailItemView) getChildAt(i); 91 userItemViews[i].clearAnimation(); 92 if (i == 0) { 93 // The first child is always the current user. 94 userItemViews[i].updateVisibilities(true /* showItem */, open /* showTextName */, 95 animate); 96 userItemViews[i].setClickable(true); 97 } else { 98 // Update clickable state immediately so that the menu feels more responsive 99 userItemViews[i].setClickable(open); 100 // Before running the animation, ensure visibility is set correctly 101 userItemViews[i].updateVisibilities(animate || open /* showItem */, 102 true /* showTextName */, false /* animate */); 103 } 104 } 105 106 if (animate) { 107 // AnimationUtils will immediately hide/show the first item in the array. Since the 108 // first view is the current user, we want to manage its visibility separately. 109 // Set first item to null so AnimationUtils ignores it. 110 userItemViews[0] = null; 111 112 setClipChildren(false); 113 setClipToPadding(false); 114 mAnimating = true; 115 (open ? mAppearAnimationUtils : mDisappearAnimationUtils) 116 .startAnimation(userItemViews, () -> { 117 setClipChildren(true); 118 setClipToPadding(true); 119 mAnimating = false; 120 }); 121 } 122 } 123 124 /** 125 * Replaces the view at the specified position in the group. 126 * 127 * @param index the position in the group of the view to remove 128 */ replaceView(KeyguardUserDetailItemView newView, int index)129 void replaceView(KeyguardUserDetailItemView newView, int index) { 130 removeViewAt(index); 131 addView(newView, index); 132 } 133 134 /** 135 * Removes the last view in the group. 136 */ removeLastView()137 void removeLastView() { 138 int lastIndex = getChildCount() - 1; 139 removeViewAt(lastIndex); 140 } 141 } 142