diff options
author | Rodrigo Lagos <rlagos@google.com> | 2020-06-12 21:57:37 -0700 |
---|---|---|
committer | Rodrigo Lagos <rlagos@google.com> | 2020-06-12 22:27:50 -0700 |
commit | 2f20b0665a13f776e39e881d712fd3515950dfbf (patch) | |
tree | c34534a926f286bd8fd133b740084f7c3dcc73f3 | |
parent | 7d7e723fcbde01df67cea5479a06454d65e73ad1 (diff) | |
download | setupwizard-2f20b0665a13f776e39e881d712fd3515950dfbf.tar.gz |
Add 'Close' button to toolbar
Plumb through convinience methods for manipulating close button
Add defailt close handler for close button
Update test
Bug: 158858809
Test: local tess, and deployed to device
Change-Id: Iff93405c96559bac180db183b8d8c99fb488fc13
10 files changed, 197 insertions, 14 deletions
diff --git a/library/main/res/drawable/car_ic_close.xml b/library/main/res/drawable/car_ic_close.xml new file mode 100644 index 0000000..08b5e36 --- /dev/null +++ b/library/main/res/drawable/car_ic_close.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (C) 2020 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="@dimen/car_primary_icon_size" + android:height="@dimen/car_primary_icon_size" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12 19,6.41z" + android:fillColor="@color/car_tint_light"/> +</vector> diff --git a/library/main/res/layout/car_setup_wizard_toolbar.xml b/library/main/res/layout/car_setup_wizard_toolbar.xml index 5c5703b..5ae4e11 100644 --- a/library/main/res/layout/car_setup_wizard_toolbar.xml +++ b/library/main/res/layout/car_setup_wizard_toolbar.xml @@ -37,6 +37,15 @@ android:background="@drawable/button_ripple_bg" android:contentDescription="@string/back_button_content_description" android:src="@drawable/car_ic_arrow_back"/> + + <ImageView + android:id="@+id/close_button" + android:layout_width="@dimen/car_primary_icon_size" + android:layout_height="@dimen/car_primary_icon_size" + android:layout_gravity="center" + android:background="@drawable/button_ripple_bg" + android:contentDescription="@string/close_button_content_description" + android:src="@drawable/car_ic_close"/> </FrameLayout> <TextView diff --git a/library/main/res/values/attrs.xml b/library/main/res/values/attrs.xml index 957f3dd..667a98f 100644 --- a/library/main/res/values/attrs.xml +++ b/library/main/res/values/attrs.xml @@ -45,6 +45,8 @@ <declare-styleable name="CarSetupWizardBaseLayout"> <!-- Attributes related to the visibility of the back button --> <attr name="showBackButton" format="boolean"/> + <!-- Attributes related to the visibility of the close button --> + <attr name="showCloseButton" format="boolean"/> <!-- Attributes related to the visibility and text of the toolbar title --> <attr name="showToolbarTitle" format="boolean"/> diff --git a/library/main/res/values/strings.xml b/library/main/res/values/strings.xml index beb37dc..027a683 100644 --- a/library/main/res/values/strings.xml +++ b/library/main/res/values/strings.xml @@ -17,4 +17,7 @@ <resources> <!-- Content description of the back button for accessibility services like Tallback [CHAR LIMIT=120] --> <string name="back_button_content_description">Navigate back</string> + + <!-- Content description of the close button for accessibility services like Tallback [CHAR LIMIT=120] --> + <string name="close_button_content_description">Close</string> </resources>
\ No newline at end of file diff --git a/library/main/src/com/android/car/setupwizardlib/BaseSetupWizardActivity.java b/library/main/src/com/android/car/setupwizardlib/BaseSetupWizardActivity.java index 3da7df6..255f228 100644 --- a/library/main/src/com/android/car/setupwizardlib/BaseSetupWizardActivity.java +++ b/library/main/src/com/android/car/setupwizardlib/BaseSetupWizardActivity.java @@ -97,6 +97,8 @@ abstract class BaseSetupWizardActivity extends FragmentActivity { } }); + mCarSetupWizardLayout.setCloseButtonListener(v-> handleCloseButton()); + resetPrimaryToolbarButtonOnClickListener(); resetSecondaryToolbarButtonOnClickListener(); @@ -255,6 +257,14 @@ abstract class BaseSetupWizardActivity extends FragmentActivity { } /** + * Method to be overwritten by subclasses wanting to implement their own close behavior. + * Default behavior is finishAction. + */ + protected void handleCloseButton() { + finishAction(); + } + + /** * Called when nextAction has been invoked, should be overridden on derived class when it is * needed perform work when nextAction has been invoked. */ @@ -350,6 +360,14 @@ abstract class BaseSetupWizardActivity extends FragmentActivity { } /** + * Sets whether the close button is visible. If this value is {@code true}, clicking the button + * will finish the current flow. + */ + protected void setCloseButtonVisible(boolean visible) { + mCarSetupWizardLayout.setCloseButtonVisible(visible); + } + + /** * Sets whether the toolbar title is visible. */ protected void setToolbarTitleVisible(boolean visible) { diff --git a/library/main/src/com/android/car/setupwizardlib/CarSetupWizardBaseLayout.java b/library/main/src/com/android/car/setupwizardlib/CarSetupWizardBaseLayout.java index 7a7808d..2773e3d 100644 --- a/library/main/src/com/android/car/setupwizardlib/CarSetupWizardBaseLayout.java +++ b/library/main/src/com/android/car/setupwizardlib/CarSetupWizardBaseLayout.java @@ -61,6 +61,7 @@ class CarSetupWizardBaseLayout extends LinearLayout { private static final int INVALID_COLOR = 0; private View mBackButton; + private View mCloseButton; private View mTitleBar; private TextView mToolbarTitle; private PartnerConfigHelper mPartnerConfigHelper; @@ -118,6 +119,7 @@ class CarSetupWizardBaseLayout extends LinearLayout { */ private void init(TypedArray attrArray) { boolean showBackButton; + boolean showCloseButton; boolean showToolbarTitle; String toolbarTitleText; @@ -136,6 +138,8 @@ class CarSetupWizardBaseLayout extends LinearLayout { try { showBackButton = attrArray.getBoolean( R.styleable.CarSetupWizardBaseLayout_showBackButton, true); + showCloseButton = attrArray.getBoolean( + R.styleable.CarSetupWizardBaseLayout_showCloseButton, false); showToolbarTitle = attrArray.getBoolean( R.styleable.CarSetupWizardBaseLayout_showToolbarTitle, false); toolbarTitleText = attrArray.getString( @@ -165,14 +169,30 @@ class CarSetupWizardBaseLayout extends LinearLayout { LayoutInflater inflater = LayoutInflater.from(getContext()); inflater.inflate(R.layout.car_setup_wizard_layout, this); - // Set the back button visibility based on the custom attribute. + setBackButton(findViewById(R.id.back_button)); + setCloseButton(findViewById(R.id.close_button)); + Drawable drawable = mPartnerConfigHelper.getDrawable( getContext(), PartnerConfig.CONFIG_TOOLBAR_BUTTON_ICON_BACK); if (drawable != null) { ((ImageView) mBackButton).setImageDrawable(drawable); } + + Drawable closeButtonDrawable = mPartnerConfigHelper.getDrawable( + getContext(), PartnerConfig.CONFIG_TOOLBAR_BUTTON_ICON_CLOSE); + if (closeButtonDrawable != null) { + ((ImageView) mCloseButton).setImageDrawable(closeButtonDrawable); + } + + if (showBackButton && showCloseButton) { + Log.w(TAG, "Showing Back and Close button simultaneously is not supported"); + } + + // Set the back button visibility based on the custom attribute. setBackButtonVisible(showBackButton); + // Set the close button visibility based on the custom attribute. + setCloseButtonVisible(showCloseButton); // Se the title bar. setTitleBar(findViewById(R.id.application_bar)); @@ -242,19 +262,25 @@ class CarSetupWizardBaseLayout extends LinearLayout { */ @VisibleForTesting void setViewVisible(View view, boolean visible) { + if (view == null) { + return; + } view.setVisibility(visible ? View.VISIBLE : View.GONE); } // Add or remove the back button touch delegate depending on whether it is visible. @VisibleForTesting - void updateBackButtonTouchDelegate(boolean visible) { + void updateNavigationButtonTouchDelegate(View button, boolean visible) { + if (button == null) { + return; + } if (visible) { // Post this action in the parent's message queue to make sure the parent // lays out its children before getHitRect() is called this.post(() -> { Rect delegateArea = new Rect(); - mBackButton.getHitRect(delegateArea); + button.getHitRect(delegateArea); /* * Update the delegate area based on the difference between the current size and @@ -273,17 +299,16 @@ class CarSetupWizardBaseLayout extends LinearLayout { delegateArea.top -= sizeDifference; // Set the TouchDelegate on the parent view - TouchDelegate touchDelegate = new TouchDelegate(delegateArea, - mBackButton); + TouchDelegate touchDelegate = new TouchDelegate(delegateArea, button); - if (View.class.isInstance(mBackButton.getParent())) { - ((View) mBackButton.getParent()).setTouchDelegate(touchDelegate); + if (View.class.isInstance(button.getParent())) { + ((View) button.getParent()).setTouchDelegate(touchDelegate); } }); } else { // Set the TouchDelegate to null if the back button is not visible. - if (View.class.isInstance(mBackButton.getParent())) { - ((View) mBackButton.getParent()).setTouchDelegate(null); + if (View.class.isInstance(button.getParent())) { + ((View) button.getParent()).setTouchDelegate(null); } } } @@ -312,8 +337,41 @@ class CarSetupWizardBaseLayout extends LinearLayout { * Set the back button visibility to the given visibility. */ public void setBackButtonVisible(boolean visible) { + if (visible) { + setViewVisible(mCloseButton, false); + updateNavigationButtonTouchDelegate(mCloseButton, false); + } setViewVisible(mBackButton, visible); - updateBackButtonTouchDelegate(visible); + updateNavigationButtonTouchDelegate(mBackButton, visible); + } + + public View getCloseButton() { + return mCloseButton; + } + + @VisibleForTesting + final void setCloseButton(View closeButton) { + mCloseButton = closeButton; + } + + /** + * Set the close button onClickListener to given listener. Can be null if the listener should + * be overridden so no callback is made. + */ + public void setCloseButtonListener(@Nullable View.OnClickListener listener) { + mCloseButton.setOnClickListener(listener); + } + + /** + * Set the back button visibility to the given visibility. + */ + public void setCloseButtonVisible(boolean visible) { + if (visible) { + setViewVisible(mBackButton, false); + updateNavigationButtonTouchDelegate(mBackButton, false); + } + setViewVisible(mCloseButton, visible); + updateNavigationButtonTouchDelegate(mCloseButton, visible); } /** diff --git a/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfig.java b/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfig.java index 00c0ea3..23ed198 100644 --- a/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfig.java +++ b/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfig.java @@ -28,6 +28,9 @@ public enum PartnerConfig { CONFIG_TOOLBAR_BUTTON_ICON_BACK( PartnerConfigKey.KEY_TOOLBAR_BUTTON_ICON_BACK, ResourceType.DRAWABLE), + CONFIG_TOOLBAR_BUTTON_ICON_CLOSE( + PartnerConfigKey.KEY_TOOLBAR_BUTTON_ICON_CLOSE, ResourceType.DRAWABLE), + CONFIG_TOOLBAR_BUTTON_FONT_FAMILY( PartnerConfigKey.KEY_TOOLBAR_BUTTON_FONT_FAMILY, ResourceType.STRING), diff --git a/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigKey.java b/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigKey.java index 32caceb..ed98c9f 100644 --- a/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigKey.java +++ b/library/main/src/com/android/car/setupwizardlib/partner/PartnerConfigKey.java @@ -26,6 +26,7 @@ import java.lang.annotation.RetentionPolicy; PartnerConfigKey.KEY_IMMERSIVE_MODE, PartnerConfigKey.KEY_TOOLBAR_BG_COLOR, PartnerConfigKey.KEY_TOOLBAR_BUTTON_ICON_BACK, + PartnerConfigKey.KEY_TOOLBAR_BUTTON_ICON_CLOSE, PartnerConfigKey.KEY_TOOLBAR_BUTTON_FONT_FAMILY, PartnerConfigKey.KEY_TOOLBAR_BUTTON_PADDING_HORIZONTAL, PartnerConfigKey.KEY_TOOLBAR_BUTTON_PADDING_VERTICAL, @@ -54,6 +55,8 @@ public @interface PartnerConfigKey { String KEY_TOOLBAR_BUTTON_ICON_BACK = "suw_compat_toolbar_button_icon_back"; + String KEY_TOOLBAR_BUTTON_ICON_CLOSE = "suw_compat_toolbar_button_icon_close"; + String KEY_TOOLBAR_BUTTON_FONT_FAMILY = "suw_compat_toolbar_button_font_family"; String KEY_TOOLBAR_BUTTON_TEXT_SIZE = "suw_compat_toolbar_button_text_size"; diff --git a/library/main/tests/robotests/res/values/attrs.xml b/library/main/tests/robotests/res/values/attrs.xml index 4454939..0591552 100644 --- a/library/main/tests/robotests/res/values/attrs.xml +++ b/library/main/tests/robotests/res/values/attrs.xml @@ -19,6 +19,8 @@ <declare-styleable name="CarSetupWizardBaseLayout"> <!-- Attributes related to the visibility of the back button --> <attr name="showBackButton" format="boolean"/> + <!-- Attributes related to the visibility of the close button --> + <attr name="showCloseButton" format="boolean"/> <!-- Attributes related to the visibility and text of the toolbar title --> <attr name="showToolbarTitle" format="boolean"/> diff --git a/library/main/tests/robotests/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayoutTest.java b/library/main/tests/robotests/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayoutTest.java index 6ec0c28..48d2c52 100644 --- a/library/main/tests/robotests/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayoutTest.java +++ b/library/main/tests/robotests/src/com/android/car/setupwizardlib/CarSetupWizardCompatLayoutTest.java @@ -101,8 +101,22 @@ public class CarSetupWizardCompatLayoutTest extends BaseRobolectricTest { } /** + * Test that {@link CarSetupWizardCompatLayout#setCloseButtonListener} does set the close button + * listener. + */ + @Test + public void testSetCloseButtonListener() { + View.OnClickListener spyListener = TestHelper.createSpyListener(); + + mCarSetupWizardCompatLayout.setCloseButtonListener(spyListener); + mCarSetupWizardCompatLayout.getCloseButton().performClick(); + Mockito.verify(spyListener).onClick(mCarSetupWizardCompatLayout.getCloseButton()); + } + + /** * Test that {@link CarSetupWizardCompatLayout#setBackButtonVisible} does set the view - * visible/not visible and calls updateBackButtonTouchDelegate. + * visible/not visible and calls + * {@link CarSetupWizardDesignLayout#updateNavigationButtonTouchDelegate(View, boolean)}. */ @Test public void testSetBackButtonVisibleTrue() { @@ -112,12 +126,18 @@ public class CarSetupWizardCompatLayoutTest extends BaseRobolectricTest { spyCarSetupWizardCompatLayout.setBackButtonVisible(true); View backButton = spyCarSetupWizardCompatLayout.getBackButton(); TestHelper.assertViewVisible(backButton); - Mockito.verify(spyCarSetupWizardCompatLayout).updateBackButtonTouchDelegate(true); + Mockito.verify(spyCarSetupWizardCompatLayout) + .updateNavigationButtonTouchDelegate(backButton, true); + View closeButton = spyCarSetupWizardCompatLayout.getCloseButton(); + TestHelper.assertViewNotVisible(closeButton); + Mockito.verify(spyCarSetupWizardCompatLayout) + .updateNavigationButtonTouchDelegate(closeButton, false); } /** * Test that {@link CarSetupWizardCompatLayout#setBackButtonVisible} does set the view - * visible/not visible and calls updateBackButtonTouchDelegate. + * visible/not visible and calls + * {@link CarSetupWizardDesignLayout#updateNavigationButtonTouchDelegate(View, boolean)}. */ @Test public void testSetBackButtonVisibleFalse() { @@ -127,7 +147,47 @@ public class CarSetupWizardCompatLayoutTest extends BaseRobolectricTest { spyCarSetupWizardCompatLayout.setBackButtonVisible(false); View backButton = spyCarSetupWizardCompatLayout.getBackButton(); TestHelper.assertViewNotVisible(backButton); - Mockito.verify(spyCarSetupWizardCompatLayout).updateBackButtonTouchDelegate(false); + Mockito.verify(spyCarSetupWizardCompatLayout) + .updateNavigationButtonTouchDelegate(backButton, false); + } + + /** + * Test that {@link CarSetupWizardCompatLayout#setCloseButtonVisible} does set the view + * visible/not visible and calls + * {@link CarSetupWizardDesignLayout#updateNavigationButtonTouchDelegate(View, boolean)}. + */ + @Test + public void testSetCloseButtonVisibleTrue() { + CarSetupWizardCompatLayout spyCarSetupWizardCompatLayout = + Mockito.spy(mCarSetupWizardCompatLayout); + + spyCarSetupWizardCompatLayout.setCloseButtonVisible(true); + View closeButton = spyCarSetupWizardCompatLayout.getCloseButton(); + TestHelper.assertViewVisible(closeButton); + Mockito.verify(spyCarSetupWizardCompatLayout) + .updateNavigationButtonTouchDelegate(closeButton, true); + View backButton = spyCarSetupWizardCompatLayout.getBackButton(); + TestHelper.assertViewNotVisible(backButton); + Mockito.verify(spyCarSetupWizardCompatLayout) + .updateNavigationButtonTouchDelegate(backButton, false); + } + + + /** + * Test that {@link CarSetupWizardCompatLayout#setCloseButtonVisible} does set the view + * visible/not visible and calls + * {@link CarSetupWizardDesignLayout#updateNavigationButtonTouchDelegate(View, boolean)}. + */ + @Test + public void testSetCloseButtonVisibleFalse() { + CarSetupWizardCompatLayout spyCarSetupWizardCompatLayout = + Mockito.spy(mCarSetupWizardCompatLayout); + + spyCarSetupWizardCompatLayout.setCloseButtonVisible(false); + View closeButton = spyCarSetupWizardCompatLayout.getCloseButton(); + TestHelper.assertViewNotVisible(closeButton); + Mockito.verify(spyCarSetupWizardCompatLayout) + .updateNavigationButtonTouchDelegate(closeButton, false); } /** |