summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorSetup Wizard Team <android-setup-team-eng@google.com>2020-12-30 19:23:06 +0800
committeralexylli <alexylli@google.com>2020-12-31 10:47:36 +0800
commit6c15fbdff11497af53e2a9bdff042e0e89df2659 (patch)
tree14e6fb8ea965c7ec84ad2d57b9310f45d412f8ce /main
parent6c7dfb3e2434a01371394a45ea687df7e331d5d7 (diff)
downloadsetupdesign-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')
-rw-r--r--main/res/layout/sud_glif_header.xml7
-rw-r--r--main/res/values-night/styles.xml1
-rw-r--r--main/res/values-v21/styles.xml4
-rw-r--r--main/res/values/attrs.xml8
-rw-r--r--main/res/values/dimens.xml21
-rw-r--r--main/res/values/styles.xml56
-rw-r--r--main/src/com/google/android/setupdesign/GlifLayout.java44
-rw-r--r--main/src/com/google/android/setupdesign/items/ExpandableSwitchItem.java6
-rw-r--r--main/src/com/google/android/setupdesign/items/Item.java15
-rw-r--r--main/src/com/google/android/setupdesign/template/DescriptionMixin.java160
-rw-r--r--main/src/com/google/android/setupdesign/template/HeaderMixin.java159
-rw-r--r--main/src/com/google/android/setupdesign/template/IconMixin.java18
-rw-r--r--main/src/com/google/android/setupdesign/template/IllustrationProgressMixin.java8
-rw-r--r--main/src/com/google/android/setupdesign/template/ListMixin.java20
-rw-r--r--main/src/com/google/android/setupdesign/template/RecyclerMixin.java20
-rw-r--r--main/src/com/google/android/setupdesign/transition/TransitionHelper.java257
-rw-r--r--main/src/com/google/android/setupdesign/transition/support/TransitionHelper.java104
-rw-r--r--main/src/com/google/android/setupdesign/util/ContentStyler.java2
-rw-r--r--main/src/com/google/android/setupdesign/util/DescriptionStyler.java10
-rw-r--r--main/src/com/google/android/setupdesign/util/HeaderAreaStyler.java155
-rw-r--r--main/src/com/google/android/setupdesign/util/ItemStyler.java151
-rw-r--r--main/src/com/google/android/setupdesign/util/LayoutStyler.java142
-rw-r--r--main/src/com/google/android/setupdesign/util/MessageWarning.java49
-rw-r--r--main/src/com/google/android/setupdesign/util/PartnerStyleHelper.java114
-rw-r--r--main/src/com/google/android/setupdesign/util/TextViewPartnerStyler.java46
-rw-r--r--main/src/com/google/android/setupdesign/util/ThemeHelper.java17
-rw-r--r--main/src/com/google/android/setupdesign/util/ThemeResolver.java10
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;