Add rotary support to the nav bar and HUN.

Add a FocusParkingView to the navigation bar and the heads-up
notification window. Add a dependency on the Chassis UI library.
Make the nav buttons have a blue background, or whatever color
the OEM specifies for the focus highlight.

Test: atest com.android.systemui.car.navigationbar.CarNavigationButtonTest
Bug: 155681517
Change-Id: Ia33c7692554c15427e429ecdba3bc978224ff129
This commit is contained in:
Danny Epstein
2020-05-19 20:16:47 -07:00
parent cc1937581a
commit 5a3e17d153
12 changed files with 41 additions and 48 deletions

View File

@@ -32,6 +32,7 @@ android_library {
"SystemUIPluginLib",
"SystemUISharedLib",
"SettingsLib",
"car-ui-lib",
"android.car.userlib",
"androidx.legacy_legacy-support-v4",
"androidx.recyclerview_recyclerview",
@@ -95,6 +96,7 @@ android_library {
"androidx.slice_slice-builders",
"androidx.arch.core_core-runtime",
"androidx.lifecycle_lifecycle-extensions",
"car-ui-lib",
"SystemUI-tags",
"SystemUI-proto",
"metrics-helper-lib",

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2018 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
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/nav_bar_ripple_background_color">
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="?android:colorAccent"/>
<corners android:radius="6dp"/>
</shape>
</item>
</ripple>

View File

@@ -79,7 +79,7 @@
android:gravity="bottom"
android:orientation="vertical">
<com.android.keyguard.AlphaOptimizedImageButton
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:id="@+id/note"
android:layout_height="wrap_content"
android:layout_width="match_parent"

View File

@@ -27,7 +27,7 @@
android:animateLayoutChanges="true"
android:orientation="vertical">
<com.android.keyguard.AlphaOptimizedImageButton
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:id="@+id/car_nav_button_icon_image"
android:layout_height="@dimen/car_navigation_button_icon_height"
android:layout_width="match_parent"
@@ -40,7 +40,7 @@
android:clickable="false"
/>
<com.android.keyguard.AlphaOptimizedImageButton
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:id="@+id/car_nav_button_more_icon"
android:layout_height="wrap_content"
android:layout_width="match_parent"

View File

@@ -82,7 +82,7 @@
android:gravity="bottom"
android:orientation="vertical">
<com.android.keyguard.AlphaOptimizedImageButton
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:id="@+id/note"
android:layout_height="wrap_content"
android:layout_width="match_parent"

View File

@@ -29,6 +29,15 @@
android:orientation="horizontal"
app:layout_constraintGuide_begin="@dimen/headsup_scrim_height"/>
<!-- Include a FocusParkingView at the beginning or end. The rotary controller "parks" the
focus here when the user navigates to another window. This is also used to prevent
wrap-around which is why it must be first or last in Tab order. -->
<com.android.car.ui.FocusParkingView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<View
android:id="@+id/scrim"
android:layout_width="match_parent"

View File

@@ -44,6 +44,6 @@
<style name="NavigationBarButton">
<item name="android:layout_height">96dp</item>
<item name="android:layout_width">96dp</item>
<item name="android:background">@drawable/nav_button_background</item>
<item name="android:background">@*android:drawable/item_background_material</item>
</style>
</resources>

View File

@@ -74,8 +74,10 @@ public class CarNavigationBarView extends LinearLayout {
mDarkIconManager.setShouldLog(true);
Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
}
// needs to be clickable so that it will receive ACTION_MOVE events
// Needs to be clickable so that it will receive ACTION_MOVE events.
setClickable(true);
// Needs to not be focusable so rotary won't highlight the entire nav bar.
setFocusable(false);
}
@Override

View File

@@ -32,8 +32,8 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import com.android.internal.annotations.VisibleForTesting;
import com.android.keyguard.AlphaOptimizedImageButton;
import com.android.systemui.R;
import com.android.systemui.statusbar.AlphaOptimizedImageView;
import java.net.URISyntaxException;
@@ -53,8 +53,8 @@ public class CarNavigationButton extends LinearLayout {
private static final String EXTRA_BUTTON_PACKAGES = "packages";
private Context mContext;
private AlphaOptimizedImageButton mIcon;
private AlphaOptimizedImageButton mMoreIcon;
private AlphaOptimizedImageView mIcon;
private AlphaOptimizedImageView mMoreIcon;
private ImageView mUnseenIcon;
private String mIntent;
private String mLongIntent;

View File

@@ -24,6 +24,7 @@ import android.view.ViewGroup;
import androidx.annotation.LayoutRes;
import com.android.car.ui.FocusParkingView;
import com.android.systemui.R;
import javax.inject.Inject;
@@ -146,6 +147,12 @@ public class NavigationBarViewFactory {
CarNavigationBarView view = (CarNavigationBarView) View.inflate(mContext, barLayout,
/* root= */ null);
// Include a FocusParkingView at the end. The rotary controller "parks" the focus here when
// the user navigates to another window. This is also used to prevent wrap-around which is
// why it must be first or last in Tab order.
view.addView(new FocusParkingView(mContext));
mCachedViewMap.put(type, view);
return mCachedViewMap.get(type);
}

View File

@@ -24,7 +24,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import com.android.car.notification.R;
import com.android.car.notification.headsup.CarHeadsUpNotificationContainer;
@@ -44,7 +43,7 @@ public class CarHeadsUpNotificationSystemContainer implements CarHeadsUpNotifica
private final OverlayViewGlobalStateController mOverlayViewGlobalStateController;
private final ViewGroup mWindow;
private final FrameLayout mHeadsUpContentFrame;
private final ViewGroup mHeadsUpContentFrame;
@Inject
CarHeadsUpNotificationSystemContainer(Context context,

View File

@@ -36,8 +36,8 @@ import android.widget.LinearLayout;
import androidx.test.filters.SmallTest;
import com.android.keyguard.AlphaOptimizedImageButton;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.AlphaOptimizedImageView;
import com.android.systemui.tests.R;
import org.junit.Before;
@@ -74,7 +74,7 @@ public class CarNavigationButtonTest extends SysuiTestCase {
@Test
public void onCreate_iconIsVisible() {
AlphaOptimizedImageButton icon = mDefaultButton.findViewById(
AlphaOptimizedImageView icon = mDefaultButton.findViewById(
R.id.car_nav_button_icon_image);
assertThat(icon.getDrawable()).isNotNull();
@@ -83,12 +83,12 @@ public class CarNavigationButtonTest extends SysuiTestCase {
@Test
public void onSelected_selectedIconDefined_togglesIcon() {
mDefaultButton.setSelected(true);
Drawable selectedIconDrawable = ((AlphaOptimizedImageButton) mDefaultButton.findViewById(
Drawable selectedIconDrawable = ((AlphaOptimizedImageView) mDefaultButton.findViewById(
R.id.car_nav_button_icon_image)).getDrawable();
mDefaultButton.setSelected(false);
Drawable unselectedIconDrawable = ((AlphaOptimizedImageButton) mDefaultButton.findViewById(
Drawable unselectedIconDrawable = ((AlphaOptimizedImageView) mDefaultButton.findViewById(
R.id.car_nav_button_icon_image)).getDrawable();
assertThat(selectedIconDrawable).isNotEqualTo(unselectedIconDrawable);
@@ -100,12 +100,12 @@ public class CarNavigationButtonTest extends SysuiTestCase {
R.id.selected_icon_undefined);
selectedIconUndefinedButton.setSelected(true);
Drawable selectedIconDrawable = ((AlphaOptimizedImageButton) mDefaultButton.findViewById(
Drawable selectedIconDrawable = ((AlphaOptimizedImageView) mDefaultButton.findViewById(
R.id.car_nav_button_icon_image)).getDrawable();
selectedIconUndefinedButton.setSelected(false);
Drawable unselectedIconDrawable = ((AlphaOptimizedImageButton) mDefaultButton.findViewById(
Drawable unselectedIconDrawable = ((AlphaOptimizedImageView) mDefaultButton.findViewById(
R.id.car_nav_button_icon_image)).getDrawable();
assertThat(selectedIconDrawable).isEqualTo(unselectedIconDrawable);
@@ -150,7 +150,7 @@ public class CarNavigationButtonTest extends SysuiTestCase {
@Test
public void onSelected_doesNotShowMoreWhenSelected_doesNotShowMoreIcon() {
mDefaultButton.setSelected(true);
AlphaOptimizedImageButton moreIcon = mDefaultButton.findViewById(
AlphaOptimizedImageView moreIcon = mDefaultButton.findViewById(
R.id.car_nav_button_more_icon);
assertThat(moreIcon.getVisibility()).isEqualTo(View.GONE);
@@ -161,7 +161,7 @@ public class CarNavigationButtonTest extends SysuiTestCase {
CarNavigationButton showMoreWhenSelected = mTestView.findViewById(
R.id.not_highlightable_more_button);
showMoreWhenSelected.setSelected(true);
AlphaOptimizedImageButton moreIcon = showMoreWhenSelected.findViewById(
AlphaOptimizedImageView moreIcon = showMoreWhenSelected.findViewById(
R.id.car_nav_button_more_icon);
assertThat(moreIcon.getVisibility()).isEqualTo(View.VISIBLE);
@@ -173,7 +173,7 @@ public class CarNavigationButtonTest extends SysuiTestCase {
R.id.highlightable_no_more_button);
showMoreWhenSelected.setSelected(true);
showMoreWhenSelected.setSelected(false);
AlphaOptimizedImageButton moreIcon = showMoreWhenSelected.findViewById(
AlphaOptimizedImageView moreIcon = showMoreWhenSelected.findViewById(
R.id.car_nav_button_more_icon);
assertThat(moreIcon.getVisibility()).isEqualTo(View.GONE);
@@ -187,7 +187,7 @@ public class CarNavigationButtonTest extends SysuiTestCase {
roleBasedButton.setSelected(false);
roleBasedButton.setAppIcon(appIcon);
Drawable currentDrawable = ((AlphaOptimizedImageButton) roleBasedButton.findViewById(
Drawable currentDrawable = ((AlphaOptimizedImageView) roleBasedButton.findViewById(
R.id.car_nav_button_icon_image)).getDrawable();
assertThat(currentDrawable).isEqualTo(appIcon);
@@ -212,7 +212,7 @@ public class CarNavigationButtonTest extends SysuiTestCase {
roleBasedButton.setSelected(true);
roleBasedButton.setAppIcon(appIcon);
Drawable currentDrawable = ((AlphaOptimizedImageButton) roleBasedButton.findViewById(
Drawable currentDrawable = ((AlphaOptimizedImageView) roleBasedButton.findViewById(
R.id.car_nav_button_icon_image)).getDrawable();
assertThat(currentDrawable).isEqualTo(appIcon);