diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp index 4c9629def113f..589623b0d6cd8 100644 --- a/packages/CarSystemUI/Android.bp +++ b/packages/CarSystemUI/Android.bp @@ -32,7 +32,6 @@ android_app { "SystemUISharedLib", "SettingsLib", "android.car.userlib", - "androidx.car_car", "androidx.legacy_legacy-support-v4", "androidx.recyclerview_recyclerview", "androidx.preference_preference", @@ -46,7 +45,6 @@ android_app { "androidx.slice_slice-builders", "androidx.arch.core_core-runtime", "androidx.lifecycle_lifecycle-extensions", - "car-theme-lib-bp", "SystemUI-tags", "SystemUI-proto", ], diff --git a/packages/CarSystemUI/res/layout/car_fullscreen_user_switcher.xml b/packages/CarSystemUI/res/layout/car_fullscreen_user_switcher.xml index e8c5134cd1805..395eac1d2ccbf 100644 --- a/packages/CarSystemUI/res/layout/car_fullscreen_user_switcher.xml +++ b/packages/CarSystemUI/res/layout/car_fullscreen_user_switcher.xml @@ -14,12 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. --> - + - + - + android:layout_height="match_parent"> + + diff --git a/packages/CarSystemUI/res/layout/car_qs_panel.xml b/packages/CarSystemUI/res/layout/car_qs_panel.xml index d923e0fbb20bf..9c598d71bd228 100644 --- a/packages/CarSystemUI/res/layout/car_qs_panel.xml +++ b/packages/CarSystemUI/res/layout/car_qs_panel.xml @@ -28,7 +28,6 @@ + android:layout_height="match_parent"/> diff --git a/packages/CarSystemUI/res/layout/car_volume_dialog.xml b/packages/CarSystemUI/res/layout/car_volume_dialog.xml index 709797d41060a..35551eabfaeda 100644 --- a/packages/CarSystemUI/res/layout/car_volume_dialog.xml +++ b/packages/CarSystemUI/res/layout/car_volume_dialog.xml @@ -14,15 +14,9 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License --> - + android:minWidth="@dimen/volume_dialog_panel_width"/> diff --git a/packages/CarSystemUI/res/layout/car_volume_item.xml b/packages/CarSystemUI/res/layout/car_volume_item.xml new file mode 100644 index 0000000000000..2275ca6329e2f --- /dev/null +++ b/packages/CarSystemUI/res/layout/car_volume_item.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + diff --git a/packages/CarSystemUI/res/layout/notification_center_activity.xml b/packages/CarSystemUI/res/layout/notification_center_activity.xml index 7c833035d57cc..383aba4e400a1 100644 --- a/packages/CarSystemUI/res/layout/notification_center_activity.xml +++ b/packages/CarSystemUI/res/layout/notification_center_activity.xml @@ -32,19 +32,14 @@ android:translationZ="2dp" /> - + app:layout_constraintEnd_toEndOf="parent"/> diff --git a/packages/CarSystemUI/res/values/colors.xml b/packages/CarSystemUI/res/values/colors.xml index 7b4e32b407ae5..83ec3514c01a6 100644 --- a/packages/CarSystemUI/res/values/colors.xml +++ b/packages/CarSystemUI/res/values/colors.xml @@ -45,4 +45,6 @@ @android:color/black @*android:color/car_list_divider_light + @*android:color/car_list_divider + @*android:color/car_card_dark diff --git a/packages/CarSystemUI/res/values/dimens.xml b/packages/CarSystemUI/res/values/dimens.xml index 07ecca201c123..60ce342b0adc1 100644 --- a/packages/CarSystemUI/res/values/dimens.xml +++ b/packages/CarSystemUI/res/values/dimens.xml @@ -26,7 +26,7 @@ 1.75 - 36dp + @*android:dimen/car_primary_icon_size @dimen/car_body1_size @@ -59,4 +59,33 @@ 24dp 96dp 128dp + + 100dp + + + 48dp + + 15dp + + 24dp + + 12dp + + 6dp + + 4dp + + 12dp + + + @*android:dimen/car_single_line_list_item_height + @*android:dimen/car_keyline_1 + @*android:dimen/car_padding_1 + @*android:dimen/car_keyline_3 + @*android:dimen/car_padding_4 + @*android:dimen/car_seekbar_padding + 60dp + 1dp + @*android:dimen/car_padding_4 + @*android:dimen/car_radius_3 diff --git a/packages/CarSystemUI/res/values/styles.xml b/packages/CarSystemUI/res/values/styles.xml index 0d95d308f48b4..382d269ecd44c 100644 --- a/packages/CarSystemUI/res/values/styles.xml +++ b/packages/CarSystemUI/res/values/styles.xml @@ -46,11 +46,4 @@ 96dp @drawable/nav_button_background - - \ No newline at end of file diff --git a/packages/CarSystemUI/res/values/themes.xml b/packages/CarSystemUI/res/values/themes.xml index 8d1a4d7c08c46..f82be3c0e529e 100644 --- a/packages/CarSystemUI/res/values/themes.xml +++ b/packages/CarSystemUI/res/values/themes.xml @@ -18,10 +18,6 @@ --> - - - diff --git a/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java b/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java index 4a2d2fbc30cf5..48cb55b3d90ec 100644 --- a/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java +++ b/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java @@ -16,11 +16,11 @@ package com.android.systemui.notifications; -import android.app.ActivityManager; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.SuppressLint; +import android.app.ActivityManager; import android.car.Car; import android.car.CarNotConnectedException; import android.car.drivingstate.CarUxRestrictionsManager; @@ -113,7 +113,7 @@ public class NotificationsUI extends SystemUI ServiceManager.getService(Context.STATUS_BAR_SERVICE)), launchResult -> { if (launchResult == ActivityManager.START_TASK_TO_FRONT - || launchResult == ActivityManager.START_SUCCESS){ + || launchResult == ActivityManager.START_SUCCESS) { closeCarNotifications(DEFAULT_FLING_VELOCITY); } }); @@ -179,8 +179,7 @@ public class NotificationsUI extends SystemUI } }); - RecyclerView notificationList = mCarNotificationWindow - .findViewById(com.android.car.notification.R.id.recycler_view); + RecyclerView notificationList = mCarNotificationWindow.findViewById(R.id.notifications); // register a scroll listener so we can figure out if we are at the bottom of the // list of notifications notificationList.addOnScrollListener(new RecyclerView.OnScrollListener() { @@ -202,7 +201,7 @@ public class NotificationsUI extends SystemUI // There's a view installed at a higher z-order such that we can intercept the ACTION_DOWN // to set the initial click state. mCarNotificationWindow.findViewById(R.id.glass_pane).setOnTouchListener((v, event) -> { - if (event.getActionMasked() == MotionEvent.ACTION_UP ) { + if (event.getActionMasked() == MotionEvent.ACTION_UP) { mNotificationListAtBottomAtTimeOfTouch = false; } if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { @@ -259,7 +258,7 @@ public class NotificationsUI extends SystemUI public boolean onTouch(View v, MotionEvent event) { // reset mNotificationListAtBottomAtTimeOfTouch here since the "glass pane" will not // get the up event - if (event.getActionMasked() == MotionEvent.ACTION_UP ) { + if (event.getActionMasked() == MotionEvent.ACTION_UP) { mNotificationListAtBottomAtTimeOfTouch = false; } boolean wasScrolledUp = mScrollUpDetector.onTouchEvent(event); @@ -351,7 +350,7 @@ public class NotificationsUI extends SystemUI public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { if (Math.abs(event1.getX() - event2.getX()) > SWIPE_MAX_OFF_PATH - || Math.abs(velocityY) < SWIPE_THRESHOLD_VELOCITY){ + || Math.abs(velocityY) < SWIPE_THRESHOLD_VELOCITY) { // swipe was not vertical or was not fast enough return false; } @@ -435,8 +434,7 @@ public class NotificationsUI extends SystemUI mNotificationViewController.disable(); mIsShowing = false; mIsTracking = false; - RecyclerView notificationListView = mCarNotificationWindow.findViewById( - com.android.car.notification.R.id.recycler_view); + RecyclerView notificationListView = mCarNotificationWindow.findViewById(R.id.notifications); notificationListView.scrollToPosition(0); } diff --git a/packages/CarSystemUI/src/com/android/systemui/qs/car/CarQSFragment.java b/packages/CarSystemUI/src/com/android/systemui/qs/car/CarQSFragment.java index 41c37d3bbc196..769fc52a574cf 100644 --- a/packages/CarSystemUI/src/com/android/systemui/qs/car/CarQSFragment.java +++ b/packages/CarSystemUI/src/com/android/systemui/qs/car/CarQSFragment.java @@ -79,7 +79,7 @@ public class CarQSFragment extends Fragment implements QS { mUserGridView = mUserSwitcherContainer.findViewById(R.id.user_grid); GridLayoutManager layoutManager = new GridLayoutManager(context, context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col)); - mUserGridView.getRecyclerView().setLayoutManager(layoutManager); + mUserGridView.setLayoutManager(layoutManager); mUserGridView.buildAdapter(); mUserSwitchCallback = new UserSwitchCallback(); diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java index 23fe5944573e9..f896cf1bf10c4 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java @@ -45,7 +45,7 @@ public class FullscreenUserSwitcher { mUserGridView = container.findViewById(R.id.user_grid); GridLayoutManager layoutManager = new GridLayoutManager(context, context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col)); - mUserGridView.getRecyclerView().setLayoutManager(layoutManager); + mUserGridView.setLayoutManager(layoutManager); mUserGridView.buildAdapter(); mUserGridView.setUserSelectionListener(this::onUserSelected); diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java index fb2b57b6d4900..57603781e3f0b 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java @@ -28,6 +28,7 @@ import android.content.DialogInterface; import android.content.pm.UserInfo; import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.Rect; import android.os.AsyncTask; import android.util.AttributeSet; import android.view.LayoutInflater; @@ -36,9 +37,9 @@ import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; -import androidx.car.widget.PagedListView; import androidx.core.graphics.drawable.RoundedBitmapDrawable; import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; +import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.internal.util.UserIcons; @@ -52,7 +53,7 @@ import java.util.List; * 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 PagedListView implements +public class UserGridRecyclerView extends RecyclerView implements CarUserManagerHelper.OnUsersUpdateListener { private UserSelectionListener mUserSelectionListener; private UserAdapter mAdapter; @@ -63,6 +64,9 @@ public class UserGridRecyclerView extends PagedListView implements super(context, attrs); mContext = context; mCarUserManagerHelper = new CarUserManagerHelper(mContext); + + addItemDecoration(new ItemSpacingDecoration(context.getResources().getDimensionPixelSize( + R.dimen.car_user_switcher_vertical_spacing_between_users))); } /** @@ -391,4 +395,31 @@ public class UserGridRecyclerView extends PagedListView implements void onUserSelected(UserRecord record); } + + /** + * A {@link RecyclerView.ItemDecoration} that will add spacing between each item in the + * RecyclerView that it is added to. + */ + private static class ItemSpacingDecoration extends RecyclerView.ItemDecoration { + private int mItemSpacing; + + private ItemSpacingDecoration(int itemSpacing) { + mItemSpacing = itemSpacing; + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, + RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + int position = parent.getChildAdapterPosition(view); + + // Skip offset for last item except for GridLayoutManager. + if (position == state.getItemCount() - 1 + && !(parent.getLayoutManager() instanceof GridLayoutManager)) { + return; + } + + outRect.bottom = mItemSpacing; + } + } } diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java index 10a0ae5a924c8..512210be0a468 100644 --- a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java +++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java @@ -32,9 +32,7 @@ import android.content.DialogInterface; import android.content.ServiceConnection; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; -import android.graphics.Color; import android.graphics.PixelFormat; -import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.os.Debug; @@ -46,7 +44,6 @@ import android.util.AttributeSet; import android.util.Log; import android.util.SparseArray; import android.util.Xml; -import android.view.ContextThemeWrapper; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; @@ -56,12 +53,8 @@ import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; -import androidx.car.widget.ListItem; -import androidx.car.widget.ListItemAdapter; -import androidx.car.widget.ListItemAdapter.BackgroundStyle; -import androidx.car.widget.ListItemProvider.ListProvider; -import androidx.car.widget.PagedListView; -import androidx.car.widget.SeekbarListItem; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import com.android.systemui.R; import com.android.systemui.plugins.VolumeDialog; @@ -96,13 +89,13 @@ public class CarVolumeDialogImpl implements VolumeDialog { private final SparseArray mVolumeItems = new SparseArray<>(); // Available volume items in car audio manager. private final List mAvailableVolumeItems = new ArrayList<>(); - // Volume items in the PagedListView. - private final List mVolumeLineItems = new ArrayList<>(); + // Volume items in the RecyclerView. + private final List mCarVolumeLineItems = new ArrayList<>(); private final KeyguardManager mKeyguard; private Window mWindow; private CustomDialog mDialog; - private PagedListView mListView; - private ListItemAdapter mPagedListAdapter; + private RecyclerView mListView; + private CarVolumeItemAdapter mVolumeItemsAdapter; private Car mCar; private CarAudioManager mCarAudioManager; private final CarAudioManager.CarVolumeCallback mVolumeChangeCallback = @@ -126,7 +119,7 @@ public class CarVolumeDialogImpl implements VolumeDialog { // callback. Updating the seekbar at the same time could block the continuous // seeking. if (value != volumeItem.progress) { - volumeItem.listItem.setProgress(value); + volumeItem.carVolumeItem.setProgress(value); volumeItem.progress = value; } if ((flags & AudioManager.FLAG_SHOW_UI) != 0) { @@ -160,13 +153,13 @@ public class CarVolumeDialogImpl implements VolumeDialog { // The first one is the default item. if (groupId == 0) { mDefaultVolumeItem = volumeItem; - setupDefaultListItem(); + setupDefaultCarVolumeItem(); } } // If list is already initiated, update its content. - if (mPagedListAdapter != null) { - mPagedListAdapter.notifyDataSetChanged(); + if (mVolumeItemsAdapter != null) { + mVolumeItemsAdapter.notifyDataSetChanged(); } mCarAudioManager.registerCarVolumeCallback(mVolumeChangeCallback); } catch (CarNotConnectedException e) { @@ -184,15 +177,15 @@ public class CarVolumeDialogImpl implements VolumeDialog { } }; - private void setupDefaultListItem() { + private void setupDefaultCarVolumeItem() { mDefaultVolumeItem.defaultItem = true; - addSeekbarListItem(mDefaultVolumeItem, /* volumeGroupId = */0, + addCarVolumeListItem(mDefaultVolumeItem, /* volumeGroupId = */0, R.drawable.car_ic_keyboard_arrow_down, new ExpandIconListener() ); } public CarVolumeDialogImpl(Context context) { - mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme); + mContext = context; mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); mCar = Car.createCar(mContext, mServiceConnection); } @@ -238,7 +231,7 @@ public class CarVolumeDialogImpl implements VolumeDialog { private void initDialog() { loadAudioUsageItems(); - mVolumeLineItems.clear(); + mCarVolumeLineItems.clear(); mDialog = new CustomDialog(mContext); mHovering = false; @@ -246,7 +239,6 @@ public class CarVolumeDialogImpl implements VolumeDialog { mExpanded = false; mWindow = mDialog.getWindow(); mWindow.requestFeature(Window.FEATURE_NO_TITLE); - mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE @@ -263,10 +255,11 @@ public class CarVolumeDialogImpl implements VolumeDialog { lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; lp.windowAnimations = -1; mWindow.setAttributes(lp); - mWindow.setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + + mDialog.setContentView(R.layout.car_volume_dialog); + mWindow.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); mDialog.setCanceledOnTouchOutside(true); - mDialog.setContentView(R.layout.car_volume_dialog); mDialog.setOnShowListener(dialog -> { mListView.setTranslationY(-mListView.getHeight()); mListView.setAlpha(0); @@ -277,7 +270,7 @@ public class CarVolumeDialogImpl implements VolumeDialog { .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator()) .start(); }); - mListView = (PagedListView) mWindow.findViewById(R.id.volume_list); + mListView = mWindow.findViewById(R.id.volume_list); mListView.setOnHoverListener((v, event) -> { int action = event.getActionMasked(); mHovering = (action == MotionEvent.ACTION_HOVER_ENTER) @@ -286,10 +279,9 @@ public class CarVolumeDialogImpl implements VolumeDialog { return true; }); - mPagedListAdapter = new ListItemAdapter(mContext, new ListProvider(mVolumeLineItems), - BackgroundStyle.PANEL); - mListView.setAdapter(mPagedListAdapter); - mListView.setMaxPages(PagedListView.UNLIMITED_PAGES); + mVolumeItemsAdapter = new CarVolumeItemAdapter(mContext, mCarVolumeLineItems); + mListView.setAdapter(mVolumeItemsAdapter); + mListView.setLayoutManager(new LinearLayoutManager(mContext)); } @@ -302,13 +294,13 @@ public class CarVolumeDialogImpl implements VolumeDialog { mHandler.removeMessages(H.DISMISS); rescheduleTimeoutH(); // Refresh the data set before showing. - mPagedListAdapter.notifyDataSetChanged(); + mVolumeItemsAdapter.notifyDataSetChanged(); if (mShowing) { return; } mShowing = true; - if (mVolumeLineItems.isEmpty()) { - setupDefaultListItem(); + if (mCarVolumeLineItems.isEmpty()) { + setupDefaultCarVolumeItem(); } mDialog.show(); Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked()); @@ -421,40 +413,41 @@ public class CarVolumeDialogImpl implements VolumeDialog { return result; } - private SeekbarListItem addSeekbarListItem(VolumeItem volumeItem, - int volumeGroupId, + private CarVolumeItem addCarVolumeListItem(VolumeItem volumeItem, int volumeGroupId, int supplementalIconId, @Nullable View.OnClickListener supplementalIconOnClickListener) { - SeekbarListItem listItem = new SeekbarListItem(mContext); - listItem.setMax(getMaxSeekbarValue(mCarAudioManager, volumeGroupId)); + CarVolumeItem carVolumeItem = new CarVolumeItem(); + carVolumeItem.setMax(getMaxSeekbarValue(mCarAudioManager, volumeGroupId)); int color = mContext.getResources().getColor(R.color.car_volume_dialog_tint); int progress = getSeekbarValue(mCarAudioManager, volumeGroupId); - listItem.setProgress(progress); - listItem.setOnSeekBarChangeListener(new CarVolumeDialogImpl - .VolumeSeekBarChangeListener(volumeGroupId, mCarAudioManager)); + carVolumeItem.setProgress(progress); + carVolumeItem.setOnSeekBarChangeListener( + new CarVolumeDialogImpl.VolumeSeekBarChangeListener(volumeGroupId, + mCarAudioManager)); Drawable primaryIcon = mContext.getResources().getDrawable(volumeItem.icon); primaryIcon.mutate().setTint(color); - listItem.setPrimaryActionIcon(primaryIcon); + carVolumeItem.setPrimaryIcon(primaryIcon); if (supplementalIconId != 0) { Drawable supplementalIcon = mContext.getResources().getDrawable(supplementalIconId); supplementalIcon.mutate().setTint(color); - listItem.setSupplementalIcon(supplementalIcon, true); - listItem.setSupplementalIconListener(supplementalIconOnClickListener); + carVolumeItem.setSupplementalIcon(supplementalIcon, + /* showSupplementalIconDivider= */ true); + carVolumeItem.setSupplementalIconListener(supplementalIconOnClickListener); } else { - listItem.setSupplementalEmptyIcon(true); - listItem.setSupplementalIconListener(null); + carVolumeItem.setSupplementalIcon(/* drawable= */ null, + /* showSupplementalIconDivider= */ false); } - mVolumeLineItems.add(listItem); - volumeItem.listItem = listItem; + mCarVolumeLineItems.add(carVolumeItem); + volumeItem.carVolumeItem = carVolumeItem; volumeItem.progress = progress; - return listItem; + return carVolumeItem; } - private VolumeItem findVolumeItem(SeekbarListItem targetItem) { + private VolumeItem findVolumeItem(CarVolumeItem targetItem) { for (int i = 0; i < mVolumeItems.size(); ++i) { VolumeItem volumeItem = mVolumeItems.valueAt(i); - if (volumeItem.listItem == targetItem) { + if (volumeItem.carVolumeItem == targetItem) { return volumeItem; } } @@ -463,7 +456,7 @@ public class CarVolumeDialogImpl implements VolumeDialog { private void cleanupAudioManager() { mCarAudioManager.unregisterCarVolumeCallback(mVolumeChangeCallback); - mVolumeLineItems.clear(); + mCarVolumeLineItems.clear(); mCarAudioManager = null; } @@ -474,8 +467,9 @@ public class CarVolumeDialogImpl implements VolumeDialog { private int rank; private boolean defaultItem = false; - private @DrawableRes int icon; - private SeekbarListItem listItem; + @DrawableRes + private int icon; + private CarVolumeItem carVolumeItem; private int progress; } @@ -554,9 +548,9 @@ public class CarVolumeDialogImpl implements VolumeDialog { // Adding the items which are not coming from the default item. VolumeItem volumeItem = mAvailableVolumeItems.get(groupId); if (volumeItem.defaultItem) { - updateDefaultVolumeItem(volumeItem.listItem); + updateDefaultVolumeItem(volumeItem.carVolumeItem); } else { - addSeekbarListItem(volumeItem, groupId, 0, null); + addCarVolumeListItem(volumeItem, groupId, 0, null); } } inAnimator = AnimatorInflater.loadAnimator( @@ -564,14 +558,14 @@ public class CarVolumeDialogImpl implements VolumeDialog { } else { // Only keeping the default stream if it is not expended. - Iterator itr = mVolumeLineItems.iterator(); + Iterator itr = mCarVolumeLineItems.iterator(); while (itr.hasNext()) { - SeekbarListItem seekbarListItem = (SeekbarListItem) itr.next(); - VolumeItem volumeItem = findVolumeItem(seekbarListItem); + CarVolumeItem carVolumeItem = (CarVolumeItem) itr.next(); + VolumeItem volumeItem = findVolumeItem(carVolumeItem); if (!volumeItem.defaultItem) { itr.remove(); } else { - updateDefaultVolumeItem(seekbarListItem); + updateDefaultVolumeItem(carVolumeItem); } } inAnimator = AnimatorInflater.loadAnimator( @@ -590,22 +584,22 @@ public class CarVolumeDialogImpl implements VolumeDialog { } animators.setTarget(mExpandIcon); animators.start(); - mPagedListAdapter.notifyDataSetChanged(); + mVolumeItemsAdapter.notifyDataSetChanged(); } - private void updateDefaultVolumeItem(SeekbarListItem seekbarListItem){ - VolumeItem volumeItem = findVolumeItem(seekbarListItem); + private void updateDefaultVolumeItem(CarVolumeItem carVolumeItem) { + VolumeItem volumeItem = findVolumeItem(carVolumeItem); // When volume dialog is expanded or collapsed the default list item is never // reset. Whereas all other list items are removed when the dialog is collapsed and then - // added when the dialog is expanded using {@link CarVolumeDialogImpl#addSeekbarListItem}. + // added when the dialog is expanded using {@link CarVolumeDialogImpl#addCarVolumeListItem}. // This sets the progressbar and the tint color of icons for all items other than default // if they were changed. For default list item it should be done manually here. int color = mContext.getResources().getColor(R.color.car_volume_dialog_tint); Drawable primaryIcon = mContext.getResources().getDrawable(volumeItem.icon); primaryIcon.mutate().setTint(color); - volumeItem.listItem.setPrimaryActionIcon(primaryIcon); - volumeItem.listItem.setProgress(volumeItem.progress); + volumeItem.carVolumeItem.setPrimaryIcon(primaryIcon); + volumeItem.carVolumeItem.setProgress(volumeItem.progress); } private final class VolumeSeekBarChangeListener implements OnSeekBarChangeListener { @@ -646,4 +640,4 @@ public class CarVolumeDialogImpl implements VolumeDialog { public void onStopTrackingTouch(SeekBar seekBar) { } } -} \ No newline at end of file +} diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeItem.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeItem.java new file mode 100644 index 0000000000000..9613de1bfaaa8 --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeItem.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2019 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.volume; + +import android.graphics.drawable.Drawable; +import android.view.View; +import android.widget.ImageView; +import android.widget.SeekBar; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.android.systemui.R; + +/** Holds all related data to represent a volume group. */ +public class CarVolumeItem { + + private boolean mIsDirty; + + private Drawable mPrimaryIcon; + private Drawable mSupplementalIcon; + private View.OnClickListener mSupplementalIconOnClickListener; + private boolean mShowSupplementalIconDivider; + + private int mMax; + private int mProgress; + private SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener; + + public CarVolumeItem() { + mIsDirty = true; + } + + /** + * Called when {@link CarVolumeItem} is bound to its ViewHolder. + */ + void bind(CarVolumeItemViewHolder viewHolder) { + if (mIsDirty) { + viewHolder.bind(/* carVolumeItem= */ this); + mIsDirty = false; + } + } + + /** Sets progress of seekbar. */ + public void setProgress(int progress) { + mProgress = progress; + mIsDirty = true; + } + + /** Sets max value of seekbar. */ + public void setMax(int max) { + mMax = max; + mIsDirty = true; + } + + /** Sets {@link SeekBar.OnSeekBarChangeListener}. */ + public void setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener listener) { + mOnSeekBarChangeListener = listener; + mIsDirty = true; + } + + /** Sets the primary icon. */ + public void setPrimaryIcon(Drawable drawable) { + mPrimaryIcon = drawable; + mIsDirty = true; + } + + /** Sets the supplemental icon and the visibility of the supplemental icon divider. */ + public void setSupplementalIcon(Drawable drawable, boolean showSupplementalIconDivider) { + mSupplementalIcon = drawable; + mShowSupplementalIconDivider = showSupplementalIconDivider; + mIsDirty = true; + } + + /** Sets {@code OnClickListener} for the supplemental icon. */ + public void setSupplementalIconListener(View.OnClickListener listener) { + mSupplementalIconOnClickListener = listener; + mIsDirty = true; + } + + /** Defines the view holder which shows the information held by {@link CarVolumeItem}. */ + public static class CarVolumeItemViewHolder extends RecyclerView.ViewHolder { + + private SeekBar mSeekBar; + private ImageView mPrimaryIcon; + private View mSupplementalIconDivider; + private ImageView mSupplementalIcon; + + public CarVolumeItemViewHolder(@NonNull View itemView) { + super(itemView); + + mSeekBar = itemView.findViewById(R.id.seek_bar); + mPrimaryIcon = itemView.findViewById(R.id.primary_icon); + mSupplementalIcon = itemView.findViewById(R.id.supplemental_icon); + mSupplementalIconDivider = itemView.findViewById(R.id.supplemental_icon_divider); + } + + /** + * Binds {@link CarVolumeItem} to the {@link CarVolumeItemViewHolder}. + */ + void bind(CarVolumeItem carVolumeItem) { + // Progress bar + mSeekBar.setMax(carVolumeItem.mMax); + mSeekBar.setProgress(carVolumeItem.mProgress); + mSeekBar.setOnSeekBarChangeListener(carVolumeItem.mOnSeekBarChangeListener); + + // Primary icon + mPrimaryIcon.setVisibility(View.VISIBLE); + mPrimaryIcon.setImageDrawable(carVolumeItem.mPrimaryIcon); + + // Supplemental icon + mSupplementalIcon.setVisibility(View.VISIBLE); + mSupplementalIconDivider.setVisibility( + carVolumeItem.mShowSupplementalIconDivider ? View.VISIBLE : View.INVISIBLE); + mSupplementalIcon.setImageDrawable(carVolumeItem.mSupplementalIcon); + mSupplementalIcon.setOnClickListener( + carVolumeItem.mSupplementalIconOnClickListener); + mSupplementalIcon.setClickable( + carVolumeItem.mSupplementalIconOnClickListener != null); + } + } +} diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeItemAdapter.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeItemAdapter.java new file mode 100644 index 0000000000000..5c1f8170afc4b --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeItemAdapter.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2019 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.volume; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.recyclerview.widget.RecyclerView; + +import com.android.systemui.R; + +import java.util.List; + +/** The {@link RecyclerView.Adapter} to show the volume items in the sysUI volume dialog. */ +public class CarVolumeItemAdapter extends + RecyclerView.Adapter { + + private final Context mContext; + private final List mItems; + + public CarVolumeItemAdapter(Context context, List items) { + mContext = context; + mItems = items; + } + + @Override + public CarVolumeItem.CarVolumeItemViewHolder onCreateViewHolder(ViewGroup parent, + int viewType) { + LayoutInflater inflater = LayoutInflater.from(mContext); + View view = inflater.inflate(R.layout.car_volume_item, parent, false); + return new CarVolumeItem.CarVolumeItemViewHolder(view); + } + + @Override + public void onBindViewHolder(CarVolumeItem.CarVolumeItemViewHolder holder, int position) { + mItems.get(position).bind(holder); + } + + @Override + public int getItemCount() { + return mItems.size(); + } +}