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:
@@ -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
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user