Refactored the UserRecyclerGridView to use PagedListView from the
car support library. This also surfaced a scrollbar.
Additionally, added a touch ripple when you touch a
user's picture and disabled the user buttons once a profile is
selected
Test: tested on Mojave
bug: 77870748, 77869522, 77870549
Change-Id: I3706f1089c7c91e8db8d9126a269fd984e2b5dc9
diff --git a/packages/SystemUI/res/drawable/car_progress_bar.xml b/packages/SystemUI/res/drawable/car_progress_bar.xml
deleted file mode 100644
index 742fca7..0000000
--- a/packages/SystemUI/res/drawable/car_progress_bar.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
- Copyright (C) 2017 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
--->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@android:id/background">
- <shape>
- <solid android:color="@color/car_user_switcher_progress_bgcolor" />
- </shape>
- </item>
-
- <item android:id="@android:id/progress">
- <clip>
- <shape>
- <solid android:color="@color/car_user_switcher_progress_fgcolor" />
- </shape>
- </clip>
- </item>
-</layer-list>
diff --git a/packages/SystemUI/res/drawable/car_round_button.xml b/packages/SystemUI/res/drawable/car_round_button.xml
deleted file mode 100644
index 5f4deb3..0000000
--- a/packages/SystemUI/res/drawable/car_round_button.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<!--
- Copyright (C) 2017 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 xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
-
- <solid android:color="@color/car_start_driving_background" />
- <corners android:radius="@dimen/car_start_driving_corner_radius" />
-</shape>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
index c59b067..3242165 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
@@ -22,14 +22,13 @@
android:alpha="0"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:gravity="fill_horizontal"
- android:layout_marginTop="@dimen/car_padding_5"
- android:layout_marginStart="@dimen/car_padding_4">
+ android:gravity="fill_horizontal">
<ImageView android:id="@+id/user_avatar"
android:layout_centerHorizontal="true"
android:layout_width="@dimen/car_fullscreen_user_pod_image_avatar_width"
android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height"
+ android:background="@drawable/car_button_ripple_background_inverse"
/>
<TextView android:id="@+id/user_name"
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
index 27d0e46..d8b52fc 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -31,34 +32,19 @@
android:theme="@android:style/Theme"
android:layout_alignParentTop="true"/>
- <RelativeLayout
- android:id="@+id/fullscreen_user_switcher_container"
- android:layout_width="match_parent"
+ <!-- TODO: add app:verticallyCenterListContent="true" when car support lib is updated -->
+ <com.android.systemui.statusbar.car.UserGridRecyclerView
+ android:id="@+id/user_grid"
+ android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_marginStart="@dimen/car_margin"
- android:layout_marginEnd="@dimen/car_margin">
-
- <RelativeLayout
- android:id="@+id/fullscreen_user_switcher_container_inner"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/car_padding_4">
-
- <com.android.systemui.statusbar.car.UserGridRecyclerView
- android:id="@+id/user_grid"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/header"
- android:scrollbars="vertical"
- android:scrollbarFadeDuration="0"
- android:verticalScrollbarPosition="left"
- android:layout_centerHorizontal="true"
- android:layout_centerVertical="true"
- android:layout_alignParentRight="true"/>
-
- </RelativeLayout>
-
- </RelativeLayout>
+ android:layout_below="@+id/header"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:layout_alignParentRight="true"
+ app:dayNightStyle="force_night"
+ app:showPagedListViewDivider="false"
+ app:gutter="both"
+ app:itemSpacing="@dimen/car_padding_5"/>
</RelativeLayout>
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/car_qs_panel.xml b/packages/SystemUI/res/layout/car_qs_panel.xml
index c01bbce..9c2b95b 100644
--- a/packages/SystemUI/res/layout/car_qs_panel.xml
+++ b/packages/SystemUI/res/layout/car_qs_panel.xml
@@ -29,6 +29,7 @@
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/user_switcher_container"
android:layout_marginStart="@dimen/car_margin"
android:layout_marginEnd="@dimen/car_margin"
@@ -36,23 +37,17 @@
android:layout_width="match_parent"
android:layout_height="@dimen/car_user_switcher_container_height">
- <RelativeLayout
- android:id="@+id/fullscreen_user_switcher_container_inner"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/car_padding_4">
-
- <com.android.systemui.statusbar.car.UserGridRecyclerView
- android:id="@+id/user_grid"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scrollbars="vertical"
- android:verticalScrollbarPosition="left"
- android:layout_centerHorizontal="true"
- android:layout_centerVertical="true"
- android:layout_alignParentRight="true"
- android:scrollbarFadeDuration="0"/>
- </RelativeLayout>
+ <com.android.systemui.statusbar.car.UserGridRecyclerView
+ android:id="@+id/user_grid"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:layout_alignParentRight="true"
+ app:dayNightStyle="force_night"
+ app:showPagedListViewDivider="false"
+ app:gutter="both"
+ app:itemSpacing="@dimen/car_padding_4"/>
</RelativeLayout>
diff --git a/packages/SystemUI/res/values/dimens_car.xml b/packages/SystemUI/res/values/dimens_car.xml
index 0cd3825..6bc8e26 100644
--- a/packages/SystemUI/res/values/dimens_car.xml
+++ b/packages/SystemUI/res/values/dimens_car.xml
@@ -16,9 +16,6 @@
*/
-->
<resources>
- <dimen name="car_margin">148dp</dimen>
- <dimen name="car_margin_standard">112dp</dimen>
-
<!-- TODO replace with car support lib sizes when available -->
<dimen name="car_fullscreen_user_pod_icon_text_size">64sp</dimen>
<dimen name="car_fullscreen_user_pod_width">243dp</dimen>
@@ -31,14 +28,6 @@
<dimen name="car_left_navigation_bar_width">96dp</dimen>
<dimen name="car_right_navigation_bar_width">96dp</dimen>
- <dimen name="car_page_indicator_dot_diameter">12dp</dimen>
- <dimen name="car_page_indicator_margin_bottom">24dp</dimen>
-
- <dimen name="car_start_driving_corner_radius">16dp</dimen>
- <dimen name="car_start_driving_padding_side">30dp</dimen>
- <dimen name="car_start_driving_height">80dp</dimen>
- <dimen name="car_start_driving_text_size">@dimen/car_body2_size</dimen>
-
<dimen name="car_qs_footer_height">112dp</dimen>
<dimen name="car_qs_footer_padding_bottom">16dp</dimen>
<dimen name="car_qs_footer_padding_top">16dp</dimen>
diff --git a/packages/SystemUI/res/values/styles_car.xml b/packages/SystemUI/res/values/styles_car.xml
deleted file mode 100644
index 2aaef86..0000000
--- a/packages/SystemUI/res/values/styles_car.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (c) 2017, 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.
--->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <style name="CarUserSwitcher.StartDrivingButton" parent="@android:style/Widget.Material.Button">
- <item name="android:background">@drawable/car_round_button</item>
- <item name="android:textSize">@dimen/car_start_driving_text_size</item>
- <item name="android:textColor">@color/car_start_driving_text</item>
- <item name="android:paddingLeft">@dimen/car_start_driving_padding_side</item>
- <item name="android:paddingRight">@dimen/car_start_driving_padding_side</item>
- </style>
-</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
index da21aa5..608a236 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
@@ -75,7 +75,7 @@
mUserGridView = mUserSwitcherContainer.findViewById(R.id.user_grid);
GridLayoutManager layoutManager = new GridLayoutManager(context,
context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col));
- mUserGridView.setLayoutManager(layoutManager);
+ mUserGridView.getRecyclerView().setLayoutManager(layoutManager);
mUserGridView.buildAdapter();
mUserSwitchCallback = new UserSwitchCallback();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index c1af1fa..6cb80c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -23,7 +23,6 @@
import android.view.ViewStub;
import android.support.v7.widget.GridLayoutManager;
-import android.support.v7.widget.RecyclerView;
import com.android.settingslib.users.UserManagerHelper;
import com.android.systemui.R;
@@ -49,7 +48,7 @@
mUserGridView = mContainer.findViewById(R.id.user_grid);
GridLayoutManager layoutManager = new GridLayoutManager(context,
context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col));
- mUserGridView.setLayoutManager(layoutManager);
+ mUserGridView.getRecyclerView().setLayoutManager(layoutManager);
mUserGridView.buildAdapter();
mUserGridView.setUserSelectionListener(this::onUserSelected);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index 5006a2c..41b70f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -16,19 +16,12 @@
package com.android.systemui.statusbar.car;
-import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.UserInfo;
+import android.content.res.ColorStateList;
import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.drawable.GradientDrawable;
import android.os.AsyncTask;
-import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.RecyclerView.ViewHolder;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -36,6 +29,8 @@
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.car.widget.PagedListView;
+
import com.android.settingslib.users.UserManagerHelper;
import com.android.systemui.R;
@@ -46,7 +41,7 @@
* Displays a GridLayout with icons for the users in the system to allow switching between users.
* One of the uses of this is for the lock screen in auto.
*/
-public class UserGridRecyclerView extends RecyclerView implements
+public class UserGridRecyclerView extends PagedListView implements
UserManagerHelper.OnUsersUpdateListener {
private UserSelectionListener mUserSelectionListener;
private UserAdapter mAdapter;
@@ -55,7 +50,6 @@
public UserGridRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
- super.setHasFixedSize(true);
mContext = context;
mUserManagerHelper = new UserManagerHelper(mContext);
}
@@ -65,6 +59,7 @@
*/
@Override
public void onFinishInflate() {
+ super.onFinishInflate();
mUserManagerHelper.registerOnUsersUpdateListener(this);
}
@@ -73,6 +68,7 @@
*/
@Override
public void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
mUserManagerHelper.unregisterOnUsersUpdateListener();
}
@@ -152,8 +148,6 @@
private final Context mContext;
private List<UserRecord> mUsers;
- private final int mPodImageAvatarWidth;
- private final int mPodImageAvatarHeight;
private final Resources mRes;
private final String mGuestName;
private final String mNewUserName;
@@ -162,10 +156,6 @@
mRes = context.getResources();
mContext = context;
updateUsers(users);
- mPodImageAvatarWidth = mRes.getDimensionPixelSize(
- R.dimen.car_fullscreen_user_pod_image_avatar_width);
- mPodImageAvatarHeight = mRes.getDimensionPixelSize(
- R.dimen.car_fullscreen_user_pod_image_avatar_height);
mGuestName = mRes.getString(R.string.car_guest);
mNewUserName = mRes.getString(R.string.car_new_user);
}
@@ -190,13 +180,22 @@
@Override
public void onBindViewHolder(UserAdapterViewHolder holder, int position) {
UserRecord userRecord = mUsers.get(position);
- holder.mUserAvatarImageView.setImageBitmap(getDefaultUserIcon(userRecord));
+ if (!userRecord.mIsAddUser) {
+ holder.mUserAvatarImageView.setImageBitmap(mUserManagerHelper
+ .getUserIcon(userRecord.mInfo));
+ } else {
+ holder.mUserAvatarImageView.setImageDrawable(mContext
+ .getDrawable(R.drawable.ic_add_circle_qs));
+ }
holder.mUserNameTextView.setText(userRecord.mInfo.name);
holder.mView.setOnClickListener(v -> {
if (userRecord == null) {
return;
}
+ // Disable button so it cannot be clicked multiple times
+ holder.mView.setEnabled(false);
+
// Notify the listener which user was selected
if (mUserSelectionListener != null) {
mUserSelectionListener.onUserSelected(userRecord);
@@ -244,57 +243,6 @@
return mUsers.size();
}
- /**
- * Returns the default user icon. This icon is a circle with a letter in it. The letter is
- * the first character in the username.
- *
- * @param record the profile of the user for which the icon should be created
- */
- private Bitmap getDefaultUserIcon(UserRecord record) {
- CharSequence displayText;
- boolean isAddUserText = false;
- if (record.mIsAddUser) {
- displayText = "+";
- isAddUserText = true;
- } else {
- displayText = record.mInfo.name.subSequence(0, 1);
- }
- Bitmap out = Bitmap.createBitmap(mPodImageAvatarWidth, mPodImageAvatarHeight,
- Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(out);
-
- // Draw the circle background.
- GradientDrawable shape = new GradientDrawable();
- shape.setShape(GradientDrawable.RADIAL_GRADIENT);
- shape.setGradientRadius(1.0f);
- shape.setColor(mContext.getColor(R.color.car_grey_50));
- shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
- shape.draw(canvas);
-
- // Draw the letter in the center.
- Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- paint.setColor(mContext.getColor(R.color.car_grey_900));
- paint.setTextAlign(Align.CENTER);
- if (isAddUserText) {
- paint.setTextSize(mRes.getDimensionPixelSize(
- R.dimen.car_touch_target_size));
- } else {
- paint.setTextSize(mRes.getDimensionPixelSize(
- R.dimen.car_fullscreen_user_pod_icon_text_size));
- }
-
- Paint.FontMetricsInt metrics = paint.getFontMetricsInt();
- // The Y coordinate is measured by taking half the height of the pod, but that would
- // draw the character putting the bottom of the font in the middle of the pod. To
- // correct this, half the difference between the top and bottom distance metrics of the
- // font gives the offset of the font. Bottom is a positive value, top is negative, so
- // the different is actually a sum. The "half" operation is then factored out.
- canvas.drawText(displayText.toString(), mPodImageAvatarWidth / 2,
- (mPodImageAvatarHeight - (metrics.bottom + metrics.top)) / 2, paint);
-
- return out;
- }
-
public class UserAdapterViewHolder extends RecyclerView.ViewHolder {
public ImageView mUserAvatarImageView;
diff --git a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
index e34ee63..676f0c7 100644
--- a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
@@ -20,17 +20,16 @@
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
-import android.graphics.Canvas;
+import android.graphics.BitmapFactory;
import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.GradientDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.R;
+import com.android.server.pm.UserManagerService;
+import java.io.FileDescriptor;
/**
* Dialog to show when a user switch it about to happen for the car. The intent is to snapshot the
@@ -60,54 +59,13 @@
View view = LayoutInflater.from(getContext()).inflate(R.layout.car_user_switching_dialog,
null);
+ FileDescriptor fileDescriptor = UserManagerService.getInstance()
+ .getUserIcon(mNewUser.id).getFileDescriptor();
+ Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
((ImageView) view.findViewById(R.id.user_loading_avatar))
- .setImageBitmap(getDefaultUserIcon(mNewUser));
+ .setImageBitmap(bitmap);
((TextView) view.findViewById(R.id.user_loading))
.setText(res.getString(R.string.car_loading_profile));
setView(view);
}
-
- /**
- * Returns the default user icon. This icon is a circle with a letter in it. The letter is
- * the first character in the username.
- *
- * @param userInfo the profile of the user for which the icon should be created
- */
- private Bitmap getDefaultUserIcon(UserInfo userInfo) {
- Resources res = mContext.getResources();
- int mPodImageAvatarWidth = res.getDimensionPixelSize(
- R.dimen.car_fullscreen_user_pod_image_avatar_width);
- int mPodImageAvatarHeight = res.getDimensionPixelSize(
- R.dimen.car_fullscreen_user_pod_image_avatar_height);
- CharSequence displayText = userInfo.name.subSequence(0, 1);
- Bitmap out = Bitmap.createBitmap(mPodImageAvatarWidth, mPodImageAvatarHeight,
- Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(out);
-
- // Draw the circle background.
- GradientDrawable shape = new GradientDrawable();
- shape.setShape(GradientDrawable.RADIAL_GRADIENT);
- shape.setGradientRadius(1.0f);
- shape.setColor(mContext.getColor(R.color.car_user_switcher_user_image_bgcolor));
- shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
- shape.draw(canvas);
-
- // Draw the letter in the center.
- Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- paint.setColor(mContext.getColor(R.color.car_user_switcher_user_image_fgcolor));
- paint.setTextAlign(Align.CENTER);
- paint.setTextSize(res.getDimensionPixelSize(
- R.dimen.car_fullscreen_user_pod_icon_text_size));
-
- Paint.FontMetricsInt metrics = paint.getFontMetricsInt();
- // The Y coordinate is measured by taking half the height of the pod, but that would
- // draw the character putting the bottom of the font in the middle of the pod. To
- // correct this, half the difference between the top and bottom distance metrics of the
- // font gives the offset of the font. Bottom is a positive value, top is negative, so
- // the different is actually a sum. The "half" operation is then factored out.
- canvas.drawText(displayText.toString(), mPodImageAvatarWidth / 2,
- (mPodImageAvatarHeight - (metrics.bottom + metrics.top)) / 2, paint);
-
- return out;
- }
}