Multi-user bouncer tweaks

Updates to layout and spacing to match latest UX. Highlight the
selected item in the drop down list.

Bug: 206826027
Test: atest KeyguardSecurityContainerControllerTest KeyguardSecurityContainerTest

Change-Id: I09f372a596eb5ce0b1e5ad701c370ca4ebe3a4b6
This commit is contained in:
Matt Pietal
2021-12-21 09:28:03 -05:00
parent d9340d5854
commit db74c47f5c
9 changed files with 175 additions and 64 deletions

View File

@@ -17,14 +17,14 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:paddingMode="stack"
android:paddingStart="44dp"
android:paddingStart="24dp"
android:paddingEnd="44dp"
android:paddingLeft="0dp"
android:paddingRight="0dp">
<item>
<shape android:shape="rectangle">
<solid android:color="?androidprv:attr/colorSurface" />
<corners android:radius="@dimen/keyguard_user_switcher_corner" />
<corners android:radius="32dp" />
</shape>
</item>
<item

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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.
-->
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<solid android:color="?androidprv:attr/colorAccentPrimary" />
<corners android:radius="24dp" />
</shape>

View File

@@ -18,5 +18,5 @@
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle">
<solid android:color="?androidprv:attr/colorSurface" />
<corners android:radius="@dimen/keyguard_user_switcher_popup_corner" />
<corners android:radius="28dp" />
</shape>

View File

@@ -30,8 +30,8 @@
<ImageView
android:id="@+id/user_icon"
android:layout_width="@dimen/keyguard_user_switcher_icon_size"
android:layout_height="@dimen/keyguard_user_switcher_icon_size" />
android:layout_width="@dimen/bouncer_user_switcher_icon_size"
android:layout_height="@dimen/bouncer_user_switcher_icon_size" />
<!-- need to keep this outer view in order to have a correctly sized anchor
for the dropdown menu, as well as dropdown background in the right place -->
@@ -40,13 +40,12 @@
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginTop="30dp"
android:minHeight="48dp">
android:layout_marginTop="30dp">
<TextView
style="@style/Keyguard.UserSwitcher.Spinner.Header"
style="@style/Bouncer.UserSwitcher.Spinner.Header"
android:clickable="false"
android:id="@+id/user_switcher_header"
android:layout_width="@dimen/keyguard_user_switcher_width"
android:layout_width="@dimen/bouncer_user_switcher_width"
android:layout_height="wrap_content" />
</LinearLayout>>

View File

@@ -13,13 +13,14 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<TextView
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/Keyguard.UserSwitcher.Spinner.Item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:paddingStart="@dimen/control_menu_horizontal_padding"
android:paddingEnd="@dimen/control_menu_horizontal_padding"
android:textDirection="locale"/>
android:layout_height="wrap_content">
<TextView
style="@style/Bouncer.UserSwitcher.Spinner.Item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp" />
</FrameLayout>

View File

@@ -108,11 +108,15 @@
<dimen name="one_handed_bouncer_move_animation_translation">120dp</dimen>
<dimen name="keyguard_user_switcher_header_text_size">32sp</dimen>
<dimen name="keyguard_user_switcher_item_text_size">32sp</dimen>
<dimen name="keyguard_user_switcher_width">320dp</dimen>
<dimen name="keyguard_user_switcher_icon_size">310dp</dimen>
<dimen name="keyguard_user_switcher_corner">32dp</dimen>
<dimen name="keyguard_user_switcher_popup_corner">24dp</dimen>
<dimen name="keyguard_user_switcher_item_padding_vertical">15dp</dimen>
<dimen name="bouncer_user_switcher_header_text_size">20sp</dimen>
<dimen name="bouncer_user_switcher_item_text_size">20sp</dimen>
<dimen name="bouncer_user_switcher_item_line_height">24sp</dimen>
<dimen name="bouncer_user_switcher_item_icon_size">28dp</dimen>
<dimen name="bouncer_user_switcher_item_icon_padding">12dp</dimen>
<dimen name="bouncer_user_switcher_width">248dp</dimen>
<dimen name="bouncer_user_switcher_icon_size">190dp</dimen>
<dimen name="bouncer_user_switcher_popup_header_height">12dp</dimen>
<dimen name="bouncer_user_switcher_popup_divider_height">4dp</dimen>
<dimen name="bouncer_user_switcher_item_padding_vertical">10dp</dimen>
<dimen name="bouncer_user_switcher_item_padding_horizontal">12dp</dimen>
</resources>

View File

@@ -141,22 +141,23 @@
<item name="android:shadowRadius">0</item>
</style>
<style name="Keyguard.UserSwitcher.Spinner" parent="@android:style/Widget.DeviceDefault.TextView">
<style name="Bouncer.UserSwitcher.Spinner" parent="@android:style/Widget.DeviceDefault.TextView">
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
<item name="android:singleLine">true</item>
<item name="android:ellipsize">end</item>
<item name="android:paddingTop">@dimen/keyguard_user_switcher_item_padding_vertical</item>
<item name="android:paddingBottom">@dimen/keyguard_user_switcher_item_padding_vertical</item>
<item name="android:minHeight">48dp</item>
<item name="android:paddingVertical">@dimen/bouncer_user_switcher_item_padding_vertical</item>
<item name="android:paddingHorizontal">@dimen/bouncer_user_switcher_item_padding_horizontal</item>
<item name="android:lineHeight">@dimen/bouncer_user_switcher_item_line_height</item>
<item name="android:gravity">start|center_vertical</item>
</style>
<style name="Keyguard.UserSwitcher.Spinner.Header">
<item name="android:background">@drawable/keyguard_user_switcher_header_bg</item>
<item name="android:textSize">@dimen/keyguard_user_switcher_header_text_size</item>
<style name="Bouncer.UserSwitcher.Spinner.Header">
<item name="android:background">@drawable/bouncer_user_switcher_header_bg</item>
<item name="android:textSize">@dimen/bouncer_user_switcher_header_text_size</item>
</style>
<style name="Keyguard.UserSwitcher.Spinner.Item">
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:textSize">@dimen/keyguard_user_switcher_item_text_size</item>
<style name="Bouncer.UserSwitcher.Spinner.Item">
<item name="android:textSize">@dimen/bouncer_user_switcher_item_text_size</item>
</style>
</resources>

View File

@@ -32,9 +32,14 @@ import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BlendMode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.UserManager;
import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
@@ -70,6 +75,7 @@ import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.UserIcons;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.settingslib.Utils;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
@@ -760,11 +766,11 @@ public class KeyguardSecurityContainer extends FrameLayout {
private ViewGroup mView;
private ViewGroup mUserSwitcherViewGroup;
private KeyguardSecurityViewFlipper mViewFlipper;
private ImageView mUserIconView;
private TextView mUserSwitcher;
private FalsingManager mFalsingManager;
private UserSwitcherController mUserSwitcherController;
private KeyguardUserSwitcherPopupMenu mPopup;
private Resources mResources;
@Override
public void init(@NonNull ViewGroup v, @NonNull GlobalSettings globalSettings,
@@ -775,6 +781,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
mViewFlipper = viewFlipper;
mFalsingManager = falsingManager;
mUserSwitcherController = userSwitcherController;
mResources = v.getContext().getResources();
if (mUserSwitcherViewGroup == null) {
LayoutInflater.from(v.getContext()).inflate(
@@ -784,9 +791,8 @@ public class KeyguardSecurityContainer extends FrameLayout {
mUserSwitcherViewGroup = mView.findViewById(R.id.keyguard_bouncer_user_switcher);
}
mUserIconView = mView.findViewById(R.id.user_icon);
Drawable icon = UserIcons.getDefaultUserIcon(v.getContext().getResources(), 0, false);
mUserIconView.setImageDrawable(icon);
Drawable userIcon = findUserIcon(KeyguardUpdateMonitor.getCurrentUser());
((ImageView) mView.findViewById(R.id.user_icon)).setImageDrawable(userIcon);
updateSecurityViewLocation();
@@ -802,6 +808,14 @@ public class KeyguardSecurityContainer extends FrameLayout {
}
}
private Drawable findUserIcon(int userId) {
Bitmap userIcon = UserManager.get(mView.getContext()).getUserIcon(userId);
if (userIcon != null) {
return new BitmapDrawable(userIcon);
}
return UserIcons.getDefaultUserIcon(mResources, userId, false);
}
@Override
public void startAppearAnimation(SecurityMode securityMode) {
// IME insets animations handle alpha and translation
@@ -824,8 +838,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
return;
}
int yTranslation = mView.getContext().getResources().getDimensionPixelSize(
R.dimen.disappear_y_translation);
int yTranslation = mResources.getDimensionPixelSize(R.dimen.disappear_y_translation);
AnimatorSet anims = new AnimatorSet();
ObjectAnimator yAnim = ObjectAnimator.ofFloat(mView, View.TRANSLATION_Y, yTranslation);
@@ -840,21 +853,70 @@ public class KeyguardSecurityContainer extends FrameLayout {
String currentUserName = mUserSwitcherController.getCurrentUserName();
mUserSwitcher.setText(currentUserName);
final UserRecord currentUser = getCurrentUser();
ViewGroup anchor = mView.findViewById(R.id.user_switcher_anchor);
BaseUserAdapter adapter = new BaseUserAdapter(mUserSwitcherController) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
UserRecord item = getItem(position);
TextView view = (TextView) convertView;
FrameLayout view = (FrameLayout) convertView;
if (view == null) {
view = (TextView) LayoutInflater.from(parent.getContext()).inflate(
view = (FrameLayout) LayoutInflater.from(parent.getContext()).inflate(
R.layout.keyguard_bouncer_user_switcher_item,
parent,
false);
}
view.setText(getName(parent.getContext(), item));
TextView textView = (TextView) view.getChildAt(0);
textView.setText(getName(parent.getContext(), item));
Drawable icon = null;
if (item.picture != null) {
icon = new BitmapDrawable(item.picture);
} else {
icon = getDrawable(item, view.getContext());
}
int iconSize = view.getResources().getDimensionPixelSize(
R.dimen.bouncer_user_switcher_item_icon_size);
int iconPadding = view.getResources().getDimensionPixelSize(
R.dimen.bouncer_user_switcher_item_icon_padding);
icon.setBounds(0, 0, iconSize, iconSize);
textView.setCompoundDrawablePadding(iconPadding);
textView.setCompoundDrawablesRelative(icon, null, null, null);
if (item == currentUser) {
textView.setBackground(view.getContext().getDrawable(
R.drawable.bouncer_user_switcher_item_selected_bg));
} else {
textView.setBackground(null);
}
return view;
}
private Drawable getDrawable(UserRecord item, Context context) {
Drawable drawable;
if (item.isCurrent && item.isGuest) {
drawable = context.getDrawable(R.drawable.ic_avatar_guest_user);
} else {
drawable = getIconDrawable(context, item);
}
int iconColor;
if (item.isSwitchToEnabled) {
iconColor = Utils.getColorAttrDefaultColor(context,
com.android.internal.R.attr.colorAccentPrimaryVariant);
} else {
iconColor = context.getResources().getColor(
R.color.kg_user_switcher_restricted_avatar_icon_color,
context.getTheme());
}
drawable.setTint(iconColor);
Drawable bg = context.getDrawable(R.drawable.kg_bg_avatar);
bg.setTintBlendMode(BlendMode.DST);
bg.setTint(Utils.getColorAttrDefaultColor(context,
com.android.internal.R.attr.colorSurfaceVariant));
drawable = new LayerDrawable(new Drawable[]{bg, drawable});
return drawable;
}
};
if (adapter.getCount() < 2) {
@@ -876,7 +938,8 @@ public class KeyguardSecurityContainer extends FrameLayout {
public void onItemClick(AdapterView parent, View view, int pos, long id) {
if (mFalsingManager.isFalseTap(LOW_PENALTY)) return;
UserRecord user = adapter.getItem(pos);
// Subtract one for the header
UserRecord user = adapter.getItem(pos - 1);
if (!user.isCurrent) {
adapter.onUserListItemClicked(user);
}
@@ -888,6 +951,16 @@ public class KeyguardSecurityContainer extends FrameLayout {
});
}
private UserRecord getCurrentUser() {
for (int i = 0; i < mUserSwitcherController.getUsers().size(); ++i) {
UserRecord userRecord = mUserSwitcherController.getUsers().get(i);
if (userRecord.isCurrent) {
return userRecord;
}
}
return null;
}
/**
* Each view will get half the width. Yes, it would be easier to use something other than
* FrameLayout but it was too disruptive to downstream projects to change.
@@ -901,8 +974,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
@Override
public void updateSecurityViewLocation() {
if (mView.getContext().getResources().getConfiguration().orientation
== Configuration.ORIENTATION_PORTRAIT) {
if (mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
updateViewGravity(mViewFlipper, Gravity.CENTER_HORIZONTAL);
updateViewGravity(mUserSwitcherViewGroup, Gravity.CENTER_HORIZONTAL);
mUserSwitcherViewGroup.setTranslationY(0);
@@ -912,8 +984,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
// Attempt to reposition a bit higher to make up for this frame being a bit lower
// on the device
int yTrans = mView.getContext().getResources().getDimensionPixelSize(
R.dimen.status_bar_height);
int yTrans = mResources.getDimensionPixelSize(R.dimen.status_bar_height);
mUserSwitcherViewGroup.setTranslationY(-yTrans);
}
}

View File

@@ -18,6 +18,8 @@ package com.android.keyguard;
import android.annotation.NonNull;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.drawable.ShapeDrawable;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListPopupWindow;
@@ -32,15 +34,6 @@ import com.android.systemui.plugins.FalsingManager;
public class KeyguardUserSwitcherPopupMenu extends ListPopupWindow {
private Context mContext;
private FalsingManager mFalsingManager;
private int mLastHeight = -1;
private View.OnLayoutChangeListener mLayoutListener = (v, l, t, r, b, ol, ot, or, ob) -> {
int height = -v.getMeasuredHeight() + getAnchorView().getHeight();
if (height != mLastHeight) {
mLastHeight = height;
setVerticalOffset(height);
KeyguardUserSwitcherPopupMenu.super.show();
}
};
public KeyguardUserSwitcherPopupMenu(@NonNull Context context,
@NonNull FalsingManager falsingManager) {
@@ -49,7 +42,7 @@ public class KeyguardUserSwitcherPopupMenu extends ListPopupWindow {
mFalsingManager = falsingManager;
Resources res = mContext.getResources();
setBackgroundDrawable(
res.getDrawable(R.drawable.keyguard_user_switcher_popup_bg, context.getTheme()));
res.getDrawable(R.drawable.bouncer_user_switcher_popup_bg, context.getTheme()));
setModal(true);
setOverlapAnchor(true);
}
@@ -63,8 +56,20 @@ public class KeyguardUserSwitcherPopupMenu extends ListPopupWindow {
super.show();
ListView listView = getListView();
// This will force the popupwindow to show upward instead of drop down
listView.addOnLayoutChangeListener(mLayoutListener);
listView.setVerticalScrollBarEnabled(false);
listView.setHorizontalScrollBarEnabled(false);
// Creates a transparent spacer between items
ShapeDrawable shape = new ShapeDrawable();
shape.setAlpha(0);
listView.setDivider(shape);
listView.setDividerHeight(mContext.getResources().getDimensionPixelSize(
R.dimen.bouncer_user_switcher_popup_divider_height));
int height = mContext.getResources().getDimensionPixelSize(
R.dimen.bouncer_user_switcher_popup_header_height);
listView.addHeaderView(createSpacer(height), null, false);
listView.addFooterView(createSpacer(height), null, false);
listView.setOnTouchListener((v, ev) -> {
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
@@ -72,11 +77,19 @@ public class KeyguardUserSwitcherPopupMenu extends ListPopupWindow {
}
return false;
});
super.show();
}
@Override
public void dismiss() {
getListView().removeOnLayoutChangeListener(mLayoutListener);
super.dismiss();
private View createSpacer(int height) {
return new View(mContext) {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(1, height);
}
@Override
public void draw(Canvas canvas) {
}
};
}
}