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