1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.car.setupwizardlib; 17 18 import android.content.Context; 19 import android.content.res.TypedArray; 20 import android.graphics.PorterDuff; 21 import android.graphics.Rect; 22 import android.graphics.Typeface; 23 import android.graphics.drawable.Drawable; 24 import android.graphics.drawable.GradientDrawable; 25 import android.graphics.drawable.InsetDrawable; 26 import android.graphics.drawable.RippleDrawable; 27 import android.text.TextUtils; 28 import android.util.AttributeSet; 29 import android.util.Log; 30 import android.util.TypedValue; 31 import android.view.LayoutInflater; 32 import android.view.TouchDelegate; 33 import android.view.View; 34 import android.view.ViewGroup; 35 import android.view.ViewStub; 36 import android.widget.Button; 37 import android.widget.ImageView; 38 import android.widget.LinearLayout; 39 import android.widget.ProgressBar; 40 import android.widget.TextView; 41 42 import androidx.annotation.Nullable; 43 import androidx.annotation.StyleRes; 44 import androidx.annotation.VisibleForTesting; 45 46 import com.android.car.setupwizardlib.partner.PartnerConfig; 47 import com.android.car.setupwizardlib.partner.PartnerConfigHelper; 48 49 import java.util.Locale; 50 import java.util.Objects; 51 52 /** 53 * Custom layout for the Car Setup Wizard. Provides accessors for modifying elements such as buttons 54 * and progress bars. Any modifications to elements built by 55 * the CarSetupWizardLayout should be done through methods provided by this class unless that is 56 * not possible so as to keep the state internally consistent. 57 * 58 * @deprecated Use {@link CarSetupWizardCompatLayout} or {@link CarSetupWizardDesignLayout}. 59 */ 60 @Deprecated 61 public class CarSetupWizardLayout extends LinearLayout { 62 private static final String TAG = CarSetupWizardLayout.class.getSimpleName(); 63 64 private View mBackButton; 65 private View mTitleBar; 66 private TextView mToolbarTitle; 67 private PartnerConfigHelper mPartnerConfigHelper; 68 69 /* <p>The Primary Toolbar Button should always be used when there is only a single action that 70 * moves the wizard to the next screen (e.g. Only need a 'Skip' button). 71 * 72 * When there are two actions that can move the wizard to the next screen (e.g. either 'Skip' 73 * or 'Let's Go' are the two options), then the Primary is used for the positive action 74 * while the Secondary is used for the negative action.</p> 75 */ 76 private Button mPrimaryToolbarButton; 77 78 /* 79 * Flag to track the primary toolbar button flat state. 80 */ 81 private boolean mPrimaryToolbarButtonFlat; 82 private View.OnClickListener mPrimaryToolbarButtonOnClick; 83 private Button mSecondaryToolbarButton; 84 private ProgressBar mProgressBar; 85 CarSetupWizardLayout(Context context)86 public CarSetupWizardLayout(Context context) { 87 this(context, null); 88 } 89 CarSetupWizardLayout(Context context, @Nullable AttributeSet attrs)90 public CarSetupWizardLayout(Context context, @Nullable AttributeSet attrs) { 91 this(context, attrs, 0); 92 } 93 CarSetupWizardLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr)94 public CarSetupWizardLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 95 this(context, attrs, defStyleAttr, 0); 96 } 97 98 /** 99 * On initialization, the layout gets all of the custom attributes and initializes 100 * the custom views that can be set by the user (e.g. back button, continue button). 101 */ CarSetupWizardLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)102 public CarSetupWizardLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr, 103 int defStyleRes) { 104 super(context, attrs, defStyleAttr, defStyleRes); 105 106 mPartnerConfigHelper = PartnerConfigHelper.get(context); 107 TypedArray attrArray = context.getTheme().obtainStyledAttributes( 108 attrs, 109 R.styleable.CarSetupWizardLayout, 110 0, 0); 111 112 init(attrArray); 113 } 114 115 /** 116 * Inflates the layout and sets the custom views (e.g. back button, continue button). 117 */ init(TypedArray attrArray)118 private void init(TypedArray attrArray) { 119 boolean showBackButton; 120 121 boolean showToolbarTitle; 122 String toolbarTitleText; 123 124 boolean showPrimaryToolbarButton; 125 String primaryToolbarButtonText; 126 boolean primaryToolbarButtonEnabled; 127 128 boolean showSecondaryToolbarButton; 129 String secondaryToolbarButtonText; 130 boolean secondaryToolbarButtonEnabled; 131 132 boolean showProgressBar; 133 boolean indeterminateProgressBar; 134 135 try { 136 showBackButton = attrArray.getBoolean( 137 R.styleable.CarSetupWizardLayout_showBackButton, true); 138 showToolbarTitle = attrArray.getBoolean( 139 R.styleable.CarSetupWizardLayout_showToolbarTitle, false); 140 toolbarTitleText = attrArray.getString( 141 R.styleable.CarSetupWizardLayout_toolbarTitleText); 142 showPrimaryToolbarButton = attrArray.getBoolean( 143 R.styleable.CarSetupWizardLayout_showPrimaryToolbarButton, true); 144 primaryToolbarButtonText = attrArray.getString( 145 R.styleable.CarSetupWizardLayout_primaryToolbarButtonText); 146 primaryToolbarButtonEnabled = attrArray.getBoolean( 147 R.styleable.CarSetupWizardLayout_primaryToolbarButtonEnabled, true); 148 mPrimaryToolbarButtonFlat = attrArray.getBoolean( 149 R.styleable.CarSetupWizardLayout_primaryToolbarButtonFlat, false); 150 showSecondaryToolbarButton = attrArray.getBoolean( 151 R.styleable.CarSetupWizardLayout_showSecondaryToolbarButton, false); 152 secondaryToolbarButtonText = attrArray.getString( 153 R.styleable.CarSetupWizardLayout_secondaryToolbarButtonText); 154 secondaryToolbarButtonEnabled = attrArray.getBoolean( 155 R.styleable.CarSetupWizardLayout_secondaryToolbarButtonEnabled, true); 156 showProgressBar = attrArray.getBoolean( 157 R.styleable.CarSetupWizardLayout_showProgressBar, false); 158 indeterminateProgressBar = attrArray.getBoolean( 159 R.styleable.CarSetupWizardLayout_indeterminateProgressBar, true); 160 } finally { 161 attrArray.recycle(); 162 } 163 164 LayoutInflater inflater = LayoutInflater.from(getContext()); 165 inflater.inflate(R.layout.car_setup_wizard_layout, this); 166 167 // Set the back button visibility based on the custom attribute. 168 setBackButton(findViewById(R.id.back_button)); 169 Drawable drawable = mPartnerConfigHelper.getDrawable( 170 getContext(), PartnerConfig.CONFIG_TOOLBAR_BUTTON_ICON_BACK); 171 if (drawable != null) { 172 ((ImageView) mBackButton).setImageDrawable(drawable); 173 } 174 setBackButtonVisible(showBackButton); 175 176 // Se the title bar. 177 setTitleBar(findViewById(R.id.application_bar)); 178 int toolbarBgColor = 179 mPartnerConfigHelper.getColor(getContext(), PartnerConfig.CONFIG_TOOLBAR_BG_COLOR); 180 if (toolbarBgColor != 0) { 181 mTitleBar.setBackgroundColor(toolbarBgColor); 182 } 183 184 // Set the toolbar title visibility and text based on the custom attributes. 185 setToolbarTitle(findViewById(R.id.toolbar_title)); 186 if (showToolbarTitle) { 187 setToolbarTitleText(toolbarTitleText); 188 } else { 189 setToolbarTitleVisible(false); 190 } 191 192 // Set the primary continue button visibility and text based on the custom attributes. 193 ViewStub primaryToolbarButtonStub = 194 (ViewStub) findViewById(R.id.primary_toolbar_button_stub); 195 // Set the button layout to flat if that attribute was set. 196 if (mPrimaryToolbarButtonFlat) { 197 primaryToolbarButtonStub.setLayoutResource(R.layout.flat_button); 198 } 199 primaryToolbarButtonStub.inflate(); 200 setPrimaryToolbarButton(findViewById(R.id.primary_toolbar_button)); 201 if (showPrimaryToolbarButton) { 202 setPrimaryToolbarButtonText(primaryToolbarButtonText); 203 setPrimaryToolbarButtonEnabled(primaryToolbarButtonEnabled); 204 205 setBackground( 206 mPrimaryToolbarButton, 207 PartnerConfig.CONFIG_TOOLBAR_PRIMARY_BUTTON_BG, 208 PartnerConfig.CONFIG_TOOLBAR_PRIMARY_BUTTON_BG_COLOR); 209 210 setButtonPadding(mPrimaryToolbarButton); 211 setButtonTypeFace(mPrimaryToolbarButton); 212 setButtonTextSize(mPrimaryToolbarButton); 213 setButtonTextColor( 214 mPrimaryToolbarButton, 215 PartnerConfig.CONFIG_TOOLBAR_PRIMARY_BUTTON_TEXT_COLOR); 216 } else { 217 setPrimaryToolbarButtonVisible(false); 218 } 219 220 // Set the secondary continue button visibility and text based on the custom attributes. 221 ViewStub secondaryToolbarButtonStub = 222 (ViewStub) findViewById(R.id.secondary_toolbar_button_stub); 223 if (showSecondaryToolbarButton || !TextUtils.isEmpty(secondaryToolbarButtonText)) { 224 secondaryToolbarButtonStub.inflate(); 225 mSecondaryToolbarButton = findViewById(R.id.secondary_toolbar_button); 226 setSecondaryToolbarButtonText(secondaryToolbarButtonText); 227 setSecondaryToolbarButtonEnabled(secondaryToolbarButtonEnabled); 228 setSecondaryToolbarButtonVisible(showSecondaryToolbarButton); 229 } 230 231 mProgressBar = findViewById(R.id.progress_bar); 232 setProgressBarVisible(showProgressBar); 233 setProgressBarIndeterminate(indeterminateProgressBar); 234 235 // Set orientation programmatically since the inflated layout uses <merge> 236 setOrientation(LinearLayout.VERTICAL); 237 } 238 239 /** 240 * Set a given view's visibility. 241 */ 242 @VisibleForTesting setViewVisible(View view, boolean visible)243 void setViewVisible(View view, boolean visible) { 244 view.setVisibility(visible ? View.VISIBLE : View.GONE); 245 } 246 247 // Add or remove the back button touch delegate depending on whether it is visible. 248 @VisibleForTesting updateBackButtonTouchDelegate(boolean visible)249 void updateBackButtonTouchDelegate(boolean visible) { 250 if (visible) { 251 // Post this action in the parent's message queue to make sure the parent 252 // lays out its children before getHitRect() is called 253 this.post(() -> { 254 Rect delegateArea = new Rect(); 255 256 mBackButton.getHitRect(delegateArea); 257 258 /* 259 * Update the delegate area based on the difference between the current size and 260 * the touch target size 261 */ 262 float touchTargetSize = getResources().getDimension( 263 R.dimen.car_touch_target_size); 264 float primaryIconSize = getResources().getDimension( 265 R.dimen.car_primary_icon_size); 266 267 int sizeDifference = (int) ((touchTargetSize - primaryIconSize) / 2); 268 269 delegateArea.right += sizeDifference; 270 delegateArea.bottom += sizeDifference; 271 delegateArea.left -= sizeDifference; 272 delegateArea.top -= sizeDifference; 273 274 // Set the TouchDelegate on the parent view 275 TouchDelegate touchDelegate = new TouchDelegate(delegateArea, 276 mBackButton); 277 278 if (View.class.isInstance(mBackButton.getParent())) { 279 ((View) mBackButton.getParent()).setTouchDelegate(touchDelegate); 280 } 281 }); 282 } else { 283 // Set the TouchDelegate to null if the back button is not visible. 284 if (View.class.isInstance(mBackButton.getParent())) { 285 ((View) mBackButton.getParent()).setTouchDelegate(null); 286 } 287 } 288 } 289 290 /** 291 * Gets the back button. 292 */ getBackButton()293 public View getBackButton() { 294 return mBackButton; 295 } 296 297 @VisibleForTesting setBackButton(View backButton)298 final void setBackButton(View backButton) { 299 mBackButton = backButton; 300 } 301 302 /** 303 * Set the back button onClickListener to given listener. Can be null if the listener should 304 * be overridden so no callback is made. 305 */ setBackButtonListener(@ullable View.OnClickListener listener)306 public void setBackButtonListener(@Nullable View.OnClickListener listener) { 307 mBackButton.setOnClickListener(listener); 308 } 309 310 /** 311 * Set the back button visibility to the given visibility. 312 */ setBackButtonVisible(boolean visible)313 public void setBackButtonVisible(boolean visible) { 314 setViewVisible(mBackButton, visible); 315 updateBackButtonTouchDelegate(visible); 316 } 317 318 /** 319 * Gets the toolbar title. 320 */ getToolbarTitle()321 public TextView getToolbarTitle() { 322 return mToolbarTitle; 323 } 324 325 @VisibleForTesting setToolbarTitle(TextView toolbarTitle)326 final void setToolbarTitle(TextView toolbarTitle) { 327 mToolbarTitle = toolbarTitle; 328 } 329 330 /** 331 * Sets the header title visibility to given value. 332 */ setToolbarTitleVisible(boolean visible)333 public void setToolbarTitleVisible(boolean visible) { 334 setViewVisible(mToolbarTitle, visible); 335 } 336 337 /** 338 * Sets the header title text to the provided text. 339 */ setToolbarTitleText(String text)340 public void setToolbarTitleText(String text) { 341 mToolbarTitle.setText(text); 342 } 343 344 /** 345 * Sets the style for the toolbar title. 346 */ setToolbarTitleStyle(@tyleRes int style)347 public void setToolbarTitleStyle(@StyleRes int style) { 348 mToolbarTitle.setTextAppearance(style); 349 } 350 351 /** 352 * Gets the primary toolbar button. 353 */ getPrimaryToolbarButton()354 public Button getPrimaryToolbarButton() { 355 return mPrimaryToolbarButton; 356 } 357 358 @VisibleForTesting setPrimaryToolbarButton(Button primaryToolbarButton)359 final void setPrimaryToolbarButton(Button primaryToolbarButton) { 360 mPrimaryToolbarButton = primaryToolbarButton; 361 } 362 363 /** 364 * Set the primary continue button visibility to the given visibility. 365 */ setPrimaryToolbarButtonVisible(boolean visible)366 public void setPrimaryToolbarButtonVisible(boolean visible) { 367 setViewVisible(mPrimaryToolbarButton, visible); 368 } 369 370 /** 371 * Set whether the primary continue button is enabled. 372 */ setPrimaryToolbarButtonEnabled(boolean enabled)373 public void setPrimaryToolbarButtonEnabled(boolean enabled) { 374 mPrimaryToolbarButton.setEnabled(enabled); 375 } 376 377 /** 378 * Set the primary continue button text to the given text. 379 */ setPrimaryToolbarButtonText(String text)380 public void setPrimaryToolbarButtonText(String text) { 381 mPrimaryToolbarButton.setText(text); 382 } 383 384 /** 385 * Set the primary continue button onClickListener to the given listener. Can be null if the 386 * listener should be overridden so no callback is made. All changes to primary toolbar 387 * button's onClickListener should be made here so they can be stored through changes to the 388 * button. 389 */ setPrimaryToolbarButtonListener(@ullable View.OnClickListener listener)390 public void setPrimaryToolbarButtonListener(@Nullable View.OnClickListener listener) { 391 mPrimaryToolbarButtonOnClick = listener; 392 mPrimaryToolbarButton.setOnClickListener(listener); 393 } 394 395 /** 396 * Getter for the flatness of the primary toolbar button. 397 */ getPrimaryToolbarButtonFlat()398 public boolean getPrimaryToolbarButtonFlat() { 399 return mPrimaryToolbarButtonFlat; 400 } 401 402 /** 403 * Changes the button in the primary slot to a flat theme, maintaining the text, visibility, 404 * whether it is enabled, and id. 405 * <p>NOTE: that other attributes set manually on the primaryToolbarButton will be lost on calls 406 * to this method as the button will be replaced.</p> 407 */ setPrimaryToolbarButtonFlat(boolean isFlat)408 public void setPrimaryToolbarButtonFlat(boolean isFlat) { 409 // Do nothing if the state isn't changing. 410 if (isFlat == mPrimaryToolbarButtonFlat) { 411 return; 412 } 413 Button newPrimaryButton = createPrimaryToolbarButton(isFlat); 414 415 ViewGroup parent = (ViewGroup) findViewById(R.id.button_container); 416 int buttonIndex = parent.indexOfChild(mPrimaryToolbarButton); 417 parent.removeViewAt(buttonIndex); 418 parent.addView(newPrimaryButton, buttonIndex); 419 420 // Update state of layout 421 setPrimaryToolbarButton(newPrimaryButton); 422 mPrimaryToolbarButtonFlat = isFlat; 423 } 424 425 @VisibleForTesting createPrimaryToolbarButton(boolean isFlat)426 Button createPrimaryToolbarButton(boolean isFlat) { 427 int layoutId = isFlat ? R.layout.flat_button : R.layout.primary_button; 428 Button newPrimaryButton = (Button) inflate(getContext(), layoutId, null); 429 newPrimaryButton.setId(mPrimaryToolbarButton.getId()); 430 newPrimaryButton.setVisibility(mPrimaryToolbarButton.getVisibility()); 431 newPrimaryButton.setEnabled(mPrimaryToolbarButton.isEnabled()); 432 newPrimaryButton.setText(mPrimaryToolbarButton.getText()); 433 newPrimaryButton.setOnClickListener(mPrimaryToolbarButtonOnClick); 434 newPrimaryButton.setLayoutParams(mPrimaryToolbarButton.getLayoutParams()); 435 436 return newPrimaryButton; 437 } 438 439 /** 440 * Gets the secondary toolbar button. 441 */ getSecondaryToolbarButton()442 public Button getSecondaryToolbarButton() { 443 return mSecondaryToolbarButton; 444 } 445 446 /** 447 * Set the secondary continue button visibility to the given visibility. 448 */ setSecondaryToolbarButtonVisible(boolean visible)449 public void setSecondaryToolbarButtonVisible(boolean visible) { 450 // If not setting it visible and it hasn't been inflated yet then don't inflate. 451 if (!visible && mSecondaryToolbarButton == null) { 452 return; 453 } 454 maybeInflateSecondaryToolbarButton(); 455 setViewVisible(mSecondaryToolbarButton, visible); 456 } 457 458 /** 459 * Sets whether the secondary continue button is enabled. 460 */ setSecondaryToolbarButtonEnabled(boolean enabled)461 public void setSecondaryToolbarButtonEnabled(boolean enabled) { 462 maybeInflateSecondaryToolbarButton(); 463 mSecondaryToolbarButton.setEnabled(enabled); 464 } 465 466 /** 467 * Sets the secondary continue button text to the given text. 468 */ setSecondaryToolbarButtonText(String text)469 public void setSecondaryToolbarButtonText(String text) { 470 maybeInflateSecondaryToolbarButton(); 471 mSecondaryToolbarButton.setText(text); 472 } 473 474 /** 475 * Sets the secondary continue button onClickListener to the given listener. Can be null if the 476 * listener should be overridden so no callback is made. 477 */ setSecondaryToolbarButtonListener(@ullable View.OnClickListener listener)478 public void setSecondaryToolbarButtonListener(@Nullable View.OnClickListener listener) { 479 maybeInflateSecondaryToolbarButton(); 480 mSecondaryToolbarButton.setOnClickListener(listener); 481 } 482 483 /** 484 * Gets the progress bar. 485 */ getProgressBar()486 public ProgressBar getProgressBar() { 487 return mProgressBar; 488 } 489 490 /** 491 * Sets the progress bar visibility to the given visibility. 492 */ setProgressBarVisible(boolean visible)493 public void setProgressBarVisible(boolean visible) { 494 setViewVisible(mProgressBar, visible); 495 } 496 497 /** 498 * Sets the progress bar indeterminate/determinate state. 499 */ setProgressBarIndeterminate(boolean indeterminate)500 public void setProgressBarIndeterminate(boolean indeterminate) { 501 mProgressBar.setIndeterminate(indeterminate); 502 } 503 504 /** 505 * Sets the progress bar's progress. 506 */ setProgressBarProgress(int progress)507 public void setProgressBarProgress(int progress) { 508 setProgressBarIndeterminate(false); 509 mProgressBar.setProgress(progress); 510 } 511 512 /** 513 * Sets the locale to be used for rendering. 514 */ applyLocale(Locale locale)515 public void applyLocale(Locale locale) { 516 if (locale == null) { 517 return; 518 } 519 int direction = TextUtils.getLayoutDirectionFromLocale(locale); 520 setLayoutDirection(direction); 521 522 mToolbarTitle.setTextLocale(locale); 523 mToolbarTitle.setLayoutDirection(direction); 524 525 mPrimaryToolbarButton.setTextLocale(locale); 526 mPrimaryToolbarButton.setLayoutDirection(direction); 527 528 mSecondaryToolbarButton.setTextLocale(locale); 529 mSecondaryToolbarButton.setLayoutDirection(direction); 530 } 531 532 /** 533 * Sets the title bar view. 534 */ setTitleBar(View titleBar)535 private void setTitleBar(View titleBar) { 536 mTitleBar = titleBar; 537 } 538 539 /** 540 * A method that inflates the SecondaryToolbarButton if it is has not already been 541 * inflated. If it has been inflated already this method will do nothing. 542 */ maybeInflateSecondaryToolbarButton()543 private void maybeInflateSecondaryToolbarButton() { 544 ViewStub secondaryToolbarButtonStub = findViewById(R.id.secondary_toolbar_button_stub); 545 // If the secondaryToolbarButtonStub is null then the stub has been inflated so there is 546 // nothing to do. 547 if (secondaryToolbarButtonStub != null) { 548 secondaryToolbarButtonStub.inflate(); 549 mSecondaryToolbarButton = findViewById(R.id.secondary_toolbar_button); 550 setSecondaryToolbarButtonVisible(false); 551 552 setBackground( 553 mSecondaryToolbarButton, 554 PartnerConfig.CONFIG_TOOLBAR_SECONDARY_BUTTON_BG, 555 PartnerConfig.CONFIG_TOOLBAR_SECONDARY_BUTTON_BG_COLOR); 556 557 setButtonPadding(mSecondaryToolbarButton); 558 setButtonTypeFace(mSecondaryToolbarButton); 559 setButtonTextSize(mSecondaryToolbarButton); 560 setButtonTextColor( 561 mSecondaryToolbarButton, 562 PartnerConfig.CONFIG_TOOLBAR_SECONDARY_BUTTON_TEXT_COLOR); 563 564 // Set button spacing 565 float marginEnd = PartnerConfigHelper.get(getContext()).getDimension( 566 getContext(), 567 PartnerConfig.CONFIG_TOOLBAR_BUTTON_SPACING); 568 569 MarginLayoutParams layoutParams = 570 (MarginLayoutParams) mSecondaryToolbarButton.getLayoutParams(); 571 layoutParams.setMarginEnd(Math.round(marginEnd)); 572 } 573 } 574 575 /** Sets button text color using partner overlay if exists */ 576 @VisibleForTesting setButtonTextColor(TextView button, PartnerConfig config)577 void setButtonTextColor(TextView button, PartnerConfig config) { 578 int color = mPartnerConfigHelper.getColor(getContext(), config); 579 if (color != 0) { 580 button.setTextColor(color); 581 } 582 } 583 584 /** 585 * Sets background using partner overlay if exists. Background color and radius are only 586 * applied if background resource doesn't exist. Otherwise default background color and radius 587 * may override what's set in the background. 588 */ 589 @VisibleForTesting setBackground(View view, PartnerConfig bgConfig, PartnerConfig bgColorConfig)590 void setBackground(View view, PartnerConfig bgConfig, PartnerConfig bgColorConfig) { 591 Drawable background = mPartnerConfigHelper.getDrawable(getContext(), bgConfig); 592 if (background == null) { 593 if (view instanceof Button) { 594 setButtonRadius((Button) view); 595 } 596 setBackgroundColor(view, bgColorConfig); 597 } else { 598 view.setBackground(background); 599 } 600 } 601 602 /** Sets button background color using partner overlay if exists */ 603 @VisibleForTesting setBackgroundColor(View button, PartnerConfig config)604 void setBackgroundColor(View button, PartnerConfig config) { 605 int color = mPartnerConfigHelper.getColor(getContext(), config); 606 if (color != 0) { 607 Drawable background = button.getBackground(); 608 if (background != null) { 609 background.mutate().setColorFilter(color, PorterDuff.Mode.SRC_ATOP); 610 } 611 } 612 } 613 614 /** Sets button text size using partner overlay if exists */ 615 @VisibleForTesting setButtonTextSize(TextView button)616 void setButtonTextSize(TextView button) { 617 float dimension = mPartnerConfigHelper.getDimension( 618 getContext(), 619 PartnerConfig.CONFIG_TOOLBAR_BUTTON_TEXT_SIZE); 620 if (dimension != 0) { 621 button.setTextSize(TypedValue.COMPLEX_UNIT_PX, dimension); 622 } 623 } 624 625 /** Sets button type face with partner overlay if exists */ setButtonTypeFace(TextView button)626 private void setButtonTypeFace(TextView button) { 627 String fontFamily = mPartnerConfigHelper.getString( 628 getContext(), 629 PartnerConfig.CONFIG_TOOLBAR_BUTTON_FONT_FAMILY); 630 if (TextUtils.isEmpty(fontFamily)) { 631 return; 632 } 633 634 Typeface typeface = Typeface.create(fontFamily, Typeface.NORMAL); 635 if (Objects.equals(typeface, Typeface.DEFAULT)) { 636 Log.w(TAG, String.format( 637 "Couldn't find font: %s. Setting default font.", 638 fontFamily)); 639 } 640 button.setTypeface(typeface); 641 } 642 643 /** Sets button radius using partner overlay if exists */ setButtonRadius(Button button)644 private void setButtonRadius(Button button) { 645 float radius = mPartnerConfigHelper.getDimension( 646 getContext(), 647 PartnerConfig.CONFIG_TOOLBAR_BUTTON_RADIUS); 648 649 GradientDrawable gradientDrawable = getGradientDrawable(button); 650 if (gradientDrawable != null) { 651 gradientDrawable.setCornerRadius(radius); 652 } 653 } 654 setButtonPadding(Button button)655 private void setButtonPadding(Button button) { 656 int hPadding = Math.round( 657 PartnerConfigHelper.get(getContext()).getDimension( 658 getContext(), 659 PartnerConfig.CONFIG_TOOLBAR_BUTTON_PADDING_HORIZONTAL) 660 ); 661 int vPadding = Math.round( 662 PartnerConfigHelper.get(getContext()).getDimension( 663 getContext(), 664 PartnerConfig.CONFIG_TOOLBAR_BUTTON_PADDING_VERTICAL) 665 ); 666 button.setPadding(hPadding, vPadding, hPadding, vPadding); 667 } 668 getGradientDrawable(Button button)669 private GradientDrawable getGradientDrawable(Button button) { 670 Drawable drawable = button.getBackground(); 671 if (drawable instanceof InsetDrawable) { 672 return getGradientDrawableFromInsetDrawable((InsetDrawable) drawable); 673 } 674 675 if (drawable instanceof RippleDrawable) { 676 drawable = ((RippleDrawable) drawable).getDrawable(0); 677 if (drawable instanceof InsetDrawable) { 678 return getGradientDrawableFromInsetDrawable((InsetDrawable) drawable); 679 } 680 return (GradientDrawable) drawable; 681 } 682 683 return null; 684 } 685 getGradientDrawableFromInsetDrawable(InsetDrawable insetDrawable)686 private GradientDrawable getGradientDrawableFromInsetDrawable(InsetDrawable insetDrawable) { 687 return (GradientDrawable) insetDrawable.getDrawable(); 688 } 689 } 690