diff options
author | Setup Wizard Team <android-setup-team-eng@google.com> | 2020-12-30 19:23:06 +0800 |
---|---|---|
committer | alexylli <alexylli@google.com> | 2020-12-31 10:47:36 +0800 |
commit | 6c15fbdff11497af53e2a9bdff042e0e89df2659 (patch) | |
tree | 14e6fb8ea965c7ec84ad2d57b9310f45d412f8ce /main | |
parent | 6c7dfb3e2434a01371394a45ea687df7e331d5d7 (diff) | |
download | setupdesign-6c15fbdff11497af53e2a9bdff042e0e89df2659.tar.gz |
Import updated Android Setupdesign Library 349536308
Copied from google3/third_party/java_src/android_libs/setupdesign
Test: mm
Included changes:
- 349536308 [BC][Stencil] Add partner resource for the item padding t...
- 349498664 [BC][Transition] Adds shared axis api for support lib's f...
- 349396975 adds java doc for TransitionHelper class
- 349384451 Make the padding start/end of ExpandableSwitchItem to fit...
- 349384008 [BC][Tranisition] Implement the API for BC activity trans...
- 349382331 Applying divider start/end margins to BC layout
- 349374941 [BC][Transition] Adds shared axis api for platform fragme...
- 349374546 [SetupDesign] Let the partnerStyleHelper to get partner r...
- 349360486 [SetupDesign] issue fix and refactoring
- 349347558 Support BC layout for outside setup screens
- 349265027 Update language to comply with Android’s inclusive langua...
- 349260624 [BC][Tranisition] Implement the API for BC activity trans...
- 349186993 Implement the API for BC activity transition
- 349006680 [BC][Stencil] Add partner resource for the item title tex...
- 348989675 Automated g4 rollback of changelist 348974409.
- 348983766 Automated g4 rollback of changelist 348976028.
- 348976028 [SetupDesign] refactor and improve the utils
- 348974409 Change the description textview from TextView to RichText...
- 348915728 [SetupDesign] Fix the condition for use partner heavy the...
- 348748997 Remove unnecessary null check
- 348729496 Cloned from CL 348561620 by 'g4 patch' and removed using ...
- 348611275 Add extra padding start/end of header container for BC la...
- 348586422 Fix backward transition with fade out meet abnormal issue.
- 348580285 [SUW][SetupDesign] Enable stencil config for auto text si...
- 348570510 [SetupDesign] remove the value for BC
- 348565251 Automated g4 rollback of changelist 348561620.
- 348561620 [BC][Stencil] Add partner resource for the icon margin to...
- 347789412 [BC][Stencil] Add partner resource for the layout margin ...
- 347548473 Check the flag of applying partner resource when extended...
- 347544485 Adjusts the javadoc for transition APIs
- 346907111 Fix legacy description doesn't apply partner resource
- 346894262 [BC][Stencil] Add partner resource for the description te...
- 346681228 Whenever sets the description, it also sets the visibilit...
- 346521136 [BC tranisition] Declare the interface for BC transition ...
- 346250818 Migrate SimMissing activity to new DescriptionMixin
- 346235546 [BC transition] Declare the interface to support new tran...
- 345997245 [BC][Stencil] Add partner resource for the header text ma...
- 345586018 [SetupDesign] Default enable the stencil heavy theme if e...
- 345388161 [BC][Stencil] Add partner resource for the header contain...
- 345182340 Create subtitle mixin for BC layout
- 345174090 [SetupDesign] Enable auto text size based on attr
PiperOrigin-RevId: 349536308
Change-Id: I6f9475b58106a2462c74892451c05c9d42eff21f
Diffstat (limited to 'main')
27 files changed, 1480 insertions, 124 deletions
diff --git a/main/res/layout/sud_glif_header.xml b/main/res/layout/sud_glif_header.xml index 0ff67bc..ea20993 100644 --- a/main/res/layout/sud_glif_header.xml +++ b/main/res/layout/sud_glif_header.xml @@ -47,4 +47,11 @@ android:inflatedId="@+id/sud_layout_progress" android:layout="@layout/sud_progress_bar" /> + <TextView + android:id="@+id/sud_layout_subtitle" + style="@style/SudGlifDescription" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone" /> + </LinearLayout> diff --git a/main/res/values-night/styles.xml b/main/res/values-night/styles.xml index 15c4028..ca94c12 100644 --- a/main/res/values-night/styles.xml +++ b/main/res/values-night/styles.xml @@ -22,6 +22,5 @@ <style name="SudThemeGlif.DayNight" parent="SudThemeGlif" /> <style name="SudThemeGlifV2.DayNight" parent="SudThemeGlifV2" /> <style name="SudThemeGlifV3.DayNight" parent="SudThemeGlifV3" /> - <style name="SudThemeGlifV4.DayNight" parent="SudThemeGlifV4" /> </resources> diff --git a/main/res/values-v21/styles.xml b/main/res/values-v21/styles.xml index 6a4df1b..c961745 100644 --- a/main/res/values-v21/styles.xml +++ b/main/res/values-v21/styles.xml @@ -54,10 +54,10 @@ <style name="SudItemContainer"> <item name="android:minHeight">?android:attr/listPreferredItemHeight</item> - <item name="android:paddingBottom">@dimen/sud_items_padding_vertical</item> + <item name="android:paddingBottom">@dimen/sud_items_padding_bottom</item> <item name="android:paddingEnd">?android:attr/listPreferredItemPaddingEnd</item> <item name="android:paddingStart">?android:attr/listPreferredItemPaddingStart</item> - <item name="android:paddingTop">@dimen/sud_items_padding_vertical</item> + <item name="android:paddingTop">@dimen/sud_items_padding_top</item> </style> <style name="SudItemTitle"> diff --git a/main/res/values/attrs.xml b/main/res/values/attrs.xml index f96a4f3..7262f70 100644 --- a/main/res/values/attrs.xml +++ b/main/res/values/attrs.xml @@ -233,4 +233,12 @@ <attr name="sudCollapsedSummary" format="string" localization="suggested" /> <attr name="sudExpandedSummary" format="string" localization="suggested" /> </declare-styleable> + + <declare-styleable name="SudDescriptionMixin"> + <attr name="sudDescriptionText" format="string" localization="suggested" /> + <attr name="sudDescriptionTextColor" format="reference|color" /> + <attr name="sudGlifDescriptionMarginTop" format="dimension" /> + <attr name="sudGlifDescriptionMarginBottom" format="dimension" /> + </declare-styleable> + </resources> diff --git a/main/res/values/dimens.xml b/main/res/values/dimens.xml index 273db2d..670743a 100644 --- a/main/res/values/dimens.xml +++ b/main/res/values/dimens.xml @@ -38,9 +38,6 @@ <dimen name="sud_glif_margin_start">24dp</dimen> <dimen name="sud_glif_margin_end">24dp</dimen> <dimen name="sud_glif_icon_margin_top">56dp</dimen> - <dimen name="sud_glif_v4_icon_margin_top">48dp</dimen> - <dimen name="sud_glif_v4_margin_start">40dp</dimen> - <dimen name="sud_glif_v4_margin_end">24dp</dimen> <dimen name="sud_glif_alert_dialog_corner_radius">8dp</dimen> <dimen name="sud_glif_v3_button_corner_radius">4dp</dimen> @@ -61,6 +58,7 @@ <dimen name="sud_description_line_spacing_extra">4sp</dimen> <dimen name="sud_description_text_size">16sp</dimen> + <!-- TODO: Remove sud_description_glif_margin_xxx once all apps migrate to sud_glif_description_margin_xxx --> <dimen name="sud_description_glif_margin_top">3dp</dimen> <dimen name="sud_description_glif_margin_bottom_lists">24dp</dimen> @@ -113,25 +111,26 @@ <dimen name="sud_glif_header_title_margin_top">16dp</dimen> <dimen name="sud_glif_header_title_margin_bottom">2dp</dimen> - <dimen name="sud_glif_v4_header_title_margin_top">24dp</dimen> - <dimen name="sud_glif_v4_header_title_margin_bottom">0dp</dimen> + <dimen name="sud_header_container_margin_bottom">0dp</dimen> <!-- This value leverages sud_description_glif_margin_top --> - <dimen name="sud_glif_subtitle_margin_top">3dp</dimen> - <dimen name="sud_glif_subtitle_margin_bottom">0dp</dimen> - <!-- TODO: Remove all attributes in Glifv4 after the stencil supports. --> - <dimen name="sud_glif_v4_subtitle_margin_top">24dp</dimen> - <dimen name="sud_glif_v4_subtitle_margin_bottom">0dp</dimen> + <dimen name="sud_glif_description_margin_top">3dp</dimen> + <dimen name="sud_glif_description_margin_bottom">12dp</dimen> <dimen name="sud_glif_icon_max_height">32dp</dimen> - <dimen name="sud_glif_v4_icon_max_height">48dp</dimen> <!-- Illustration --> <item name="sud_illustration_aspect_ratio" format="float" type="dimen">2.22</item> <!-- Items --> <dimen name="sud_items_icon_container_width">48dp</dimen> + <!-- TODO: Remove it when all attributes being used migrated into new one. --> <dimen name="sud_items_padding_vertical">15dp</dimen> <dimen name="sud_items_verbose_padding_vertical">20dp</dimen> + <dimen name="sud_items_title_text_size">16sp</dimen> + <dimen name="sud_items_summary_text_size">14sp</dimen> + <dimen name="sud_items_summary_margin_top">4dp</dimen> + <dimen name="sud_items_padding_top">15dp</dimen> + <dimen name="sud_items_padding_bottom">15dp</dimen> <!-- Ignore UnusedResources: can be used by clients --> <dimen name="sud_items_icon_divider_inset" tools:ignore="UnusedResources">88dp</dimen> diff --git a/main/res/values/styles.xml b/main/res/values/styles.xml index 055c8c8..f348651 100644 --- a/main/res/values/styles.xml +++ b/main/res/values/styles.xml @@ -134,9 +134,10 @@ <item name="sudGlifHeaderGravity">start</item> <item name="sudGlifSubtitleGravity">start</item> <item name="sucGlifHeaderMarginTop">@dimen/sud_glif_header_title_margin_top</item> - <item name="sucGlifSubtitleMarginTop">@dimen/sud_glif_subtitle_margin_top</item> + <item name="sudGlifDescriptionMarginTop">@dimen/sud_glif_description_margin_top</item> <item name="sucGlifHeaderMarginBottom">@dimen/sud_glif_header_title_margin_bottom</item> - <item name="sucGlifSubtitleMarginBottom">@dimen/sud_glif_subtitle_margin_bottom</item> + <item name="sudGlifDescriptionMarginBottom">@dimen/sud_glif_description_margin_bottom</item> + <item name="sucHeaderContainerMarginBottom">@dimen/sud_header_container_margin_bottom</item> <item name="sudGlifIconStyle">@style/SudGlifIcon</item> <item name="sucGlifIconMarginTop">@dimen/sud_glif_icon_margin_top</item> <item name="sudGlifIconSize">@dimen/sud_glif_icon_max_height</item> @@ -198,9 +199,10 @@ <item name="sudGlifHeaderGravity">start</item> <item name="sudGlifSubtitleGravity">start</item> <item name="sucGlifHeaderMarginTop">@dimen/sud_glif_header_title_margin_top</item> - <item name="sucGlifSubtitleMarginTop">@dimen/sud_glif_subtitle_margin_top</item> + <item name="sudGlifDescriptionMarginTop">@dimen/sud_glif_description_margin_top</item> <item name="sucGlifHeaderMarginBottom">@dimen/sud_glif_header_title_margin_bottom</item> - <item name="sucGlifSubtitleMarginBottom">@dimen/sud_glif_subtitle_margin_bottom</item> + <item name="sudGlifDescriptionMarginBottom">@dimen/sud_glif_description_margin_bottom</item> + <item name="sucHeaderContainerMarginBottom">@dimen/sud_header_container_margin_bottom</item> <item name="sudGlifIconStyle">@style/SudGlifIcon</item> <item name="sucGlifIconMarginTop">@dimen/sud_glif_icon_margin_top</item> <item name="sudGlifIconSize">@dimen/sud_glif_icon_max_height</item> @@ -288,30 +290,6 @@ </style> <style name="SudThemeGlifV3.Light" parent="SudBaseThemeGlifV3.Light" /> - <style name="SudThemeGlifV4" parent="SudThemeGlifV3"> - <!-- TODO: Remove all attributes in Glifv4 after the stencil supports. --> - <item name="sucGlifIconMarginTop">@dimen/sud_glif_v4_icon_margin_top</item> - <item name="sudMarginStart">@dimen/sud_glif_v4_margin_start</item> - <item name="sudMarginEnd">@dimen/sud_glif_v4_margin_end</item> - <item name="sudGlifIconSize">@dimen/sud_glif_v4_icon_max_height</item> - <item name="sucGlifHeaderMarginTop">@dimen/sud_glif_v4_header_title_margin_top</item> - <item name="sucGlifSubtitleMarginTop">@dimen/sud_glif_v4_subtitle_margin_top</item> - <item name="sucGlifHeaderMarginBottom">@dimen/sud_glif_v4_header_title_margin_bottom</item> - <item name="sucGlifSubtitleMarginBottom">@dimen/sud_glif_v4_subtitle_margin_bottom</item> - </style> - - <style name="SudThemeGlifV4.Light" parent="SudThemeGlifV3.Light"> - <!-- TODO: Remove all attributes in Glifv4 after the stencil supports. --> - <item name="sucGlifIconMarginTop">@dimen/sud_glif_v4_icon_margin_top</item> - <item name="sudMarginStart">@dimen/sud_glif_v4_margin_start</item> - <item name="sudMarginEnd">@dimen/sud_glif_v4_margin_end</item> - <item name="sudGlifIconSize">@dimen/sud_glif_v4_icon_max_height</item> - <item name="sucGlifHeaderMarginTop">@dimen/sud_glif_v4_header_title_margin_top</item> - <item name="sucGlifSubtitleMarginTop">@dimen/sud_glif_v4_subtitle_margin_top</item> - <item name="sucGlifHeaderMarginBottom">@dimen/sud_glif_v4_header_title_margin_bottom</item> - <item name="sucGlifSubtitleMarginBottom">@dimen/sud_glif_v4_subtitle_margin_bottom</item> - </style> - <style name="Animation.SudWindowAnimation" parent="@android:style/Animation.Activity"> <item name="android:activityOpenEnterAnimation">@anim/sud_slide_next_in</item> <item name="android:activityOpenExitAnimation">@anim/sud_slide_next_out</item> @@ -324,7 +302,6 @@ <style name="SudThemeGlif.DayNight" parent="SudThemeGlif.Light" /> <style name="SudThemeGlifV2.DayNight" parent="SudThemeGlifV2.Light" /> <style name="SudThemeGlifV3.DayNight" parent="SudThemeGlifV3.Light" /> - <style name="SudThemeGlifV4.DayNight" parent="SudThemeGlifV4.Light" /> <!-- Content styles --> @@ -578,12 +555,12 @@ <style name="SudItemContainer"> <item name="android:minHeight">?android:attr/listPreferredItemHeight</item> - <item name="android:paddingBottom">@dimen/sud_items_padding_vertical</item> + <item name="android:paddingBottom">@dimen/sud_items_padding_bottom</item> <item name="android:paddingEnd" tools:ignore="NewApi">?attr/listPreferredItemPaddingRight</item> <item name="android:paddingLeft">?attr/listPreferredItemPaddingLeft</item> <item name="android:paddingRight">?attr/listPreferredItemPaddingRight</item> <item name="android:paddingStart" tools:ignore="NewApi">?attr/listPreferredItemPaddingLeft</item> - <item name="android:paddingTop">@dimen/sud_items_padding_vertical</item> + <item name="android:paddingTop">@dimen/sud_items_padding_top</item> </style> <style name="SudItemContainer.Description" parent="SudItemContainer"> @@ -654,21 +631,20 @@ <item name="android:textColor">?android:attr/textColorPrimary</item> </style> - <style name="SudGlifSubtitleTitle"> - <item name="android:gravity">?attr/sudGlifSubtitleGravity</item> - <item name="android:layout_marginBottom">?attr/sucGlifSubtitleMarginBottom</item> + <style name="SudGlifDescription" parent="SudDescription.Glif"> + <item name="android:layout_marginTop">?attr/sudGlifDescriptionMarginTop</item> + <item name="android:layout_marginBottom">?attr/sudGlifDescriptionMarginBottom</item> <item name="android:layout_marginLeft">?attr/sudMarginStart</item> + <item name="android:layout_marginStart">?attr/sudMarginStart</item> <item name="android:layout_marginRight">?attr/sudMarginEnd</item> - <item name="android:layout_marginTop">?attr/sucGlifSubtitleMarginTop</item> + <item name="android:layout_marginEnd">?attr/sudMarginEnd</item> <item name="android:fontFamily" tools:targetApi="jelly_bean">@string/sudFontSecondary</item> - <item name="android:textAlignment" tools:targetApi="jelly_bean_mr1">gravity</item> <item name="android:textColor">?android:attr/textColorPrimary</item> - <item name="android:lineSpacingExtra">@dimen/sud_description_line_spacing_extra</item> - <item name="android:textAppearance">@style/TextAppearance.SudDescription</item> </style> <style name="SudGlifHeaderContainer"> <item name="android:gravity">?attr/sudGlifHeaderGravity</item> + <item name="android:layout_marginBottom">?attr/sucHeaderContainerMarginBottom</item> </style> <style name="SudGlifIcon"> @@ -686,12 +662,12 @@ </style> <style name="TextAppearance.SudGlifItemTitle" parent="android:TextAppearance"> - <item name="android:textSize">16sp</item> + <item name="android:textSize">@dimen/sud_items_title_text_size</item> <item name="android:textColor">?android:attr/textColorPrimary</item> </style> <style name="TextAppearance.SudGlifItemSummary" parent="android:TextAppearance"> - <item name="android:textSize">14sp</item> + <item name="android:textSize">@dimen/sud_items_summary_text_size</item> <item name="android:textColor">?android:attr/textColorSecondary</item> </style> diff --git a/main/src/com/google/android/setupdesign/GlifLayout.java b/main/src/com/google/android/setupdesign/GlifLayout.java index 4cf9e24..19eb50a 100644 --- a/main/src/com/google/android/setupdesign/GlifLayout.java +++ b/main/src/com/google/android/setupdesign/GlifLayout.java @@ -39,6 +39,7 @@ import com.google.android.setupcompat.PartnerCustomizationLayout; import com.google.android.setupcompat.partnerconfig.PartnerConfig; import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper; import com.google.android.setupcompat.template.StatusBarMixin; +import com.google.android.setupdesign.template.DescriptionMixin; import com.google.android.setupdesign.template.HeaderMixin; import com.google.android.setupdesign.template.IconMixin; import com.google.android.setupdesign.template.IllustrationProgressMixin; @@ -46,6 +47,7 @@ import com.google.android.setupdesign.template.ProgressBarMixin; import com.google.android.setupdesign.template.RequireScrollMixin; import com.google.android.setupdesign.template.ScrollViewScrollHandlingDelegate; import com.google.android.setupdesign.util.DescriptionStyler; +import com.google.android.setupdesign.util.LayoutStyler; /** * Layout for the GLIF theme used in Setup Wizard for N. @@ -68,8 +70,6 @@ import com.google.android.setupdesign.util.DescriptionStyler; */ public class GlifLayout extends PartnerCustomizationLayout { - private static final String TAG = "GlifLayout"; - private ColorStateList primaryColor; private boolean backgroundPatterned = true; @@ -114,6 +114,7 @@ public class GlifLayout extends PartnerCustomizationLayout { applyPartnerHeavyThemeResource = shouldApplyPartnerResource() && usePartnerHeavyTheme; registerMixin(HeaderMixin.class, new HeaderMixin(this, attrs, defStyleAttr)); + registerMixin(DescriptionMixin.class, new DescriptionMixin(this, attrs, defStyleAttr)); registerMixin(IconMixin.class, new IconMixin(this, attrs, defStyleAttr)); registerMixin(ProgressBarMixin.class, new ProgressBarMixin(this)); registerMixin(IllustrationProgressMixin.class, new IllustrationProgressMixin(this)); @@ -133,6 +134,18 @@ public class GlifLayout extends PartnerCustomizationLayout { if (applyPartnerHeavyThemeResource) { updateContentBackgroundColorWithPartnerConfig(); + + View view = findManagedViewById(R.id.sud_layout_content); + if (view != null) { + // The margin of content is defined by @style/SudContentFrame. The Setupdesign library + // cannot + // obtain the content resource ID of the client, so the value of the content margin cannot + // be adjusted through GlifLayout. If the margin sides are changed through the partner + // config, it can only be based on the increased or decreased value to adjust the value of + // pading. In this way, the value of content margin plus padding will be equal to the value + // of partner config. + LayoutStyler.applyPartnerCustomizationExtraPaddingStyle(view); + } } ColorStateList backgroundColor = @@ -155,12 +168,14 @@ public class GlifLayout extends PartnerCustomizationLayout { super.onFinishInflate(); getMixin(IconMixin.class).tryApplyPartnerCustomizationStyle(); getMixin(HeaderMixin.class).tryApplyPartnerCustomizationStyle(); + getMixin(DescriptionMixin.class).tryApplyPartnerCustomizationStyle(); tryApplyPartnerCustomizationStyleToShortDescription(); } + // TODO: remove when all sud_layout_description has migrated to + // DescriptionMixin(sud_layout_subtitle) private void tryApplyPartnerCustomizationStyleToShortDescription() { - TextView description = - this.findManagedViewById(com.google.android.setupdesign.R.id.sud_layout_description); + TextView description = this.findManagedViewById(R.id.sud_layout_description); if (description != null) { if (applyPartnerHeavyThemeResource) { DescriptionStyler.applyPartnerCustomizationHeavyStyle(description); @@ -221,6 +236,22 @@ public class GlifLayout extends PartnerCustomizationLayout { return getMixin(HeaderMixin.class).getText(); } + public TextView getDescriptionTextView() { + return getMixin(DescriptionMixin.class).getTextView(); + } + + public void setDescriptionText(int title) { + getMixin(DescriptionMixin.class).setText(title); + } + + public void setDescriptionText(CharSequence title) { + getMixin(DescriptionMixin.class).setText(title); + } + + public CharSequence getDescriptionText() { + return getMixin(DescriptionMixin.class).getText(); + } + public void setHeaderColor(ColorStateList color) { getMixin(HeaderMixin.class).setTextColor(color); } @@ -320,7 +351,10 @@ public class GlifLayout extends PartnerCustomizationLayout { * Returns if the current layout/activity applies heavy partner customized configurations or not. */ public boolean shouldApplyPartnerHeavyThemeResource() { - return applyPartnerHeavyThemeResource; + + return applyPartnerHeavyThemeResource + || (shouldApplyPartnerResource() + && PartnerConfigHelper.shouldApplyExtendedPartnerConfig(getContext())); } /** Updates the background color of this layout with the partner-customizable background color. */ diff --git a/main/src/com/google/android/setupdesign/items/ExpandableSwitchItem.java b/main/src/com/google/android/setupdesign/items/ExpandableSwitchItem.java index 42438d6..78cf0a9 100644 --- a/main/src/com/google/android/setupdesign/items/ExpandableSwitchItem.java +++ b/main/src/com/google/android/setupdesign/items/ExpandableSwitchItem.java @@ -35,6 +35,8 @@ import android.view.View.OnClickListener; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.TextView; import com.google.android.setupdesign.R; +import com.google.android.setupdesign.util.LayoutStyler; +import com.google.android.setupdesign.util.PartnerStyleHelper; import com.google.android.setupdesign.view.CheckableLinearLayout; /** @@ -179,6 +181,10 @@ public class ExpandableSwitchItem extends SwitchItem // Expandable switch item has focusability on the expandable layout on the left, and the // switch on the right, but not the item itself. view.setFocusable(false); + + if (PartnerStyleHelper.shouldApplyPartnerHeavyThemeResource(view)) { + LayoutStyler.applyPartnerCustomizationLayoutPaddingStyle(content); + } } @Override diff --git a/main/src/com/google/android/setupdesign/items/Item.java b/main/src/com/google/android/setupdesign/items/Item.java index 0a79be9..d3e6a8c 100644 --- a/main/src/com/google/android/setupdesign/items/Item.java +++ b/main/src/com/google/android/setupdesign/items/Item.java @@ -30,6 +30,9 @@ import android.widget.TextView; import androidx.annotation.ColorInt; import androidx.annotation.Nullable; import com.google.android.setupdesign.R; +import com.google.android.setupdesign.util.ItemStyler; +import com.google.android.setupdesign.util.LayoutStyler; +import com.google.android.setupdesign.util.PartnerStyleHelper; /** * Definition of an item in an {@link ItemHierarchy}. An item is usually defined in XML and inflated @@ -200,6 +203,18 @@ public class Item extends AbstractItem { } view.setId(getViewId()); + + if (PartnerStyleHelper.shouldApplyPartnerHeavyThemeResource(view)) { + // ExpandableSwitchItem uses its child view to apply the style SudItemContainer. It is not + // possible to directly adjust the padding start/end of the item's layout here. It needs to + // get its child view to adjust it first, so skip the Layout padding adjustment. + // If the item view is a header layout, it doesn't need to adjust the layout padding start/end + // here. It will be adjusted by HeaderMixin. + if (!(this instanceof ExpandableSwitchItem) && view.getId() != R.id.sud_layout_header) { + LayoutStyler.applyPartnerCustomizationLayoutPaddingStyle(view); + } + ItemStyler.applyPartnerCustomizationItemStyle(view); + } } /** diff --git a/main/src/com/google/android/setupdesign/template/DescriptionMixin.java b/main/src/com/google/android/setupdesign/template/DescriptionMixin.java new file mode 100644 index 0000000..b78ee1f --- /dev/null +++ b/main/src/com/google/android/setupdesign/template/DescriptionMixin.java @@ -0,0 +1,160 @@ +/* + * 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. + */ + +package com.google.android.setupdesign.template; + +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.View; +import android.widget.TextView; +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.google.android.setupcompat.PartnerCustomizationLayout; +import com.google.android.setupcompat.internal.TemplateLayout; +import com.google.android.setupcompat.template.Mixin; +import com.google.android.setupdesign.R; +import com.google.android.setupdesign.util.HeaderAreaStyler; +import com.google.android.setupdesign.util.PartnerStyleHelper; + +/** + * A {@link com.google.android.setupcompat.template.Mixin} for setting and getting the description + * text. + */ +public class DescriptionMixin implements Mixin { + + private final TemplateLayout templateLayout; + + /** + * A {@link com.google.android.setupcompat.template.Mixin} for setting and getting the + * description. + * + * @param layout The layout this Mixin belongs to + * @param attrs XML attributes given to the layout + * @param defStyleAttr The default style attribute as given to the constructor of the layout + */ + public DescriptionMixin( + @NonNull TemplateLayout layout, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { + templateLayout = layout; + + final TypedArray a = + layout + .getContext() + .obtainStyledAttributes(attrs, R.styleable.SudDescriptionMixin, defStyleAttr, 0); + + // Set the description text + final CharSequence descriptionText = + a.getText(R.styleable.SudDescriptionMixin_sudDescriptionText); + if (descriptionText != null) { + setText(descriptionText); + } + // Set the description text color + final ColorStateList descriptionTextColor = + a.getColorStateList(R.styleable.SudDescriptionMixin_sudDescriptionTextColor); + if (descriptionTextColor != null) { + setTextColor(descriptionTextColor); + } + + a.recycle(); + } + + /** + * Applies the partner customizations to the description text (contains text alignment) and + * background, if apply heavy theme resource, it will apply all partner customizations, otherwise, + * only apply alignment style. + */ + public void tryApplyPartnerCustomizationStyle() { + TextView description = templateLayout.findManagedViewById(R.id.sud_layout_subtitle); + boolean partnerHeavyThemeLayout = PartnerStyleHelper.isPartnerHeavyThemeLayout(templateLayout); + if (partnerHeavyThemeLayout) { + if (description != null) { + HeaderAreaStyler.applyPartnerCustomizationDescriptionHeavyStyle(description); + } + } else if (templateLayout instanceof PartnerCustomizationLayout + && ((PartnerCustomizationLayout) templateLayout).shouldApplyPartnerResource()) { + if (description != null) { + HeaderAreaStyler.applyPartnerCustomizationDescriptionLightStyle(description); + } + } + } + + /** Returns the TextView displaying the description. */ + public TextView getTextView() { + return (TextView) templateLayout.findManagedViewById(R.id.sud_layout_subtitle); + } + + /** + * Sets the description text and also sets the text visibility to visble. This can also be set via + * the XML attribute {@code app:sudDescriptionText}. + * + * @param title The resource ID of the text to be set as description + */ + public void setText(int title) { + final TextView titleView = getTextView(); + if (titleView != null) { + titleView.setText(title); + setVisibility(View.VISIBLE); + } + } + + /** + * Sets the description text and also sets the text visibility to visble. This can also be set via + * the XML attribute {@code app:sudDescriptionText}. + * + * @param title The text to be set as description + */ + public void setText(CharSequence title) { + final TextView titleView = getTextView(); + if (titleView != null) { + titleView.setText(title); + setVisibility(View.VISIBLE); + } + } + + /** Returns the current description text. */ + public CharSequence getText() { + final TextView titleView = getTextView(); + return titleView != null ? titleView.getText() : null; + } + + /** Sets the visibility of description text */ + public void setVisibility(int visibility) { + final TextView titleView = getTextView(); + if (titleView != null) { + titleView.setVisibility(visibility); + } + } + + /** + * Sets the color of the description text. This can also be set via XML using {@code + * app:sudDescriptionTextColor}. + * + * @param color The text color of the description + */ + public void setTextColor(ColorStateList color) { + final TextView titleView = getTextView(); + if (titleView != null) { + titleView.setTextColor(color); + } + } + + /** Returns the current text color of the description. */ + public ColorStateList getTextColor() { + final TextView titleView = getTextView(); + return titleView != null ? titleView.getTextColors() : null; + } +} diff --git a/main/src/com/google/android/setupdesign/template/HeaderMixin.java b/main/src/com/google/android/setupdesign/template/HeaderMixin.java index ba52db3..d040c94 100644 --- a/main/src/com/google/android/setupdesign/template/HeaderMixin.java +++ b/main/src/com/google/android/setupdesign/template/HeaderMixin.java @@ -16,20 +16,30 @@ package com.google.android.setupdesign.template; +import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; +import android.os.Build; import android.util.AttributeSet; +import android.util.Log; +import android.util.TypedValue; +import android.view.View; +import android.view.ViewGroup; import android.view.ViewParent; +import android.view.ViewTreeObserver; import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.AttrRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.google.android.setupcompat.PartnerCustomizationLayout; +import androidx.annotation.VisibleForTesting; import com.google.android.setupcompat.internal.TemplateLayout; +import com.google.android.setupcompat.partnerconfig.PartnerConfig; +import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper; import com.google.android.setupcompat.template.Mixin; import com.google.android.setupdesign.R; import com.google.android.setupdesign.util.HeaderAreaStyler; +import com.google.android.setupdesign.util.LayoutStyler; import com.google.android.setupdesign.util.PartnerStyleHelper; /** @@ -38,6 +48,12 @@ import com.google.android.setupdesign.util.PartnerStyleHelper; public class HeaderMixin implements Mixin { private final TemplateLayout templateLayout; + @VisibleForTesting boolean autoTextSizeEnabled = false; + private float headerAutoSizeMaxTextSizeInPx; + private float headerAutoSizeMinTextSizeInPx; + private float headerAutoSizeLineExtraSpacingInPx; + private int headerAutoSizeMaxLineOfMaxSize; + private static final int AUTO_SIZE_DEFAULT_MAX_LINES = 6; /** * A {@link com.google.android.setupcompat.template.Mixin} for setting and getting the Header. @@ -55,42 +71,99 @@ public class HeaderMixin implements Mixin { .getContext() .obtainStyledAttributes(attrs, R.styleable.SucHeaderMixin, defStyleAttr, 0); - // Set the header text final CharSequence headerText = a.getText(R.styleable.SucHeaderMixin_sucHeaderText); + final ColorStateList headerTextColor = + a.getColorStateList(R.styleable.SucHeaderMixin_sucHeaderTextColor); + + a.recycle(); + + // overlay the Auto size config settings + updateAutoTextSizeWithPartnerConfig(); + + // Set the header text if (headerText != null) { setText(headerText); } // Set the header text color - final ColorStateList headerTextColor = - a.getColorStateList(R.styleable.SucHeaderMixin_sucHeaderTextColor); if (headerTextColor != null) { setTextColor(headerTextColor); } + } - a.recycle(); + private void updateAutoTextSizeWithPartnerConfig() { + Context context = templateLayout.getContext(); + if (!PartnerStyleHelper.isPartnerHeavyThemeLayout(templateLayout) + || !PartnerConfigHelper.shouldApplyExtendedPartnerConfig(context)) { + autoTextSizeEnabled = false; + return; + } + // overridden by partner resource + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_HEADER_AUTO_SIZE_ENABLED)) { + autoTextSizeEnabled = + PartnerConfigHelper.get(context) + .getBoolean( + context, PartnerConfig.CONFIG_HEADER_AUTO_SIZE_ENABLED, autoTextSizeEnabled); + } + if (!autoTextSizeEnabled) { + return; + } + + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_HEADER_AUTO_SIZE_MAX_TEXT_SIZE)) { + headerAutoSizeMaxTextSizeInPx = + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_HEADER_AUTO_SIZE_MAX_TEXT_SIZE); + } + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_HEADER_AUTO_SIZE_MIN_TEXT_SIZE)) { + headerAutoSizeMinTextSizeInPx = + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_HEADER_AUTO_SIZE_MIN_TEXT_SIZE); + } + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_HEADER_AUTO_SIZE_LINE_SPACING_EXTRA)) { + headerAutoSizeLineExtraSpacingInPx = + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_HEADER_AUTO_SIZE_LINE_SPACING_EXTRA); + } + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_HEADER_AUTO_SIZE_MAX_LINE_OF_MAX_SIZE)) { + headerAutoSizeMaxLineOfMaxSize = + PartnerConfigHelper.get(context) + .getInteger(context, PartnerConfig.CONFIG_HEADER_AUTO_SIZE_MAX_LINE_OF_MAX_SIZE, 0); + } + if ((headerAutoSizeMaxLineOfMaxSize < 1) + || (headerAutoSizeMinTextSizeInPx <= 0) + || (headerAutoSizeMaxTextSizeInPx < headerAutoSizeMinTextSizeInPx)) { + Log.w("HeaderMixin", "Invalid configs, disable auto text size."); + autoTextSizeEnabled = false; + } } /** - * Applies the partner customizations to the header text (contains text alignment) and background, - * if apply heavy theme resource, it will apply all partner customizations, otherwise, only apply - * alignment style. + * Applies the partner customizations to the header text (contains text alignment), background, + * and margin. If apply heavy theme resource, it will apply all partner customizations, otherwise, + * only apply alignment style. In addition, if only enable extended customized flag, the margin + * style will be applied. */ public void tryApplyPartnerCustomizationStyle() { TextView header = templateLayout.findManagedViewById(R.id.suc_layout_title); + boolean partnerLightThemeLayout = PartnerStyleHelper.isPartnerLightThemeLayout(templateLayout); boolean partnerHeavyThemeLayout = PartnerStyleHelper.isPartnerHeavyThemeLayout(templateLayout); if (partnerHeavyThemeLayout) { - if (header != null) { - HeaderAreaStyler.applyPartnerCustomizationHeaderHeavyStyle(header); - } - LinearLayout headerLayout = templateLayout.findManagedViewById(R.id.sud_layout_header); - if (headerLayout != null) { - HeaderAreaStyler.applyPartnerCustomizationHeaderAreaStyle(headerLayout); - } - } else if (templateLayout instanceof PartnerCustomizationLayout - && ((PartnerCustomizationLayout) templateLayout).shouldApplyPartnerResource()) { - if (header != null) { - HeaderAreaStyler.applyPartnerCustomizationHeaderLightStyle(header); - } + View headerAreaView = templateLayout.findManagedViewById(R.id.sud_layout_header); + HeaderAreaStyler.applyPartnerCustomizationHeaderHeavyStyle(header); + HeaderAreaStyler.applyPartnerCustomizationHeaderAreaStyle((ViewGroup) headerAreaView); + LayoutStyler.applyPartnerCustomizationExtraPaddingStyle(headerAreaView); + // overlay the Auto size config settings + updateAutoTextSizeWithPartnerConfig(); + } else if (partnerLightThemeLayout) { + HeaderAreaStyler.applyPartnerCustomizationHeaderLightStyle(header); + } + if (autoTextSizeEnabled) { + // Override the text size setting of the header + autoAdjustTextSize(header); } } @@ -107,6 +180,10 @@ public class HeaderMixin implements Mixin { public void setText(int title) { final TextView titleView = getTextView(); if (titleView != null) { + if (autoTextSizeEnabled) { + // Override the text size setting of the header + autoAdjustTextSize(titleView); + } titleView.setText(title); } } @@ -119,10 +196,52 @@ public class HeaderMixin implements Mixin { public void setText(CharSequence title) { final TextView titleView = getTextView(); if (titleView != null) { + if (autoTextSizeEnabled) { + // Override the text size setting of the header + autoAdjustTextSize(titleView); + } titleView.setText(title); } } + private void autoAdjustTextSize(TextView titleView) { + if (titleView == null) { + return; + } + // preset as the max size + titleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, headerAutoSizeMaxTextSizeInPx); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + titleView.setLineHeight( + Math.round(headerAutoSizeLineExtraSpacingInPx + headerAutoSizeMaxTextSizeInPx)); + } + titleView.setMaxLines(AUTO_SIZE_DEFAULT_MAX_LINES); + + // reset text size if the line count for max text size > headerAutoSizeMaxLineOfMaxTextSize + titleView + .getViewTreeObserver() + .addOnPreDrawListener( + new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + // Remove listener to avoid this called every frame + titleView.getViewTreeObserver().removeOnPreDrawListener(this); + int lineCount = titleView.getLineCount(); + if (lineCount > headerAutoSizeMaxLineOfMaxSize) { + // reset text size + titleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, headerAutoSizeMinTextSizeInPx); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + titleView.setLineHeight( + Math.round( + headerAutoSizeLineExtraSpacingInPx + headerAutoSizeMinTextSizeInPx)); + } + titleView.invalidate(); + return false; // false to skip this frame + } + return true; + } + }); + } + /** Returns the current header text. */ public CharSequence getText() { final TextView titleView = getTextView(); diff --git a/main/src/com/google/android/setupdesign/template/IconMixin.java b/main/src/com/google/android/setupdesign/template/IconMixin.java index f674c01..964f712 100644 --- a/main/src/com/google/android/setupdesign/template/IconMixin.java +++ b/main/src/com/google/android/setupdesign/template/IconMixin.java @@ -28,7 +28,6 @@ import android.view.ViewGroup.LayoutParams; import android.widget.ImageView; import androidx.annotation.ColorInt; import androidx.annotation.DrawableRes; -import com.google.android.setupcompat.PartnerCustomizationLayout; import com.google.android.setupcompat.internal.TemplateLayout; import com.google.android.setupcompat.template.Mixin; import com.google.android.setupdesign.R; @@ -67,14 +66,17 @@ public class IconMixin implements Mixin { } final TypedArray a = - context.obtainStyledAttributes(attrs, R.styleable.SudIconMixin, defStyleAttr, 0); + context.obtainStyledAttributes( + attrs, R.styleable.SudIconMixin, defStyleAttr, /* defStyleRes= */ 0); - final @DrawableRes int icon = a.getResourceId(R.styleable.SudIconMixin_android_icon, 0); + final @DrawableRes int icon = + a.getResourceId(R.styleable.SudIconMixin_android_icon, /* defValue= */ 0); if (icon != 0) { setIcon(icon); } - final boolean upscaleIcon = a.getBoolean(R.styleable.SudIconMixin_sudUpscaleIcon, false); + final boolean upscaleIcon = + a.getBoolean(R.styleable.SudIconMixin_sudUpscaleIcon, /* defValue= */ false); setUpscaleIcon(upscaleIcon); final @ColorInt int iconTint = @@ -88,13 +90,7 @@ public class IconMixin implements Mixin { /** Tries to apply the partner customization to the header icon. */ public void tryApplyPartnerCustomizationStyle() { - if (templateLayout instanceof PartnerCustomizationLayout - && ((PartnerCustomizationLayout) templateLayout).shouldApplyPartnerResource()) { - ImageView iconImage = templateLayout.findManagedViewById(R.id.sud_layout_icon); - if (iconImage != null) { - HeaderAreaStyler.applyPartnerCustomizationIconStyle(iconImage); - } - } + HeaderAreaStyler.applyPartnerCustomizationIconStyle(getView(), templateLayout); } /** diff --git a/main/src/com/google/android/setupdesign/template/IllustrationProgressMixin.java b/main/src/com/google/android/setupdesign/template/IllustrationProgressMixin.java index 558d000..23b9fa0 100644 --- a/main/src/com/google/android/setupdesign/template/IllustrationProgressMixin.java +++ b/main/src/com/google/android/setupdesign/template/IllustrationProgressMixin.java @@ -37,8 +37,14 @@ import com.google.android.setupdesign.GlifLayout; import com.google.android.setupdesign.R; import com.google.android.setupdesign.view.IllustrationVideoView; -/** A {@link Mixin} for showing a progress illustration. */ +// TODO: remove this mixin after migrate to new GlifLoadingLayout +/** + * A {@link Mixin} for showing a progress illustration. + * + * @deprecated Will be replaced by GlifLoadingLayout. + */ @TargetApi(VERSION_CODES.ICE_CREAM_SANDWICH) +@Deprecated public class IllustrationProgressMixin implements Mixin { private final GlifLayout glifLayout; diff --git a/main/src/com/google/android/setupdesign/template/ListMixin.java b/main/src/com/google/android/setupdesign/template/ListMixin.java index f88fa94..0ba5b0a 100644 --- a/main/src/com/google/android/setupdesign/template/ListMixin.java +++ b/main/src/com/google/android/setupdesign/template/ListMixin.java @@ -30,12 +30,15 @@ import androidx.annotation.AttrRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.google.android.setupcompat.internal.TemplateLayout; +import com.google.android.setupcompat.partnerconfig.PartnerConfig; +import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper; import com.google.android.setupcompat.template.Mixin; import com.google.android.setupdesign.R; import com.google.android.setupdesign.items.ItemAdapter; import com.google.android.setupdesign.items.ItemGroup; import com.google.android.setupdesign.items.ItemInflater; import com.google.android.setupdesign.util.DrawableLayoutDirectionHelper; +import com.google.android.setupdesign.util.PartnerStyleHelper; /** A {@link Mixin} for interacting with ListViews. */ public class ListMixin implements Mixin { @@ -71,6 +74,23 @@ public class ListMixin implements Mixin { int dividerInsetStart = a.getDimensionPixelSize(R.styleable.SudListMixin_sudDividerInsetStart, 0); int dividerInsetEnd = a.getDimensionPixelSize(R.styleable.SudListMixin_sudDividerInsetEnd, 0); + + if (PartnerStyleHelper.shouldApplyPartnerHeavyThemeResource(templateLayout)) { + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_LAYOUT_MARGIN_START)) { + dividerInsetStart = + (int) + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_LAYOUT_MARGIN_START); + } + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_LAYOUT_MARGIN_END)) { + dividerInsetEnd = + (int) + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_LAYOUT_MARGIN_END); + } + } setDividerInsets(dividerInsetStart, dividerInsetEnd); } a.recycle(); diff --git a/main/src/com/google/android/setupdesign/template/RecyclerMixin.java b/main/src/com/google/android/setupdesign/template/RecyclerMixin.java index 83f9d58..fb3e06d 100644 --- a/main/src/com/google/android/setupdesign/template/RecyclerMixin.java +++ b/main/src/com/google/android/setupdesign/template/RecyclerMixin.java @@ -30,6 +30,8 @@ import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.google.android.setupcompat.internal.TemplateLayout; +import com.google.android.setupcompat.partnerconfig.PartnerConfig; +import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper; import com.google.android.setupcompat.template.Mixin; import com.google.android.setupdesign.DividerItemDecoration; import com.google.android.setupdesign.GlifLayout; @@ -38,6 +40,7 @@ import com.google.android.setupdesign.items.ItemHierarchy; import com.google.android.setupdesign.items.ItemInflater; import com.google.android.setupdesign.items.RecyclerItemAdapter; import com.google.android.setupdesign.util.DrawableLayoutDirectionHelper; +import com.google.android.setupdesign.util.PartnerStyleHelper; import com.google.android.setupdesign.view.HeaderRecyclerView; import com.google.android.setupdesign.view.HeaderRecyclerView.HeaderAdapter; @@ -126,6 +129,23 @@ public class RecyclerMixin implements Mixin { a.getDimensionPixelSize(R.styleable.SudRecyclerMixin_sudDividerInsetStart, 0); int dividerInsetEnd = a.getDimensionPixelSize(R.styleable.SudRecyclerMixin_sudDividerInsetEnd, 0); + + if (PartnerStyleHelper.shouldApplyPartnerHeavyThemeResource(templateLayout)) { + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_LAYOUT_MARGIN_START)) { + dividerInsetStart = + (int) + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_LAYOUT_MARGIN_START); + } + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_LAYOUT_MARGIN_END)) { + dividerInsetEnd = + (int) + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_LAYOUT_MARGIN_END); + } + } setDividerInsets(dividerInsetStart, dividerInsetEnd); } diff --git a/main/src/com/google/android/setupdesign/transition/TransitionHelper.java b/main/src/com/google/android/setupdesign/transition/TransitionHelper.java index 86b3dfa..1836a11 100644 --- a/main/src/com/google/android/setupdesign/transition/TransitionHelper.java +++ b/main/src/com/google/android/setupdesign/transition/TransitionHelper.java @@ -17,14 +17,29 @@ package com.google.android.setupdesign.transition; import android.app.Activity; +import android.app.ActivityOptions; +import android.app.Fragment; +import android.content.Intent; import android.content.res.TypedArray; +import android.os.Build; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; +import android.os.Parcelable; +import android.util.Log; +import android.view.Window; import androidx.annotation.IntDef; +import com.google.android.material.transition.platform.MaterialSharedAxis; +import com.google.android.setupcompat.partnerconfig.PartnerConfig; +import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper; import com.google.android.setupdesign.R; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +/** Helper class for apply the transition to the pages which uses platform version. */ public class TransitionHelper { + private static final String TAG = "TransitionHelper"; + /* * In Setup Wizard, all Just-a-sec style screens (i.e. screens that has an indeterminate * progress bar and automatically finishes itself), should do a cross-fade when entering or @@ -64,7 +79,8 @@ public class TransitionHelper { TRANSITION_FRAMEWORK_DEFAULT, TRANSITION_SLIDE, TRANSITION_FADE, - TRANSITION_FRAMEWORK_DEFAULT_PRE_P + TRANSITION_FRAMEWORK_DEFAULT_PRE_P, + TRANSITION_CAPTIVE, }) public @interface TransitionType {} @@ -96,9 +112,70 @@ public class TransitionHelper { /** Override the transition to the old framework default pre P. */ public static final int TRANSITION_FRAMEWORK_DEFAULT_PRE_P = 4; + /** + * Override the transition to the specific transition and the transition type will depends on the + * partner resource. + */ + // TODO: Add new partner resource to determine which transition type would be apply. + public static final int TRANSITION_CAPTIVE = 5; + + /** Override the transition to the specific type that will depend on the partner resource. */ + private static final int CONFIG_TRANSITION_SHARED_X_AXIS = 1; + + /** + * Passed in an intent as EXTRA_ACTIVITY_OPTIONS. This is the {@link ActivityOptions} of the + * transition used in {@link Activity#startActivity} or {@link Activity#startActivityForResult}. + */ + public static final String EXTRA_ACTIVITY_OPTIONS = "activity_options"; + private TransitionHelper() {} /** + * Apply the transition for going forward which is decided by partner resource {@link + * PartnerConfig#CONFIG_TRANSITION_TYPE} and system property {@code setupwizard.transition_type}. + * The default transition that will be applied is {@link #TRANSITION_SLIDE}. The timing to apply + * the transition is going forward from the previous activity to this, or going forward from this + * activity to the next. + * + * <p>For example, in the flow below, the forward transitions will be applied to all arrows + * pointing to the right. Previous screen --> This screen --> Next screen + */ + public static void applyForwardTransition(Activity activity) { + applyForwardTransition(activity, TRANSITION_CAPTIVE); + } + + /** + * Apply the transition for going forward which is decided by partner resource {@link + * PartnerConfig#CONFIG_TRANSITION_TYPE} and system property {@code setupwizard.transition_type}. + * The default transition that will be applied is {@link #TRANSITION_NO_OVERRIDE}. The timing to + * apply the transition is going forward from the previous {@link Fragment} to this, or going + * forward from this {@link Fragment} to the next. + */ + public static void applyForwardTransition(Fragment fragment) { + int transitionType; + if (VERSION.SDK_INT > VERSION_CODES.R) { + transitionType = + PartnerConfigHelper.get(fragment.getContext()) + .getInteger( + fragment.getContext(), + PartnerConfig.CONFIG_TRANSITION_TYPE, + TRANSITION_NO_OVERRIDE); + + if (CONFIG_TRANSITION_SHARED_X_AXIS == transitionType) { + MaterialSharedAxis exitTransition = + new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ true); + fragment.setExitTransition(exitTransition); + + MaterialSharedAxis enterTransition = + new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ true); + fragment.setEnterTransition(enterTransition); + } + } else { + Log.w(TAG, "Not apply the forward transition for platform fragment."); + } + } + + /** * Apply the transition for going forward. This is applied when going forward from the previous * activity to this, or going forward from this activity to the next. * @@ -118,19 +195,90 @@ public class TransitionHelper { android.R.attr.activityOpenEnterAnimation, android.R.attr.activityOpenExitAnimation }); activity.overridePendingTransition( - typedArray.getResourceId(0, 0), typedArray.getResourceId(1, 0)); + typedArray.getResourceId(/* index= */ 0, /* defValue= */ 0), + typedArray.getResourceId(/* index= */ 1, /* defValue= */ 0)); typedArray.recycle(); } else if (transitionId == TRANSITION_FRAMEWORK_DEFAULT_PRE_P) { activity.overridePendingTransition( R.anim.sud_pre_p_activity_open_enter, R.anim.sud_pre_p_activity_open_exit); } else if (transitionId == TRANSITION_NONE) { // For TRANSITION_NONE, turn off the transition - activity.overridePendingTransition(0, 0); + activity.overridePendingTransition(/* enterAnim= */ 0, /* exitAnim= */ 0); + } else if (transitionId == TRANSITION_CAPTIVE) { + // 1. If the flag not available, apply TRANSITION_SLIDE + // 2. If the flag present, apply the transition from transition type + int configTransitionType = + PartnerConfigHelper.get(activity) + .getInteger(activity, PartnerConfig.CONFIG_TRANSITION_TYPE, TRANSITION_SLIDE); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R + && configTransitionType == CONFIG_TRANSITION_SHARED_X_AXIS) { + Window window = activity.getWindow(); + if (window != null) { + MaterialSharedAxis exitTransition = + new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ true); + window.setExitTransition(exitTransition); + + window.setAllowEnterTransitionOverlap(true); + + MaterialSharedAxis enterTransition = + new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ true); + window.setEnterTransition(enterTransition); + } else { + Log.w(TAG, "applyForwardTransition: Invalid window=" + window); + } + } else { + activity.overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out); + } } // For TRANSITION_NO_OVERRIDE or other values, do not override the transition } /** + * Apply the transition for going backward which is decided by partner resource {@link + * PartnerConfig#CONFIG_TRANSITION_TYPE} and system property {@code setupwizard.transition_type}. + * The default transition that will be applied is {@link #TRANSITION_SLIDE}. The timing to apply + * the transition is going backward from the next activity to this, or going backward from this + * activity to the previous. + * + * <p>For example, in the flow below, the backward transitions will be applied to all arrows + * pointing to the left. Previous screen <-- This screen <-- Next screen + */ + public static void applyBackwardTransition(Activity activity) { + applyBackwardTransition(activity, TRANSITION_CAPTIVE); + } + + /** + * Apply the transition for going backward which is decided by partner resource {@link + * PartnerConfig#CONFIG_TRANSITION_TYPE} and system property {@code setupwizard.transition_type}. + * The default transition that will be applied is {@link #TRANSITION_NO_OVERRIDE}. The timing to + * apply the transition is going backward from the next {@link Fragment} to this, or going + * backward from this {@link Fragment} to the previous. + */ + public static void applyBackwardTransition(Fragment fragment) { + int transitionType; + if (VERSION.SDK_INT > VERSION_CODES.R) { + transitionType = + PartnerConfigHelper.get(fragment.getContext()) + .getInteger( + fragment.getContext(), + PartnerConfig.CONFIG_TRANSITION_TYPE, + TRANSITION_NO_OVERRIDE); + + if (CONFIG_TRANSITION_SHARED_X_AXIS == transitionType) { + MaterialSharedAxis returnTransition = + new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ false); + fragment.setReturnTransition(returnTransition); + + MaterialSharedAxis reenterTransition = + new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ false); + fragment.setReenterTransition(reenterTransition); + } + } else { + Log.w(TAG, "Not apply the backward transition for platform fragment."); + } + } + + /** * Apply the transition for going backward. This is applied when going backward from the next * activity to this, or going backward from this activity to the previous. * @@ -141,7 +289,7 @@ public class TransitionHelper { if (transitionId == TRANSITION_SLIDE) { activity.overridePendingTransition(R.anim.sud_slide_back_in, R.anim.sud_slide_back_out); } else if (transitionId == TRANSITION_FADE) { - activity.overridePendingTransition(android.R.anim.fade_in, R.anim.sud_stay); + activity.overridePendingTransition(R.anim.sud_stay, android.R.anim.fade_out); } else if (transitionId == TRANSITION_FRAMEWORK_DEFAULT) { TypedArray typedArray = activity.obtainStyledAttributes( @@ -151,15 +299,112 @@ public class TransitionHelper { android.R.attr.activityCloseExitAnimation }); activity.overridePendingTransition( - typedArray.getResourceId(0, 0), typedArray.getResourceId(1, 0)); + typedArray.getResourceId(/* index= */ 0, /* defValue= */ 0), + typedArray.getResourceId(/* index= */ 1, /* defValue= */ 0)); typedArray.recycle(); } else if (transitionId == TRANSITION_FRAMEWORK_DEFAULT_PRE_P) { activity.overridePendingTransition( R.anim.sud_pre_p_activity_close_enter, R.anim.sud_pre_p_activity_close_exit); } else if (transitionId == TRANSITION_NONE) { // For TRANSITION_NONE, turn off the transition - activity.overridePendingTransition(0, 0); + activity.overridePendingTransition(/* enterAnim= */ 0, /* exitAnim= */ 0); + } else if (transitionId == TRANSITION_CAPTIVE) { + // 1. If the flag not available, apply TRANSITION_SLIDE + // 2. If the flag present, apply the transition from transition type + int configTransitionType = + PartnerConfigHelper.get(activity) + .getInteger(activity, PartnerConfig.CONFIG_TRANSITION_TYPE, TRANSITION_SLIDE); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R + && configTransitionType == CONFIG_TRANSITION_SHARED_X_AXIS) { + Window window = activity.getWindow(); + if (window != null) { + MaterialSharedAxis reenterTransition = + new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ false); + window.setReenterTransition(reenterTransition); + + MaterialSharedAxis returnTransition = + new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ false); + window.setReturnTransition(returnTransition); + } else { + Log.w(TAG, "applyBackwardTransition: Invalid window=" + window); + } + } else { + activity.overridePendingTransition(R.anim.sud_slide_back_in, R.anim.sud_slide_back_out); + } } // For TRANSITION_NO_OVERRIDE or other values, do not override the transition } + + /** + * A wrapper method, create an {@link android.app.ActivityOptions} to transition between + * activities as the {@link ActivityOptions} parameter of {@link Activity#startActivity}. + * + * @throws IllegalArgumentException is thrown when {@code activity} or {@code intent} is null. + * @throws android.content.ActivityNotFoundException if there was no {@link Activity} found to run + * the given Intent. + */ + public static void startActivityWithTransition(Activity activity, Intent intent) { + if (activity == null) { + throw new IllegalArgumentException("Invalid activity=" + activity); + } + + if (intent == null) { + throw new IllegalArgumentException("Invalid intent=" + intent); + } + + int configTransitionType = + PartnerConfigHelper.get(activity) + .getInteger(activity, PartnerConfig.CONFIG_TRANSITION_TYPE, TRANSITION_SLIDE); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R + && configTransitionType == CONFIG_TRANSITION_SHARED_X_AXIS) { + if (activity.getWindow() != null + && !activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)) { + Log.w( + TAG, "The transition won't take effect due to NO FEATURE_ACTIVITY_TRANSITIONS feature"); + } + + ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation(activity); + intent.putExtra(EXTRA_ACTIVITY_OPTIONS, (Parcelable) activityOptions.toBundle()); + activity.startActivity(intent, activityOptions.toBundle()); + } else { + activity.startActivity(intent); + } + } + + /** + * A wrapper method, create an {@link android.app.ActivityOptions} to transition between + * activities as the {@code activityOptions} parameter of {@link Activity#startActivityForResult}. + * + * @throws IllegalArgumentException is thrown when {@code activity} or {@code intent} is null. + * @throws android.content.ActivityNotFoundException if there was no {@link Activity} found to run + * the given Intent. + */ + public static void startActivityForResultWithTransition( + Activity activity, Intent intent, int requestCode) { + if (activity == null) { + throw new IllegalArgumentException("Invalid activity=" + activity); + } + + if (intent == null) { + throw new IllegalArgumentException("Invalid intent=" + intent); + } + + int configTransitionType = + PartnerConfigHelper.get(activity) + .getInteger(activity, PartnerConfig.CONFIG_TRANSITION_TYPE, TRANSITION_SLIDE); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R + && configTransitionType == CONFIG_TRANSITION_SHARED_X_AXIS) { + if (activity.getWindow() != null + && !activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)) { + Log.w( + TAG, "The transition won't take effect due to NO FEATURE_ACTIVITY_TRANSITIONS feature"); + } + + ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation(activity); + intent.putExtra(EXTRA_ACTIVITY_OPTIONS, (Parcelable) activityOptions.toBundle()); + activity.startActivityForResult(intent, requestCode, activityOptions.toBundle()); + } else { + activity.startActivityForResult(intent, requestCode); + } + } } diff --git a/main/src/com/google/android/setupdesign/transition/support/TransitionHelper.java b/main/src/com/google/android/setupdesign/transition/support/TransitionHelper.java new file mode 100644 index 0000000..06e9625 --- /dev/null +++ b/main/src/com/google/android/setupdesign/transition/support/TransitionHelper.java @@ -0,0 +1,104 @@ +/* + * 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. + */ + +package com.google.android.setupdesign.transition.support; + +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; +import androidx.fragment.app.Fragment; +import android.util.Log; +import com.google.android.material.transition.platform.MaterialSharedAxis; +import com.google.android.setupcompat.partnerconfig.PartnerConfig; +import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper; + +/** Helper class for apply the transition to the pages which uses support library. */ +public class TransitionHelper { + + private static final String TAG = "TransitionHelper"; + + /** + * No override. If this is specified as the transition, overridePendingTransition will not be + * called. + */ + public static final int TRANSITION_NO_OVERRIDE = 0; + + /** Override the transition to the specific type that will depend on the partner resource. */ + private static final int CONFIG_TRANSITION_SHARED_X_AXIS = 1; + + private TransitionHelper() {} + + /** + * Apply the transition for going forward which is decided by partner resource {@link + * PartnerConfig#CONFIG_TRANSITION_TYPE} and system property {@code setupwizard.transition_type}. + * The default transition that will be applied is {@link #TRANSITION_NO_OVERRIDE}. The timing to + * apply the transition is going forward from the previous {@link Fragment} to this, or going + * forward from this {@link Fragment} to the next. + */ + public static void applyForwardTransition(Fragment fragment) { + int transitionType; + if (VERSION.SDK_INT > VERSION_CODES.R) { + transitionType = + PartnerConfigHelper.get(fragment.getContext()) + .getInteger( + fragment.getContext(), + PartnerConfig.CONFIG_TRANSITION_TYPE, + TRANSITION_NO_OVERRIDE); + + if (CONFIG_TRANSITION_SHARED_X_AXIS == transitionType) { + MaterialSharedAxis exitTransition = + new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ true); + fragment.setExitTransition(exitTransition); + + MaterialSharedAxis enterTransition = + new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ true); + fragment.setEnterTransition(enterTransition); + } + } else { + Log.w(TAG, "Not apply the forward transition for support lib's fragment."); + } + } + + /** + * Apply the transition for going backward which is decided by partner resource {@link + * PartnerConfig#CONFIG_TRANSITION_TYPE} and system property {@code setupwizard.transition_type}. + * The default transition that will be applied is {@link #TRANSITION_NO_OVERRIDE}. The timing to + * apply the transition is going backward from the next {@link Fragment} to this, or going + * backward from this {@link Fragment} to the previous. + */ + public static void applyBackwardTransition(Fragment fragment) { + int transitionType; + if (VERSION.SDK_INT > VERSION_CODES.R) { + transitionType = + PartnerConfigHelper.get(fragment.getContext()) + .getInteger( + fragment.getContext(), + PartnerConfig.CONFIG_TRANSITION_TYPE, + TRANSITION_NO_OVERRIDE); + + if (CONFIG_TRANSITION_SHARED_X_AXIS == transitionType) { + MaterialSharedAxis returnTransition = + new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ false); + fragment.setReturnTransition(returnTransition); + + MaterialSharedAxis reenterTransition = + new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ false); + fragment.setReenterTransition(reenterTransition); + } + } else { + Log.w(TAG, "Not apply the backward transition for support lib's fragment."); + } + } +} diff --git a/main/src/com/google/android/setupdesign/util/ContentStyler.java b/main/src/com/google/android/setupdesign/util/ContentStyler.java index 0ab49b8..3b64fd6 100644 --- a/main/src/com/google/android/setupdesign/util/ContentStyler.java +++ b/main/src/com/google/android/setupdesign/util/ContentStyler.java @@ -38,6 +38,8 @@ public final class ContentStyler { PartnerConfig.CONFIG_CONTENT_LINK_TEXT_COLOR, PartnerConfig.CONFIG_CONTENT_TEXT_SIZE, PartnerConfig.CONFIG_CONTENT_FONT_FAMILY, + null, + null, ContentStyler.getPartnerContentTextGravity(contentText.getContext()))); } diff --git a/main/src/com/google/android/setupdesign/util/DescriptionStyler.java b/main/src/com/google/android/setupdesign/util/DescriptionStyler.java index e1068f2..0a786c6 100644 --- a/main/src/com/google/android/setupdesign/util/DescriptionStyler.java +++ b/main/src/com/google/android/setupdesign/util/DescriptionStyler.java @@ -41,6 +41,8 @@ public final class DescriptionStyler { PartnerConfig.CONFIG_DESCRIPTION_LINK_TEXT_COLOR, PartnerConfig.CONFIG_DESCRIPTION_TEXT_SIZE, PartnerConfig.CONFIG_DESCRIPTION_FONT_FAMILY, + null, + null, PartnerStyleHelper.getLayoutGravity(description.getContext()))); } @@ -54,7 +56,13 @@ public final class DescriptionStyler { TextViewPartnerStyler.applyPartnerCustomizationLightStyle( description, new TextPartnerConfigs( - null, null, null, null, PartnerStyleHelper.getLayoutGravity(description.getContext()))); + null, + null, + null, + null, + null, + null, + PartnerStyleHelper.getLayoutGravity(description.getContext()))); } private DescriptionStyler() {} diff --git a/main/src/com/google/android/setupdesign/util/HeaderAreaStyler.java b/main/src/com/google/android/setupdesign/util/HeaderAreaStyler.java index 7702eba..efeff97 100644 --- a/main/src/com/google/android/setupdesign/util/HeaderAreaStyler.java +++ b/main/src/com/google/android/setupdesign/util/HeaderAreaStyler.java @@ -17,11 +17,19 @@ package com.google.android.setupdesign.util; import android.content.Context; +import android.graphics.drawable.VectorDrawable; +import android.os.Build; import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.view.ViewTreeObserver; import android.widget.ImageView; +import android.widget.ImageView.ScaleType; import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; +import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat; +import com.google.android.setupcompat.internal.TemplateLayout; import com.google.android.setupcompat.partnerconfig.PartnerConfig; import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper; import com.google.android.setupdesign.util.TextViewPartnerStyler.TextPartnerConfigs; @@ -32,6 +40,10 @@ import com.google.android.setupdesign.util.TextViewPartnerStyler.TextPartnerConf */ public final class HeaderAreaStyler { + @VisibleForTesting + static final String WARNING_TO_USE_DRAWABLE = + "To achieve scaling icon in SetupDesign lib, should use vector drawable icon!!"; + /** * Applies the partner heavy style of header text to the given textView {@code header}. * @@ -49,10 +61,35 @@ public final class HeaderAreaStyler { null, PartnerConfig.CONFIG_HEADER_TEXT_SIZE, PartnerConfig.CONFIG_HEADER_FONT_FAMILY, + PartnerConfig.CONFIG_HEADER_TEXT_MARGIN_TOP, + PartnerConfig.CONFIG_HEADER_TEXT_MARGIN_BOTTOM, PartnerStyleHelper.getLayoutGravity(header.getContext()))); } /** + * Applies the partner heavy style of description text to the given textView {@code description}. + * + * @param description A description text would apply partner heavy style + */ + public static void applyPartnerCustomizationDescriptionHeavyStyle( + @Nullable TextView description) { + + if (description == null) { + return; + } + TextViewPartnerStyler.applyPartnerCustomizationStyle( + description, + new TextPartnerConfigs( + PartnerConfig.CONFIG_DESCRIPTION_TEXT_COLOR, + PartnerConfig.CONFIG_DESCRIPTION_LINK_TEXT_COLOR, + PartnerConfig.CONFIG_DESCRIPTION_TEXT_SIZE, + PartnerConfig.CONFIG_DESCRIPTION_FONT_FAMILY, + PartnerConfig.CONFIG_DESCRIPTION_TEXT_MARGIN_TOP, + PartnerConfig.CONFIG_DESCRIPTION_TEXT_MARGIN_BOTTOM, + PartnerStyleHelper.getLayoutGravity(description.getContext()))); + } + + /** * Applies the partner light style of header text to the given textView {@code header}. * * @param header A header text would apply partner light style @@ -66,13 +103,43 @@ public final class HeaderAreaStyler { TextViewPartnerStyler.applyPartnerCustomizationLightStyle( header, new TextPartnerConfigs( - null, null, null, null, PartnerStyleHelper.getLayoutGravity(header.getContext()))); + null, + null, + null, + null, + null, + null, + PartnerStyleHelper.getLayoutGravity(header.getContext()))); + } + + /** + * Applies the partner light style of description text to the given textView {@code description}. + * + * @param description A description text would apply partner light style + */ + public static void applyPartnerCustomizationDescriptionLightStyle( + @Nullable TextView description) { + + if (description == null) { + return; + } + + TextViewPartnerStyler.applyPartnerCustomizationLightStyle( + description, + new TextPartnerConfigs( + null, + null, + null, + null, + null, + null, + PartnerStyleHelper.getLayoutGravity(description.getContext()))); } /** - * Applies the partner style of header background to the given layout {@code headerArea}. + * Applies the partner style of header area to the given layout {@code headerArea}. * - * @param headerArea A ViewGroup would apply the partner style of header background + * @param headerArea A ViewGroup would apply the partner style of header area */ public static void applyPartnerCustomizationHeaderAreaStyle(ViewGroup headerArea) { @@ -84,25 +151,97 @@ public final class HeaderAreaStyler { PartnerConfigHelper.get(context) .getColor(context, PartnerConfig.CONFIG_HEADER_AREA_BACKGROUND_COLOR); headerArea.setBackgroundColor(color); + + if (PartnerConfigHelper.shouldApplyExtendedPartnerConfig(context)) { + final ViewGroup.LayoutParams lp = headerArea.getLayoutParams(); + if (lp instanceof ViewGroup.MarginLayoutParams) { + final ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) lp; + + int bottomMargin = + (int) + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_HEADER_CONTAINER_MARGIN_BOTTOM); + mlp.setMargins(mlp.leftMargin, mlp.topMargin, mlp.rightMargin, bottomMargin); + headerArea.setLayoutParams(lp); + } + } } /** * Applies the partner style of header icon to the given {@code iconImage}. * * @param iconImage A ImageView would apply the partner style of header icon + * @param templateLayout The template containing this mixin */ - public static void applyPartnerCustomizationIconStyle(@Nullable ImageView iconImage) { - + public static void applyPartnerCustomizationIconStyle( + @Nullable ImageView iconImage, TemplateLayout templateLayout) { if (iconImage == null) { return; } - int gravity = PartnerStyleHelper.getLayoutGravity(iconImage.getContext()); - if (gravity != 0) { - setGravity(iconImage, gravity); + if (PartnerStyleHelper.isPartnerLightThemeLayout(templateLayout)) { + Context context = iconImage.getContext(); + int gravity = PartnerStyleHelper.getLayoutGravity(context); + if (gravity != 0) { + setGravity(iconImage, gravity); + } + + if (!PartnerStyleHelper.isPartnerHeavyThemeLayout(templateLayout) + || !PartnerConfigHelper.shouldApplyExtendedPartnerConfig(context)) { + return; + } + + final ViewGroup.LayoutParams lp = iconImage.getLayoutParams(); + boolean partnerConfigAvailable = + PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_ICON_MARGIN_TOP); + if (partnerConfigAvailable && lp instanceof ViewGroup.MarginLayoutParams) { + final ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) lp; + int topMargin = + (int) + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_ICON_MARGIN_TOP); + mlp.setMargins(mlp.leftMargin, topMargin, mlp.rightMargin, mlp.bottomMargin); + } + + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_ICON_SIZE)) { + + checkImageType(iconImage); + + lp.height = + (int) + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_ICON_SIZE); + lp.width = LayoutParams.WRAP_CONTENT; + iconImage.setScaleType(ScaleType.FIT_CENTER); + } } } + private static void checkImageType(ImageView imageView) { + ViewTreeObserver vto = imageView.getViewTreeObserver(); + vto.addOnPreDrawListener( + new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + imageView.getViewTreeObserver().removeOnPreDrawListener(this); + + // TODO: Remove when Partners all used Drawable icon image and never use + // un-drawable image in Setup. + // Should set vector drawable icon rather than non-drawable icon(e.g. PNG) + if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP + || !(imageView.getDrawable() instanceof VectorDrawable)) + && !(imageView.getDrawable() instanceof VectorDrawableCompat)) { + // TODO : Use reflection to get ro.debuggable and show toast to warn. + MessageWarning.makeWarning(WARNING_TO_USE_DRAWABLE); + } + + return true; + } + }); + } + private static void setGravity(ImageView icon, int gravity) { if (icon.getLayoutParams() instanceof LinearLayout.LayoutParams) { LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) icon.getLayoutParams(); diff --git a/main/src/com/google/android/setupdesign/util/ItemStyler.java b/main/src/com/google/android/setupdesign/util/ItemStyler.java new file mode 100644 index 0000000..5b95d0d --- /dev/null +++ b/main/src/com/google/android/setupdesign/util/ItemStyler.java @@ -0,0 +1,151 @@ +/* + * 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. + */ + +package com.google.android.setupdesign.util; + +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.Typeface; +import android.os.Build.VERSION_CODES; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; +import androidx.annotation.Nullable; +import com.google.android.setupcompat.partnerconfig.PartnerConfig; +import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper; +import com.google.android.setupdesign.R; + +/** + * Applies the partner style of layout to the given View {@code view}. The user needs to check if + * the {@code view} should apply partner heavy theme before calling this method. + */ +public final class ItemStyler { + + /** + * Applies the extended partner configs to the given view {@code view}. The user needs to check + * before calling this method: + * + * <p>1) If the {@code view} should apply extended partner configs by calling {@link + * ThemeHelper#shouldApplyExtendedPartnerConfig}. + * + * <p>2) If the layout of the {@code view} contains fixed resource IDs which attempts to apply + * extended partner resources (The resource ID of the title is "sud_items_title" and the resource + * ID of the summary is "sud_items_summary"), refer to {@link R.layout#sud_items_default}. + * + * @param view A view would be applied extended partner styles + */ + @TargetApi(VERSION_CODES.JELLY_BEAN_MR1) + public static void applyPartnerCustomizationItemStyle(@Nullable View view) { + if (view == null) { + return; + } + + final Context context = view.getContext(); + + if (!PartnerStyleHelper.shouldApplyPartnerHeavyThemeResource(view) + || !PartnerConfigHelper.shouldApplyExtendedPartnerConfig(context)) { + return; + } + + TextView summaryView = view.findViewById(R.id.sud_items_summary); + if (summaryView.getVisibility() == View.GONE && view instanceof LinearLayout) { + // Set list items to vertical center when no summary. + ((LinearLayout) view).setGravity(Gravity.CENTER_VERTICAL); + } + + final TextView titleView = view.findViewById(R.id.sud_items_title); + + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_ITEMS_TITLE_TEXT_SIZE)) { + final float titleSize = + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_ITEMS_TITLE_TEXT_SIZE); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, titleSize); + } + + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_ITEMS_SUMMARY_TEXT_SIZE)) { + final float summarySize = + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_ITEMS_SUMMARY_TEXT_SIZE); + summaryView.setTextSize(TypedValue.COMPLEX_UNIT_PX, summarySize); + } + + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_ITEMS_FONT_FAMILY)) { + + final String textFont = + PartnerConfigHelper.get(context) + .getString(context, PartnerConfig.CONFIG_ITEMS_FONT_FAMILY); + + final Typeface typeface = Typeface.create(textFont, Typeface.NORMAL); + + titleView.setTypeface(typeface); + summaryView.setTypeface(typeface); + } + + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_ITEMS_SUMMARY_MARGIN_TOP)) { + float summaryMarginTop = + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_ITEMS_SUMMARY_MARGIN_TOP); + final ViewGroup.LayoutParams lp = summaryView.getLayoutParams(); + if (lp instanceof LinearLayout.LayoutParams) { + final LinearLayout.LayoutParams mlp = (LinearLayout.LayoutParams) lp; + mlp.setMargins(mlp.leftMargin, (int) summaryMarginTop, mlp.rightMargin, mlp.bottomMargin); + summaryView.setLayoutParams(lp); + } + } + + float paddingTop; + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_ITEMS_PADDING_TOP)) { + paddingTop = + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_ITEMS_PADDING_TOP); + } else { + paddingTop = view.getPaddingTop(); + } + + float paddingBottom; + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_ITEMS_PADDING_BOTTOM)) { + paddingBottom = + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_ITEMS_PADDING_BOTTOM); + } else { + paddingBottom = view.getPaddingBottom(); + } + + if (paddingTop != view.getPaddingTop() || paddingBottom != view.getPaddingBottom()) { + view.setPadding( + view.getPaddingStart(), (int) paddingTop, view.getPaddingEnd(), (int) paddingBottom); + } + + if (PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_ITEMS_MIN_HEIGHT)) { + float minHeight = + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_ITEMS_MIN_HEIGHT); + view.setMinimumHeight((int) minHeight); + } + } + + private ItemStyler() {} +} diff --git a/main/src/com/google/android/setupdesign/util/LayoutStyler.java b/main/src/com/google/android/setupdesign/util/LayoutStyler.java new file mode 100644 index 0000000..97596e1 --- /dev/null +++ b/main/src/com/google/android/setupdesign/util/LayoutStyler.java @@ -0,0 +1,142 @@ +/* + * 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. + */ + +package com.google.android.setupdesign.util; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Build.VERSION_CODES; +import android.view.View; +import androidx.annotation.Nullable; +import com.google.android.setupcompat.partnerconfig.PartnerConfig; +import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper; +import com.google.android.setupdesign.R; + +/** + * Applies the partner style of layout to the given View {@code view}. The user needs to check if + * the {@code view} should apply partner heavy theme before calling this method. + */ +public final class LayoutStyler { + + /** + * Applies the partner layout padding style to the given view {@code view}. + * + * @param view A view would be applied partner layout padding style + */ + @TargetApi(VERSION_CODES.JELLY_BEAN_MR1) + public static void applyPartnerCustomizationLayoutPaddingStyle(@Nullable View view) { + if (view == null) { + return; + } + + Context context = view.getContext(); + boolean partnerMarginStartAvailable = + PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_LAYOUT_MARGIN_START); + boolean partnerMarginEndAvailable = + PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_LAYOUT_MARGIN_END); + + if (PartnerConfigHelper.shouldApplyExtendedPartnerConfig(context) + && (partnerMarginStartAvailable || partnerMarginEndAvailable)) { + int paddingStart; + int paddingEnd; + if (partnerMarginStartAvailable) { + paddingStart = + (int) + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_LAYOUT_MARGIN_START); + } else { + paddingStart = view.getPaddingStart(); + } + if (partnerMarginEndAvailable) { + paddingEnd = + (int) + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_LAYOUT_MARGIN_END); + } else { + paddingEnd = view.getPaddingEnd(); + } + + if (paddingStart != view.getPaddingStart() || paddingEnd != view.getPaddingEnd()) { + view.setPadding(paddingStart, view.getPaddingTop(), paddingEnd, view.getPaddingBottom()); + } + } + } + + /** + * Applies the extra padding style to the given view {@code view}. This method is used when {@code + * view} already sets its margin, and like to extra padding make view.margin + view.pendding = + * global page margin. + * + * @param view A view would be applied extra padding style based on the layout margin of partner + * config. + */ + @TargetApi(VERSION_CODES.JELLY_BEAN_MR1) + public static void applyPartnerCustomizationExtraPaddingStyle(@Nullable View view) { + if (view == null) { + return; + } + + Context context = view.getContext(); + boolean partnerMarginStartAvailable = + PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_LAYOUT_MARGIN_START); + boolean partnerMarginEndAvailable = + PartnerConfigHelper.get(context) + .isPartnerConfigAvailable(PartnerConfig.CONFIG_LAYOUT_MARGIN_END); + + if (PartnerConfigHelper.shouldApplyExtendedPartnerConfig(context) + && (partnerMarginStartAvailable || partnerMarginEndAvailable)) { + int extraPaddingStart; + int extraPaddingEnd; + + TypedArray a = + context.obtainStyledAttributes(new int[] {R.attr.sudMarginStart, R.attr.sudMarginEnd}); + int layoutMarginStart = a.getDimensionPixelSize(0, 0); + int layoutMarginEnd = a.getDimensionPixelSize(1, 0); + a.recycle(); + + if (partnerMarginStartAvailable) { + extraPaddingStart = + ((int) + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_LAYOUT_MARGIN_START)) + - layoutMarginStart; + } else { + extraPaddingStart = view.getPaddingStart(); + } + + if (partnerMarginEndAvailable) { + extraPaddingEnd = + ((int) + PartnerConfigHelper.get(context) + .getDimension(context, PartnerConfig.CONFIG_LAYOUT_MARGIN_END)) + - layoutMarginEnd; + } else { + extraPaddingEnd = view.getPaddingEnd(); + } + + if (extraPaddingStart != view.getPaddingStart() || extraPaddingEnd != view.getPaddingEnd()) { + view.setPadding( + extraPaddingStart, view.getPaddingTop(), extraPaddingEnd, view.getPaddingBottom()); + } + } + } + + private LayoutStyler() {} +} diff --git a/main/src/com/google/android/setupdesign/util/MessageWarning.java b/main/src/com/google/android/setupdesign/util/MessageWarning.java new file mode 100644 index 0000000..e98eb52 --- /dev/null +++ b/main/src/com/google/android/setupdesign/util/MessageWarning.java @@ -0,0 +1,49 @@ +/* + * 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. + */ + +package com.google.android.setupdesign.util; + +import android.os.Build; +import android.util.Log; + +/** Utilities to warn developer in Android S later debug build. */ +public final class MessageWarning { + + private static final String TAG = "ToastWarning"; + + /** + * Shows the warning message. + * + * @param warningMsg The message to show for warning . + */ + public static void makeWarning(String warningMsg) { + if (isAtLeastS()) { + Log.w(TAG, warningMsg); + } + } + + private static boolean isAtLeastS() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { + return false; + } + return (Build.VERSION.CODENAME.equals("REL") && Build.VERSION.SDK_INT >= 31) + || (Build.VERSION.CODENAME.length() == 1 + && Build.VERSION.CODENAME.charAt(0) >= 'S' + && Build.VERSION.CODENAME.charAt(0) <= 'Z'); + } + + private MessageWarning() {} +} diff --git a/main/src/com/google/android/setupdesign/util/PartnerStyleHelper.java b/main/src/com/google/android/setupdesign/util/PartnerStyleHelper.java index d1d4a26..ed5af71 100644 --- a/main/src/com/google/android/setupdesign/util/PartnerStyleHelper.java +++ b/main/src/com/google/android/setupdesign/util/PartnerStyleHelper.java @@ -16,12 +16,19 @@ package com.google.android.setupdesign.util; +import android.app.Activity; import android.content.Context; +import android.content.res.TypedArray; +import android.os.Build; import android.view.Gravity; -import android.widget.FrameLayout; +import android.view.View; +import com.google.android.setupcompat.PartnerCustomizationLayout; +import com.google.android.setupcompat.internal.TemplateLayout; import com.google.android.setupcompat.partnerconfig.PartnerConfig; import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper; +import com.google.android.setupcompat.util.WizardManagerHelper; import com.google.android.setupdesign.GlifLayout; +import com.google.android.setupdesign.R; import java.util.Locale; /** The helper reads styles from the partner configurations. */ @@ -47,14 +54,113 @@ public final class PartnerStyleHelper { } /** Returns the given layout if apply partner heavy theme. */ - public static boolean isPartnerHeavyThemeLayout(FrameLayout layout) { + public static boolean isPartnerHeavyThemeLayout(TemplateLayout layout) { if (!(layout instanceof GlifLayout)) { return false; } - if (!((GlifLayout) layout).shouldApplyPartnerHeavyThemeResource()) { + return ((GlifLayout) layout).shouldApplyPartnerHeavyThemeResource(); + } + + /** Returns the given layout if apply partner light theme. */ + public static boolean isPartnerLightThemeLayout(TemplateLayout layout) { + if (!(layout instanceof PartnerCustomizationLayout)) { + return false; + } + return ((PartnerCustomizationLayout) layout).shouldApplyPartnerResource(); + } + + /** + * Returns if the current layout/activity of the given {@code view} applies partner customized + * configurations or not. + * + * @param view A view would be used to get the activity and context. + */ + public static boolean shouldApplyPartnerResource(View view) { + if (view == null) { + return false; + } + if (view instanceof PartnerCustomizationLayout) { + return isPartnerLightThemeLayout((PartnerCustomizationLayout) view); + } + return shouldApplyPartnerResource(view.getContext()); + } + + private static boolean shouldApplyPartnerResource(Context context) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { + return false; + } + + if (!PartnerConfigHelper.get(context).isAvailable()) { + return false; + } + + Activity activity = null; + try { + activity = PartnerCustomizationLayout.lookupActivityFromContext(context); + if (activity != null) { + TemplateLayout layout = findLayoutFromActivity(activity); + if (layout instanceof PartnerCustomizationLayout) { + return ((PartnerCustomizationLayout) layout).shouldApplyPartnerResource(); + } + } + } catch (IllegalArgumentException | ClassCastException ex) { + // fall through + } + + // try best to get partner resource settings from attrs + boolean isSetupFlow = false; + if (activity != null) { + isSetupFlow = WizardManagerHelper.isAnySetupWizard(activity.getIntent()); + } + TypedArray a = context.obtainStyledAttributes(new int[] {R.attr.sucUsePartnerResource}); + boolean usePartnerResource = a.getBoolean(0, true); + a.recycle(); + + return isSetupFlow || usePartnerResource; + } + + /** + * Returns if the current layout/activity applies heavy partner customized configurations or not. + * + * @param view A view would be used to get the activity and context. + */ + public static boolean shouldApplyPartnerHeavyThemeResource(View view) { + if (view == null) { return false; } - return true; + if (view instanceof GlifLayout) { + return isPartnerHeavyThemeLayout((GlifLayout) view); + } + return shouldApplyPartnerHeavyThemeResource(view.getContext()); + } + + private static boolean shouldApplyPartnerHeavyThemeResource(Context context) { + try { + Activity activity = PartnerCustomizationLayout.lookupActivityFromContext(context); + TemplateLayout layout = findLayoutFromActivity(activity); + if (layout instanceof GlifLayout) { + return ((GlifLayout) layout).shouldApplyPartnerHeavyThemeResource(); + } + } catch (IllegalArgumentException | ClassCastException ex) { + // fall through + } + + // try best to get partner resource settings from attr + TypedArray a = context.obtainStyledAttributes(new int[] {R.attr.sudUsePartnerHeavyTheme}); + boolean usePartnerHeavyTheme = a.getBoolean(0, false); + a.recycle(); + usePartnerHeavyTheme = + usePartnerHeavyTheme || PartnerConfigHelper.shouldApplyExtendedPartnerConfig(context); + + return shouldApplyPartnerResource(context) && usePartnerHeavyTheme; + } + + private static TemplateLayout findLayoutFromActivity(Activity activity) { + if (activity == null) { + return null; + } + View rootView = activity.findViewById(R.id.suc_layout_status); + return rootView != null ? (TemplateLayout) rootView.getParent() : null; } private PartnerStyleHelper() {} diff --git a/main/src/com/google/android/setupdesign/util/TextViewPartnerStyler.java b/main/src/com/google/android/setupdesign/util/TextViewPartnerStyler.java index 2b8a6b7..8344692 100644 --- a/main/src/com/google/android/setupdesign/util/TextViewPartnerStyler.java +++ b/main/src/com/google/android/setupdesign/util/TextViewPartnerStyler.java @@ -19,6 +19,8 @@ package com.google.android.setupdesign.util; import android.content.Context; import android.graphics.Typeface; import android.util.TypedValue; +import android.view.ViewGroup; +import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -74,6 +76,36 @@ final class TextViewPartnerStyler { } } + if (PartnerConfigHelper.shouldApplyExtendedPartnerConfig(context)) { + if (textPartnerConfigs.getTextMarginTop() != null + || textPartnerConfigs.getTextMarginBottom() != null) { + int topMargin; + int bottomMargin; + final ViewGroup.LayoutParams lp = textView.getLayoutParams(); + if (lp instanceof LinearLayout.LayoutParams) { + final LinearLayout.LayoutParams mlp = (LinearLayout.LayoutParams) lp; + if (textPartnerConfigs.getTextMarginTop() != null) { + topMargin = + (int) + PartnerConfigHelper.get(context) + .getDimension(context, textPartnerConfigs.getTextMarginTop()); + } else { + topMargin = mlp.topMargin; + } + + if (textPartnerConfigs.getTextMarginBottom() != null) { + bottomMargin = + (int) + PartnerConfigHelper.get(context) + .getDimension(context, textPartnerConfigs.getTextMarginBottom()); + } else { + bottomMargin = mlp.bottomMargin; + } + mlp.setMargins(mlp.leftMargin, topMargin, mlp.rightMargin, bottomMargin); + textView.setLayoutParams(lp); + } + } + } textView.setGravity(textPartnerConfigs.getTextGravity()); } @@ -99,6 +131,8 @@ final class TextViewPartnerStyler { private final PartnerConfig textLinkedColorConfig; private final PartnerConfig textSizeConfig; private final PartnerConfig textFontFamilyConfig; + private final PartnerConfig textMarginTopConfig; + private final PartnerConfig textMarginBottomConfig; private final int textGravity; public TextPartnerConfigs( @@ -106,11 +140,15 @@ final class TextViewPartnerStyler { @Nullable PartnerConfig textLinkedColorConfig, @Nullable PartnerConfig textSizeConfig, @Nullable PartnerConfig textFontFamilyConfig, + @Nullable PartnerConfig textMarginTopConfig, + @Nullable PartnerConfig textMarginBottomConfig, int textGravity) { this.textColorConfig = textColorConfig; this.textLinkedColorConfig = textLinkedColorConfig; this.textSizeConfig = textSizeConfig; this.textFontFamilyConfig = textFontFamilyConfig; + this.textMarginTopConfig = textMarginTopConfig; + this.textMarginBottomConfig = textMarginBottomConfig; this.textGravity = textGravity; } @@ -130,6 +168,14 @@ final class TextViewPartnerStyler { return textFontFamilyConfig; } + public PartnerConfig getTextMarginTop() { + return textMarginTopConfig; + } + + public PartnerConfig getTextMarginBottom() { + return textMarginBottomConfig; + } + public int getTextGravity() { return textGravity; } diff --git a/main/src/com/google/android/setupdesign/util/ThemeHelper.java b/main/src/com/google/android/setupdesign/util/ThemeHelper.java index 630ab1b..c45b64f 100644 --- a/main/src/com/google/android/setupdesign/util/ThemeHelper.java +++ b/main/src/com/google/android/setupdesign/util/ThemeHelper.java @@ -24,7 +24,7 @@ import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper; import com.google.android.setupcompat.util.WizardManagerHelper; /** The helper class holds the constant names of themes and util functions */ -public class ThemeHelper { +public final class ThemeHelper { /** * Passed in a setup wizard intent as {@link WizardManagerHelper#EXTRA_THEME}. This is the dark @@ -144,12 +144,21 @@ public class ThemeHelper { } /** - * Checks whether SetupWizard support the DayNight theme during setup flow; if returns false setup - * flow is always light theme. + * Checks whether SetupWizard supports the DayNight theme during setup flow; if it returns false, + * setup flow is always light theme. * - * @return true if the setupwizard is listening to system DayNight theme setting. + * @return true if the SetupWizard is listening to system DayNight theme setting. */ public static boolean isSetupWizardDayNightEnabled(@NonNull Context context) { return PartnerConfigHelper.isSetupWizardDayNightEnabled(context); } + + /** + * Returns true if the partner provider of SetupWizard is ready to support more partner configs. + */ + public static boolean shouldApplyExtendedPartnerConfig(@NonNull Context context) { + return PartnerConfigHelper.shouldApplyExtendedPartnerConfig(context); + } + + private ThemeHelper() {} } diff --git a/main/src/com/google/android/setupdesign/util/ThemeResolver.java b/main/src/com/google/android/setupdesign/util/ThemeResolver.java index c755d86..98b8883 100644 --- a/main/src/com/google/android/setupdesign/util/ThemeResolver.java +++ b/main/src/com/google/android/setupdesign/util/ThemeResolver.java @@ -141,9 +141,6 @@ public class ThemeResolver { private static int getDayNightThemeRes(@Nullable String theme) { if (theme != null) { switch (theme) { - case ThemeHelper.THEME_GLIF_V4_LIGHT: - case ThemeHelper.THEME_GLIF_V4: - return R.style.SudThemeGlifV4_DayNight; case ThemeHelper.THEME_GLIF_V3_LIGHT: case ThemeHelper.THEME_GLIF_V3: return R.style.SudThemeGlifV3_DayNight; @@ -171,10 +168,6 @@ public class ThemeResolver { private static int getThemeRes(@Nullable String theme) { if (theme != null) { switch (theme) { - case ThemeHelper.THEME_GLIF_V4_LIGHT: - return R.style.SudThemeGlifV4_Light; - case ThemeHelper.THEME_GLIF_V4: - return R.style.SudThemeGlifV4; case ThemeHelper.THEME_GLIF_V3_LIGHT: return R.style.SudThemeGlifV3_Light; case ThemeHelper.THEME_GLIF_V3: @@ -210,9 +203,6 @@ public class ThemeResolver { private static int getThemeVersion(String theme) { if (theme != null) { switch (theme) { - case ThemeHelper.THEME_GLIF_V4_LIGHT: - case ThemeHelper.THEME_GLIF_V4: - return 5; case ThemeHelper.THEME_GLIF_V3_LIGHT: case ThemeHelper.THEME_GLIF_V3: return 4; |