blob: 8f807e6cb9d8d68baaa47c80c33f4a42b136cf56 [file] [log] [blame]
/*
* Copyright (C) 2017 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.setupcompat.template;
import static com.google.android.setupcompat.internal.Preconditions.ensureOnMainThread;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.PersistableBundle;
import android.util.AttributeSet;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewStub;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import androidx.annotation.AttrRes;
import androidx.annotation.CallSuper;
import androidx.annotation.ColorInt;
import androidx.annotation.IdRes;
import androidx.annotation.LayoutRes;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.annotation.VisibleForTesting;
import com.google.android.setupcompat.PartnerCustomizationLayout;
import com.google.android.setupcompat.R;
import com.google.android.setupcompat.internal.FooterButtonPartnerConfig;
import com.google.android.setupcompat.internal.TemplateLayout;
import com.google.android.setupcompat.logging.internal.FooterBarMixinMetrics;
import com.google.android.setupcompat.partnerconfig.PartnerConfig;
import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper;
import com.google.android.setupcompat.template.FooterButton.ButtonType;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicInteger;
/**
* A {@link Mixin} for managing buttons. By default, the button bar expects that buttons on the
* start (left for LTR) are "secondary" borderless buttons, while buttons on the end (right for LTR)
* are "primary" accent-colored buttons.
*/
public class FooterBarMixin implements Mixin {
private final Context context;
@Nullable private final ViewStub footerStub;
@VisibleForTesting final boolean applyPartnerResources;
@VisibleForTesting final boolean applyDynamicColor;
@VisibleForTesting final boolean useFullDynamicColor;
private LinearLayout buttonContainer;
private FooterButton primaryButton;
private FooterButton secondaryButton;
@IdRes private int primaryButtonId;
@IdRes private int secondaryButtonId;
ColorStateList primaryDefaultTextColor = null;
ColorStateList secondaryDefaultTextColor = null;
@VisibleForTesting public FooterButtonPartnerConfig primaryButtonPartnerConfigForTesting;
@VisibleForTesting public FooterButtonPartnerConfig secondaryButtonPartnerConfigForTesting;
private int footerBarPaddingTop;
private int footerBarPaddingBottom;
@VisibleForTesting int defaultPadding;
@ColorInt private final int footerBarPrimaryBackgroundColor;
@ColorInt private final int footerBarSecondaryBackgroundColor;
private boolean removeFooterBarWhenEmpty = true;
private boolean isSecondaryButtonInPrimaryStyle = false;
private static final AtomicInteger nextGeneratedId = new AtomicInteger(1);
@VisibleForTesting public final FooterBarMixinMetrics metrics = new FooterBarMixinMetrics();
private FooterButton.OnButtonEventListener createButtonEventListener(@IdRes int id) {
return new FooterButton.OnButtonEventListener() {
@Override
public void onEnabledChanged(boolean enabled) {
if (buttonContainer != null) {
Button button = buttonContainer.findViewById(id);
if (button != null) {
button.setEnabled(enabled);
if (applyPartnerResources) {
updateButtonTextColorWithPartnerConfig(
button,
(id == primaryButtonId || isSecondaryButtonInPrimaryStyle)
? PartnerConfig.CONFIG_FOOTER_PRIMARY_BUTTON_TEXT_COLOR
: PartnerConfig.CONFIG_FOOTER_SECONDARY_BUTTON_TEXT_COLOR);
}
}
}
}
@Override
public void onVisibilityChanged(int visibility) {
if (buttonContainer != null) {
Button button = buttonContainer.findViewById(id);
if (button != null) {
button.setVisibility(visibility);
autoSetButtonBarVisibility();
}
}
}
@Override
public void onTextChanged(CharSequence text) {
if (buttonContainer != null) {
Button button = buttonContainer.findViewById(id);
if (button != null) {
button.setText(text);
}
}
}
@Override
@TargetApi(VERSION_CODES.JELLY_BEAN_MR1)
public void onLocaleChanged(Locale locale) {
if (buttonContainer != null) {
Button button = buttonContainer.findViewById(id);
if (button != null && locale != null) {
button.setTextLocale(locale);
}
}
}
@Override
@TargetApi(VERSION_CODES.JELLY_BEAN_MR1)
public void onDirectionChanged(int direction) {
if (buttonContainer != null && direction != -1) {
buttonContainer.setLayoutDirection(direction);
}
}
};
}
/**
* Creates a mixin for managing buttons on the footer.
*
* @param layout The {@link TemplateLayout} containing this mixin.
* @param attrs XML attributes given to the layout.
* @param defStyleAttr The default style attribute as given to the constructor of the layout.
*/
public FooterBarMixin(
TemplateLayout layout, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
context = layout.getContext();
footerStub = layout.findManagedViewById(R.id.suc_layout_footer);
this.applyPartnerResources =
layout instanceof PartnerCustomizationLayout
&& ((PartnerCustomizationLayout) layout).shouldApplyPartnerResource();
applyDynamicColor =
layout instanceof PartnerCustomizationLayout
&& ((PartnerCustomizationLayout) layout).shouldApplyDynamicColor();
useFullDynamicColor =
layout instanceof PartnerCustomizationLayout
&& ((PartnerCustomizationLayout) layout).useFullDynamicColor();
TypedArray a =
context.obtainStyledAttributes(attrs, R.styleable.SucFooterBarMixin, defStyleAttr, 0);
defaultPadding =
a.getDimensionPixelSize(R.styleable.SucFooterBarMixin_sucFooterBarPaddingVertical, 0);
footerBarPaddingTop =
a.getDimensionPixelSize(
R.styleable.SucFooterBarMixin_sucFooterBarPaddingTop, defaultPadding);
footerBarPaddingBottom =
a.getDimensionPixelSize(
R.styleable.SucFooterBarMixin_sucFooterBarPaddingBottom, defaultPadding);
footerBarPrimaryBackgroundColor =
a.getColor(R.styleable.SucFooterBarMixin_sucFooterBarPrimaryFooterBackground, 0);
footerBarSecondaryBackgroundColor =
a.getColor(R.styleable.SucFooterBarMixin_sucFooterBarSecondaryFooterBackground, 0);
int primaryBtn =
a.getResourceId(R.styleable.SucFooterBarMixin_sucFooterBarPrimaryFooterButton, 0);
int secondaryBtn =
a.getResourceId(R.styleable.SucFooterBarMixin_sucFooterBarSecondaryFooterButton, 0);
a.recycle();
FooterButtonInflater inflater = new FooterButtonInflater(context);
if (secondaryBtn != 0) {
setSecondaryButton(inflater.inflate(secondaryBtn));
metrics.logPrimaryButtonInitialStateVisibility(/* isVisible= */ true, /* isUsingXml= */ true);
}
if (primaryBtn != 0) {
setPrimaryButton(inflater.inflate(primaryBtn));
metrics.logSecondaryButtonInitialStateVisibility(
/* isVisible= */ true, /* isUsingXml= */ true);
}
}
private View addSpace() {
LinearLayout buttonContainer = ensureFooterInflated();
View space = new View(buttonContainer.getContext());
space.setLayoutParams(new LayoutParams(0, 0, 1.0f));
space.setVisibility(View.INVISIBLE);
buttonContainer.addView(space);
return space;
}
@NonNull
private LinearLayout ensureFooterInflated() {
if (buttonContainer == null) {
if (footerStub == null) {
throw new IllegalStateException("Footer stub is not found in this template");
}
buttonContainer = (LinearLayout) inflateFooter(R.layout.suc_footer_button_bar);
onFooterBarInflated(buttonContainer);
onFooterBarApplyPartnerResource(buttonContainer);
}
return buttonContainer;
}
/**
* Notifies that the footer bar has been inflated to the view hierarchy. Calling super is
* necessary while subclass implement it.
*/
@CallSuper
protected void onFooterBarInflated(LinearLayout buttonContainer) {
if (buttonContainer == null) {
// Ignore action since buttonContainer is null
return;
}
if (Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
buttonContainer.setId(View.generateViewId());
} else {
buttonContainer.setId(generateViewId());
}
updateFooterBarPadding(
buttonContainer,
buttonContainer.getPaddingLeft(),
footerBarPaddingTop,
buttonContainer.getPaddingRight(),
footerBarPaddingBottom);
}
/**
* Notifies while the footer bar apply Partner Resource. Calling super is necessary while subclass
* implement it.
*/
@CallSuper
protected void onFooterBarApplyPartnerResource(LinearLayout buttonContainer) {
if (buttonContainer == null) {
// Ignore action since buttonContainer is null
return;
}
if (!applyPartnerResources) {
return;
}
// skip apply partner resources on footerbar background if dynamic color enabled
if (!useFullDynamicColor) {
@ColorInt
int color =
PartnerConfigHelper.get(context)
.getColor(context, PartnerConfig.CONFIG_FOOTER_BAR_BG_COLOR);
buttonContainer.setBackgroundColor(color);
}
footerBarPaddingTop =
(int)
PartnerConfigHelper.get(context)
.getDimension(context, PartnerConfig.CONFIG_FOOTER_BUTTON_PADDING_TOP);
footerBarPaddingBottom =
(int)
PartnerConfigHelper.get(context)
.getDimension(context, PartnerConfig.CONFIG_FOOTER_BUTTON_PADDING_BOTTOM);
updateFooterBarPadding(
buttonContainer,
buttonContainer.getPaddingLeft(),
footerBarPaddingTop,
buttonContainer.getPaddingRight(),
footerBarPaddingBottom);
if (PartnerConfigHelper.get(context)
.isPartnerConfigAvailable(PartnerConfig.CONFIG_FOOTER_BAR_MIN_HEIGHT)) {
int minHeight =
(int)
PartnerConfigHelper.get(context)
.getDimension(context, PartnerConfig.CONFIG_FOOTER_BAR_MIN_HEIGHT);
if (minHeight > 0) {
buttonContainer.setMinimumHeight(minHeight);
}
}
}
/**
* Inflate FooterActionButton with layout "suc_button". Subclasses can implement this method to
* modify the footer button layout as necessary.
*/
@SuppressLint("InflateParams")
protected FooterActionButton createThemedButton(Context context, @StyleRes int theme) {
// Inflate a single button from XML, which when using support lib, will take advantage of
// the injected layout inflater and give us AppCompatButton instead.
LayoutInflater inflater = LayoutInflater.from(new ContextThemeWrapper(context, theme));
return (FooterActionButton) inflater.inflate(R.layout.suc_button, null, false);
}
/** Sets primary button for footer. */
@MainThread
public void setPrimaryButton(FooterButton footerButton) {
ensureOnMainThread("setPrimaryButton");
ensureFooterInflated();
// Setup button partner config
FooterButtonPartnerConfig footerButtonPartnerConfig =
new FooterButtonPartnerConfig.Builder(footerButton)
.setPartnerTheme(
getPartnerTheme(
footerButton,
/* defaultPartnerTheme= */ R.style.SucPartnerCustomizationButton_Primary,
/* buttonBackgroundColorConfig= */ PartnerConfig
.CONFIG_FOOTER_PRIMARY_BUTTON_BG_COLOR))
.setButtonBackgroundConfig(PartnerConfig.CONFIG_FOOTER_PRIMARY_BUTTON_BG_COLOR)
.setButtonDisableAlphaConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_DISABLED_ALPHA)
.setButtonDisableBackgroundConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_DISABLED_BG_COLOR)
.setButtonIconConfig(getDrawablePartnerConfig(footerButton.getButtonType()))
.setButtonRadiusConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_RADIUS)
.setButtonRippleColorAlphaConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_RIPPLE_COLOR_ALPHA)
.setTextColorConfig(PartnerConfig.CONFIG_FOOTER_PRIMARY_BUTTON_TEXT_COLOR)
.setTextSizeConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_TEXT_SIZE)
.setButtonMinHeight(PartnerConfig.CONFIG_FOOTER_BUTTON_MIN_HEIGHT)
.setTextTypeFaceConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_FONT_FAMILY)
.setTextStyleConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_TEXT_STYLE)
.build();
FooterActionButton button = inflateButton(footerButton, footerButtonPartnerConfig);
// update information for primary button. Need to update as long as the button inflated.
primaryButtonId = button.getId();
primaryDefaultTextColor = button.getTextColors();
primaryButton = footerButton;
primaryButtonPartnerConfigForTesting = footerButtonPartnerConfig;
onFooterButtonInflated(button, footerBarPrimaryBackgroundColor);
onFooterButtonApplyPartnerResource(button, footerButtonPartnerConfig);
// Make sure the position of buttons are correctly and prevent primary button create twice or
// more.
repopulateButtons();
}
/** Returns the {@link FooterButton} of primary button. */
public FooterButton getPrimaryButton() {
return primaryButton;
}
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
public Button getPrimaryButtonView() {
return buttonContainer == null ? null : buttonContainer.findViewById(primaryButtonId);
}
@VisibleForTesting
boolean isPrimaryButtonVisible() {
return getPrimaryButtonView() != null && getPrimaryButtonView().getVisibility() == View.VISIBLE;
}
/** Sets secondary button for footer. */
@MainThread
public void setSecondaryButton(FooterButton footerButton) {
setSecondaryButton(footerButton, /*usePrimaryStyle= */ false);
}
/** Sets secondary button for footer. Allow to use the primary button style. */
@MainThread
public void setSecondaryButton(FooterButton footerButton, boolean usePrimaryStyle) {
ensureOnMainThread("setSecondaryButton");
isSecondaryButtonInPrimaryStyle = usePrimaryStyle;
ensureFooterInflated();
// Setup button partner config
FooterButtonPartnerConfig footerButtonPartnerConfig =
new FooterButtonPartnerConfig.Builder(footerButton)
.setPartnerTheme(
getPartnerTheme(
footerButton,
/* defaultPartnerTheme= */ usePrimaryStyle
? R.style.SucPartnerCustomizationButton_Primary
: R.style.SucPartnerCustomizationButton_Secondary,
/* buttonBackgroundColorConfig= */ usePrimaryStyle
? PartnerConfig.CONFIG_FOOTER_PRIMARY_BUTTON_BG_COLOR
: PartnerConfig.CONFIG_FOOTER_SECONDARY_BUTTON_BG_COLOR))
.setButtonBackgroundConfig(
usePrimaryStyle
? PartnerConfig.CONFIG_FOOTER_PRIMARY_BUTTON_BG_COLOR
: PartnerConfig.CONFIG_FOOTER_SECONDARY_BUTTON_BG_COLOR)
.setButtonDisableAlphaConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_DISABLED_ALPHA)
.setButtonDisableBackgroundConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_DISABLED_BG_COLOR)
.setButtonIconConfig(getDrawablePartnerConfig(footerButton.getButtonType()))
.setButtonRadiusConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_RADIUS)
.setButtonRippleColorAlphaConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_RIPPLE_COLOR_ALPHA)
.setTextColorConfig(
usePrimaryStyle
? PartnerConfig.CONFIG_FOOTER_PRIMARY_BUTTON_TEXT_COLOR
: PartnerConfig.CONFIG_FOOTER_SECONDARY_BUTTON_TEXT_COLOR)
.setTextSizeConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_TEXT_SIZE)
.setButtonMinHeight(PartnerConfig.CONFIG_FOOTER_BUTTON_MIN_HEIGHT)
.setTextTypeFaceConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_FONT_FAMILY)
.setTextStyleConfig(PartnerConfig.CONFIG_FOOTER_BUTTON_TEXT_STYLE)
.build();
FooterActionButton button = inflateButton(footerButton, footerButtonPartnerConfig);
// update information for secondary button. Need to update as long as the button inflated.
secondaryButtonId = button.getId();
secondaryDefaultTextColor = button.getTextColors();
secondaryButton = footerButton;
secondaryButtonPartnerConfigForTesting = footerButtonPartnerConfig;
onFooterButtonInflated(button, footerBarSecondaryBackgroundColor);
onFooterButtonApplyPartnerResource(button, footerButtonPartnerConfig);
// Make sure the position of buttons are correctly and prevent secondary button create twice or
// more.
repopulateButtons();
}
/**
* Corrects the order of footer buttons after the button has been inflated to the view hierarchy.
* Subclasses can implement this method to modify the order of footer buttons as necessary.
*/
protected void repopulateButtons() {
LinearLayout buttonContainer = ensureFooterInflated();
Button tempPrimaryButton = getPrimaryButtonView();
Button tempSecondaryButton = getSecondaryButtonView();
buttonContainer.removeAllViews();
if (tempSecondaryButton != null) {
if (isSecondaryButtonInPrimaryStyle) {
// Since the secondary button has the same style (with background) as the primary button,
// we need to have the left padding equal to the right padding.
updateFooterBarPadding(
buttonContainer,
buttonContainer.getPaddingRight(),
buttonContainer.getPaddingTop(),
buttonContainer.getPaddingRight(),
buttonContainer.getPaddingBottom());
}
buttonContainer.addView(tempSecondaryButton);
}
addSpace();
if (tempPrimaryButton != null) {
buttonContainer.addView(tempPrimaryButton);
}
}
/**
* Notifies that the footer button has been inInflated and add to the view hierarchy. Calling
* super is necessary while subclass implement it.
*/
@CallSuper
protected void onFooterButtonInflated(Button button, @ColorInt int defaultButtonBackgroundColor) {
// Try to set default background
if (defaultButtonBackgroundColor != 0) {
FooterButtonStyleUtils.updateButtonBackground(button, defaultButtonBackgroundColor);
} else {
// TODO: get button background color from activity theme
}
buttonContainer.addView(button);
autoSetButtonBarVisibility();
}
private int getPartnerTheme(
FooterButton footerButton,
int defaultPartnerTheme,
PartnerConfig buttonBackgroundColorConfig) {
int overrideTheme = footerButton.getTheme();
// Set the default theme if theme is not set, or when running in setup flow.
if (footerButton.getTheme() == 0 || applyPartnerResources) {
overrideTheme = defaultPartnerTheme;
}
// TODO: Make sure customize attributes in theme can be applied during setup flow.
// If sets background color to full transparent, the button changes to colored borderless ink
// button style.
if (applyPartnerResources) {
int color = PartnerConfigHelper.get(context).getColor(context, buttonBackgroundColorConfig);
if (color == Color.TRANSPARENT) {
overrideTheme = R.style.SucPartnerCustomizationButton_Secondary;
} else if (color != Color.TRANSPARENT) {
// TODO: remove the constrain (color != Color.WHITE), need to check all pages
// go well without customization. It should be fine since the default value of secondary bg
// color is set as transparent.
overrideTheme = R.style.SucPartnerCustomizationButton_Primary;
}
}
return overrideTheme;
}
@VisibleForTesting
public LinearLayout getButtonContainer() {
return buttonContainer;
}
/** Returns the {@link FooterButton} of secondary button. */
public FooterButton getSecondaryButton() {
return secondaryButton;
}
/**
* Sets whether the footer bar should be removed when there are no footer buttons in the bar.
*
* @param value True if footer bar is gone, false otherwise.
*/
public void setRemoveFooterBarWhenEmpty(boolean value) {
removeFooterBarWhenEmpty = value;
autoSetButtonBarVisibility();
}
/**
* Checks the visibility state of footer buttons to set the visibility state of this footer bar
* automatically.
*/
private void autoSetButtonBarVisibility() {
Button primaryButton = getPrimaryButtonView();
Button secondaryButton = getSecondaryButtonView();
boolean primaryVisible = primaryButton != null && primaryButton.getVisibility() == View.VISIBLE;
boolean secondaryVisible =
secondaryButton != null && secondaryButton.getVisibility() == View.VISIBLE;
if (buttonContainer != null) {
buttonContainer.setVisibility(
primaryVisible || secondaryVisible
? View.VISIBLE
: removeFooterBarWhenEmpty ? View.GONE : View.INVISIBLE);
}
}
/** Returns the visibility status for this footer bar. */
@VisibleForTesting
public int getVisibility() {
return buttonContainer.getVisibility();
}
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
public Button getSecondaryButtonView() {
return buttonContainer == null ? null : buttonContainer.findViewById(secondaryButtonId);
}
@VisibleForTesting
boolean isSecondaryButtonVisible() {
return getSecondaryButtonView() != null
&& getSecondaryButtonView().getVisibility() == View.VISIBLE;
}
private static int generateViewId() {
for (; ; ) {
final int result = nextGeneratedId.get();
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
int newValue = result + 1;
if (newValue > 0x00FFFFFF) {
newValue = 1; // Roll over to 1, not 0.
}
if (nextGeneratedId.compareAndSet(result, newValue)) {
return result;
}
}
}
private FooterActionButton inflateButton(
FooterButton footerButton, FooterButtonPartnerConfig footerButtonPartnerConfig) {
FooterActionButton button =
createThemedButton(context, footerButtonPartnerConfig.getPartnerTheme());
if (Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
button.setId(View.generateViewId());
} else {
button.setId(generateViewId());
}
// apply initial configuration into button view.
button.setText(footerButton.getText());
button.setOnClickListener(footerButton);
button.setVisibility(footerButton.getVisibility());
button.setEnabled(footerButton.isEnabled());
button.setFooterButton(footerButton);
footerButton.setOnButtonEventListener(createButtonEventListener(button.getId()));
return button;
}
// TODO: Make sure customize attributes in theme can be applied during setup flow.
@TargetApi(VERSION_CODES.Q)
private void onFooterButtonApplyPartnerResource(
Button button, FooterButtonPartnerConfig footerButtonPartnerConfig) {
if (!applyPartnerResources) {
return;
}
// If dynamic color enabled, these colors won't be overrode by partner config.
// Instead, these colors align with the current theme colors.
if (!applyDynamicColor) {
updateButtonTextColorWithPartnerConfig(
button, footerButtonPartnerConfig.getButtonTextColorConfig());
FooterButtonStyleUtils.updateButtonBackgroundWithPartnerConfig(
context,
button,
footerButtonPartnerConfig.getButtonBackgroundConfig(),
footerButtonPartnerConfig.getButtonDisableAlphaConfig(),
footerButtonPartnerConfig.getButtonDisableBackgroundConfig());
FooterButtonStyleUtils.updateButtonRippleColorWithPartnerConfig(
context, button, footerButtonPartnerConfig);
}
FooterButtonStyleUtils.updateButtonTextSizeWithPartnerConfig(
context, button, footerButtonPartnerConfig.getButtonTextSizeConfig());
FooterButtonStyleUtils.updateButtonMinHeightWithPartnerConfig(
context, button, footerButtonPartnerConfig.getButtonMinHeightConfig());
FooterButtonStyleUtils.updateButtonTypeFaceWithPartnerConfig(
context,
button,
footerButtonPartnerConfig.getButtonTextTypeFaceConfig(),
footerButtonPartnerConfig.getButtonTextStyleConfig());
FooterButtonStyleUtils.updateButtonRadiusWithPartnerConfig(
context, button, footerButtonPartnerConfig.getButtonRadiusConfig());
FooterButtonStyleUtils.updateButtonIconWithPartnerConfig(
context,
button,
footerButtonPartnerConfig.getButtonIconConfig(),
primaryButtonId == button.getId());
}
private void updateButtonTextColorWithPartnerConfig(
Button button, PartnerConfig buttonTextColorConfig) {
if (button.isEnabled()) {
FooterButtonStyleUtils.updateButtonTextEnabledColorWithPartnerConfig(
context, button, buttonTextColorConfig);
} else {
FooterButtonStyleUtils.updateButtonTextDisableColor(
button,
/* is Primary= */ (primaryButtonId == button.getId() || isSecondaryButtonInPrimaryStyle)
? primaryDefaultTextColor
: secondaryDefaultTextColor);
}
}
private static PartnerConfig getDrawablePartnerConfig(@ButtonType int buttonType) {
PartnerConfig result;
switch (buttonType) {
case ButtonType.ADD_ANOTHER:
result = PartnerConfig.CONFIG_FOOTER_BUTTON_ICON_ADD_ANOTHER;
break;
case ButtonType.CANCEL:
result = PartnerConfig.CONFIG_FOOTER_BUTTON_ICON_CANCEL;
break;
case ButtonType.CLEAR:
result = PartnerConfig.CONFIG_FOOTER_BUTTON_ICON_CLEAR;
break;
case ButtonType.DONE:
result = PartnerConfig.CONFIG_FOOTER_BUTTON_ICON_DONE;
break;
case ButtonType.NEXT:
result = PartnerConfig.CONFIG_FOOTER_BUTTON_ICON_NEXT;
break;
case ButtonType.OPT_IN:
result = PartnerConfig.CONFIG_FOOTER_BUTTON_ICON_OPT_IN;
break;
case ButtonType.SKIP:
result = PartnerConfig.CONFIG_FOOTER_BUTTON_ICON_SKIP;
break;
case ButtonType.STOP:
result = PartnerConfig.CONFIG_FOOTER_BUTTON_ICON_STOP;
break;
case ButtonType.OTHER:
default:
result = null;
break;
}
return result;
}
protected View inflateFooter(@LayoutRes int footer) {
if (Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
LayoutInflater inflater =
LayoutInflater.from(
new ContextThemeWrapper(context, R.style.SucPartnerCustomizationButtonBar_Stackable));
footerStub.setLayoutInflater(inflater);
}
footerStub.setLayoutResource(footer);
return footerStub.inflate();
}
private void updateFooterBarPadding(
LinearLayout buttonContainer, int left, int top, int right, int bottom) {
if (buttonContainer == null) {
// Ignore action since buttonContainer is null
return;
}
buttonContainer.setPadding(left, top, right, bottom);
}
/** Returns the paddingTop of footer bar. */
@VisibleForTesting
int getPaddingTop() {
return (buttonContainer != null) ? buttonContainer.getPaddingTop() : footerStub.getPaddingTop();
}
/** Returns the paddingBottom of footer bar. */
@VisibleForTesting
int getPaddingBottom() {
return (buttonContainer != null)
? buttonContainer.getPaddingBottom()
: footerStub.getPaddingBottom();
}
/** Uses for notify mixin the view already attached to window. */
public void onAttachedToWindow() {
metrics.logPrimaryButtonInitialStateVisibility(
/* isVisible= */ isPrimaryButtonVisible(), /* isUsingXml= */ false);
metrics.logSecondaryButtonInitialStateVisibility(
/* isVisible= */ isSecondaryButtonVisible(), /* isUsingXml= */ false);
}
/** Uses for notify mixin the view already detached from window. */
public void onDetachedFromWindow() {
metrics.updateButtonVisibility(isPrimaryButtonVisible(), isSecondaryButtonVisible());
}
/**
* Assigns logging metrics to bundle for PartnerCustomizationLayout to log metrics to SetupWizard.
*/
@TargetApi(VERSION_CODES.Q)
public PersistableBundle getLoggingMetrics() {
return metrics.getMetrics();
}
}