Repository: paypal/paypal-android
Pull request #316: [V3] Remove Button Size Classes
Author: login: sshropshire
Created: 2025-04-28T19:45:01Z | Merged: 2025-05-05T15:19:22Z

### Summary of changes

 - This PR removes `PaymentButtonSize` from the `:PaymentButtons` module

 ### Checklist

 - [x] Added a changelog entry

### Authors
> List GitHub usernames for everyone who contributed to this pull request.

- @sshropshire



Diff:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 11bf94d79..dd865636b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
 # PayPal Android SDK Release Notes
 
+## unreleased
+
+* Breaking Changes
+  * PayPalButtons
+    * Remove `PaymentButtonSize` enum
+    * Remove `size` property from `PaymentButton` base class
+
 ## 2.0.0 (2025-03-18)
 * Breaking Changes
   * PayPalNativePayments
diff --git a/Demo/src/main/java/com/paypal/android/ui/paypalbuttons/PayPalButtonsUiState.kt b/Demo/src/main/java/com/paypal/android/ui/paypalbuttons/PayPalButtonsUiState.kt
index e1e479128..7f4b8ca83 100644
--- a/Demo/src/main/java/com/paypal/android/ui/paypalbuttons/PayPalButtonsUiState.kt
+++ b/Demo/src/main/java/com/paypal/android/ui/paypalbuttons/PayPalButtonsUiState.kt
@@ -4,7 +4,6 @@ import com.paypal.android.paymentbuttons.PayPalButtonColor
 import com.paypal.android.paymentbuttons.PayPalButtonLabel
 import com.paypal.android.paymentbuttons.PayPalCreditButtonColor
 import com.paypal.android.paymentbuttons.PaymentButtonShape
-import com.paypal.android.paymentbuttons.PaymentButtonSize
 
 data class PayPalButtonsUiState(
     val fundingType: ButtonFundingType = ButtonFundingType.PAYPAL,
@@ -12,6 +11,5 @@ data class PayPalButtonsUiState(
     val payPalButtonColor: PayPalButtonColor = PayPalButtonColor.GOLD,
     val payPalButtonLabel: PayPalButtonLabel = PayPalButtonLabel.PAYPAL,
     val paymentButtonShape: PaymentButtonShape = PaymentButtonShape.ROUNDED,
-    val paymentButtonSize: PaymentButtonSize = PaymentButtonSize.SMALL,
     val customCornerRadius: Int? = null
 )
diff --git a/Demo/src/main/java/com/paypal/android/ui/paypalbuttons/PayPalButtonsView.kt b/Demo/src/main/java/com/paypal/android/ui/paypalbuttons/PayPalButtonsView.kt
index 3d9308de9..a1ab37db9 100644
--- a/Demo/src/main/java/com/paypal/android/ui/paypalbuttons/PayPalButtonsView.kt
+++ b/Demo/src/main/java/com/paypal/android/ui/paypalbuttons/PayPalButtonsView.kt
@@ -98,10 +98,6 @@ fun PayPalButtonsView(viewModel: PayPalButtonsViewModel = viewModel()) {
                 cornerRadius = uiState.customCornerRadius,
                 onCornerRadiusChange = { value -> viewModel.customCornerRadius = value }
             )
-            PaymentButtonSizeOptionList(
-                selectedOption = uiState.paymentButtonSize,
-                onSelection = { value -> viewModel.paymentButtonSize = value }
-            )
             Spacer(modifier = Modifier.size(contentPadding))
         }
     }
@@ -208,7 +204,6 @@ private fun configureButton(
     uiState: PayPalButtonsUiState
 ) {
     button.shape = uiState.paymentButtonShape
-    button.size = uiState.paymentButtonSize
 
     if (button is PayPalButton) {
         button.label = uiState.payPalButtonLabel
diff --git a/Demo/src/main/java/com/paypal/android/ui/paypalbuttons/PayPalButtonsViewModel.kt b/Demo/src/main/java/com/paypal/android/ui/paypalbuttons/PayPalButtonsViewModel.kt
index 39d22d2f8..80b251a8c 100644
--- a/Demo/src/main/java/com/paypal/android/ui/paypalbuttons/PayPalButtonsViewModel.kt
+++ b/Demo/src/main/java/com/paypal/android/ui/paypalbuttons/PayPalButtonsViewModel.kt
@@ -5,7 +5,6 @@ import com.paypal.android.paymentbuttons.PayPalButtonColor
 import com.paypal.android.paymentbuttons.PayPalButtonLabel
 import com.paypal.android.paymentbuttons.PayPalCreditButtonColor
 import com.paypal.android.paymentbuttons.PaymentButtonShape
-import com.paypal.android.paymentbuttons.PaymentButtonSize
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.update
@@ -53,10 +52,4 @@ class PayPalButtonsViewModel : ViewModel() {
                 )
             }
         }
-
-    var paymentButtonSize: PaymentButtonSize
-        get() = _uiState.value.paymentButtonSize
-        set(value) {
-            _uiState.update { it.copy(paymentButtonSize = value) }
-        }
 }
diff --git a/Demo/src/main/java/com/paypal/android/ui/paypalbuttons/PaymentButtonSizeOptionList.kt b/Demo/src/main/java/com/paypal/android/ui/paypalbuttons/PaymentButtonSizeOptionList.kt
deleted file mode 100644
index 4e609f3f5..000000000
--- a/Demo/src/main/java/com/paypal/android/ui/paypalbuttons/PaymentButtonSizeOptionList.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.paypal.android.ui.paypalbuttons
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.res.stringResource
-import com.paypal.android.R
-import com.paypal.android.paymentbuttons.PaymentButtonSize
-import com.paypal.android.uishared.components.OptionList
-
-@Composable
-fun PaymentButtonSizeOptionList(
-    selectedOption: PaymentButtonSize,
-    onSelection: (PaymentButtonSize) -> Unit
-) {
-    OptionList(
-        title = stringResource(id = R.string.pay_pal_button_size),
-        options = PaymentButtonSize.values().map { it.name },
-        selectedOption = selectedOption.name,
-        onSelectedOptionChange = { option ->
-            onSelection(PaymentButtonSize.valueOf(option))
-        }
-    )
-}
diff --git a/Demo/src/main/res/values/strings.xml b/Demo/src/main/res/values/strings.xml
index 884afaa07..b946024b2 100644
--- a/Demo/src/main/res/values/strings.xml
+++ b/Demo/src/main/res/values/strings.xml
@@ -26,7 +26,6 @@
     <string name="pay_pal_button_color">Button Color</string>
     <string name="pay_pal_button_label">Button Label</string>
     <string name="pay_pal_button_shape">Button Shape</string>
-    <string name="pay_pal_button_size">Button Size</string>
 
     <string name="intent_title">INTENT</string>
     <string-array name="intent_options">
diff --git a/PaymentButtons/src/main/java/com/paypal/android/paymentbuttons/PayPalCreditButton.kt b/PaymentButtons/src/main/java/com/paypal/android/paymentbuttons/PayPalCreditButton.kt
index d186ecfb3..57e7c26dc 100644
--- a/PaymentButtons/src/main/java/com/paypal/android/paymentbuttons/PayPalCreditButton.kt
+++ b/PaymentButtons/src/main/java/com/paypal/android/paymentbuttons/PayPalCreditButton.kt
@@ -118,7 +118,7 @@ enum class PayPalCreditButtonColor(
                 BLACK.value -> BLACK
                 GOLD.value -> GOLD
                 WHITE.value -> WHITE
-                else -> throw createFormattedIllegalArgumentException("PaymentButtonSize", values().size)
+                else -> throw createFormattedIllegalArgumentException("PayPalCreditButtonColor", values().size)
             }
         }
     }
diff --git a/PaymentButtons/src/main/java/com/paypal/android/paymentbuttons/PaymentButton.kt b/PaymentButtons/src/main/java/com/paypal/android/paymentbuttons/PaymentButton.kt
index 69a0542c8..7f0de37fc 100644
--- a/PaymentButtons/src/main/java/com/paypal/android/paymentbuttons/PaymentButton.kt
+++ b/PaymentButtons/src/main/java/com/paypal/android/paymentbuttons/PaymentButton.kt
@@ -96,16 +96,14 @@ abstract class PaymentButton<C : PaymentButtonColor> @JvmOverloads constructor(
             }
 
             shapeAppearanceModel = ShapeAppearanceModel.builder().apply {
-                value?.let {
-                    setAllCornerSizes(it)
-                }
+                setAllCornerSizes(value)
                 setAllCorners(cornerTreatment)
             }.build()
         }
 
     /**
      * Updates the shape of the Payment Button with the provided [PaymentButtonShape]
-     * and defaults to [ROUNDED] if one is not provided.
+     * and defaults to [PaymentButtonShape.ROUNDED] if one is not provided.
      *
      * If your application is taking advantage of Material Theming then your own shape definitions
      * will be used as the default.
@@ -123,9 +121,11 @@ abstract class PaymentButton<C : PaymentButtonColor> @JvmOverloads constructor(
                 PaymentButtonShape.ROUNDED -> {
                     resources.getDimension(R.dimen.paypal_payment_button_corner_radius_rounded)
                 }
+
                 PaymentButtonShape.PILL -> {
                     resources.getDimension(R.dimen.paypal_payment_button_corner_pill)
                 }
+
                 PaymentButtonShape.RECTANGLE -> {
                     resources.getDimension(R.dimen.paypal_payment_button_corner_radius_square)
                 }
@@ -165,27 +165,6 @@ abstract class PaymentButton<C : PaymentButtonColor> @JvmOverloads constructor(
     private var prefixTextView: TextView
     private var suffixTextView: TextView
 
-    /**
-     * Updates the size of the Payment Button with the provided [PaymentButtonSize].
-     *
-     * The main UI elements which change when modifying the size include:
-     *  - Minimum height of the button.
-     *  - Height and width of the wordmark.
-     *
-     * The default size of a button is [MEDIUM].
-     */
-    var size: PaymentButtonSize = PaymentButtonSize.MEDIUM
-        set(value) {
-            field = value
-            minimumHeight = resources.getDimension(field.minHeightResId).toInt()
-            val verticalPadding = resources.getDimension(field.verticalPaddingResId).toInt()
-            setPadding(paddingLeft, verticalPadding, paddingRight, verticalPadding)
-
-            val labelTextSize = resources.getDimension(field.labelTextSizeResId)
-            prefixTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, labelTextSize)
-            suffixTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, labelTextSize)
-        }
-
     init {
         LayoutInflater.from(context)
             .inflate(R.layout.paypal_ui_payment_button_view, this, true)
@@ -198,6 +177,7 @@ abstract class PaymentButton<C : PaymentButtonColor> @JvmOverloads constructor(
         gravity = Gravity.CENTER
 
         initAttributes(attributeSet, defStyleAttr)
+        applyDefaultAttributes()
     }
 
     override fun onAttachedToWindow() {
@@ -223,11 +203,21 @@ abstract class PaymentButton<C : PaymentButtonColor> @JvmOverloads constructor(
 
     private fun initAttributes(attributeSet: AttributeSet?, defStyleAttr: Int) {
         context.obtainStyledAttributes(attributeSet, R.styleable.PaymentButton).use { typedArray ->
-            updateSizeFrom(typedArray)
             updateShapeFrom(typedArray, attributeSet, defStyleAttr)
         }
     }
 
+    private fun applyDefaultAttributes() {
+        minimumHeight = resources.getDimension(R.dimen.paypal_payment_button_min_height).toInt()
+        val verticalPadding =
+            resources.getDimension(R.dimen.paypal_payment_button_vertical_padding).toInt()
+        setPadding(paddingLeft, verticalPadding, paddingRight, verticalPadding)
+
+        val labelTextSize = resources.getDimension(R.dimen.paypal_payment_button_label_text_size)
+        prefixTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, labelTextSize)
+        suffixTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, labelTextSize)
+    }
+
     override fun setOnClickListener(listener: OnClickListener?) {
         super.setOnClickListener { view ->
             listener?.onClick(view)
@@ -239,16 +229,13 @@ abstract class PaymentButton<C : PaymentButtonColor> @JvmOverloads constructor(
         }
     }
 
-    private fun updateSizeFrom(typedArray: TypedArray) {
-        val paypalSizeAttribute = typedArray.getInt(
-            R.styleable.PaymentButton_payment_button_size,
-            PaymentButtonSize.MEDIUM.value
-        )
-        size = PaymentButtonSize(paypalSizeAttribute)
-    }
-
-    private fun updateShapeFrom(typedArray: TypedArray, attributeSet: AttributeSet?, defStyleAttr: Int) {
-        val shapeAttributeExists = typedArray.hasValue(R.styleable.PaymentButton_payment_button_shape)
+    private fun updateShapeFrom(
+        typedArray: TypedArray,
+        attributeSet: AttributeSet?,
+        defStyleAttr: Int
+    ) {
+        val shapeAttributeExists =
+            typedArray.hasValue(R.styleable.PaymentButton_payment_button_shape)
         if (shapeAttributeExists) {
             val paypalShapeAttribute = typedArray.getInt(
                 R.styleable.PaymentButton_payment_button_shape,
@@ -293,6 +280,7 @@ abstract class PaymentButton<C : PaymentButtonColor> @JvmOverloads constructor(
             PaymentButtonColorLuminance.LIGHT -> {
                 ContextCompat.getDrawable(context, wordmarkLightLuminanceResId)
             }
+
             PaymentButtonColorLuminance.DARK -> {
                 ContextCompat.getDrawable(context, wordmarkDarkLuminanceResId)
             }
@@ -305,6 +293,7 @@ abstract class PaymentButton<C : PaymentButtonColor> @JvmOverloads constructor(
             PaymentButtonColorLuminance.LIGHT -> {
                 ContextCompat.getColor(context, R.color.paypal_spb_on_light_surface)
             }
+
             PaymentButtonColorLuminance.DARK -> {
                 ContextCompat.getColor(context, R.color.paypal_spb_on_dark_surface)
             }
diff --git a/PaymentButtons/src/main/java/com/paypal/android/paymentbuttons/PaymentButtonSize.kt b/PaymentButtons/src/main/java/com/paypal/android/paymentbuttons/PaymentButtonSize.kt
deleted file mode 100644
index 825eaf4c1..000000000
--- a/PaymentButtons/src/main/java/com/paypal/android/paymentbuttons/PaymentButtonSize.kt
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.paypal.android.paymentbuttons
-
-import com.paypal.android.paymentbuttons.error.createFormattedIllegalArgumentException
-import com.paypal.android.ui.R
-
-/**
- * Defines the sizes available for payment buttons. If no size is provided then it will
- * default to medium. Button size is used for setting properties like minimum width and height to
- * allow for the use of wrap_content where necessary along with modifying the size of the wordmark
- * and adjusting padding within the button.
- *
- * @see SMALL used when a smaller button is desired, the minimum height will be 48dp with the wordmark
- * having a height of 15dp and width of 61dp.
- * @see MEDIUM this is the default button size, the minimum height will be 48dp with the wordmark having
- * a height of 20dp and width of 79dp.
- * @see LARGE this is the largest button size, the minimum height will be 26dp with the wordmark having
- * a height of 26dp and width of 103dp.
- */
-enum class PaymentButtonSize(
-    val value: Int,
-    val minHeightResId: Int,
-    val verticalPaddingResId: Int,
-    val labelTextSizeResId: Int
-) {
-    SMALL(
-        value = 0,
-        minHeightResId = R.dimen.paypal_payment_button_min_height,
-        verticalPaddingResId = R.dimen.paypal_payment_button_vertical_padding,
-        labelTextSizeResId = R.dimen.paypal_payment_button_label_text_size
-    ),
-    MEDIUM(
-        value = 1,
-        minHeightResId = R.dimen.paypal_payment_button_min_height,
-        verticalPaddingResId = R.dimen.paypal_payment_button_vertical_padding,
-        labelTextSizeResId = R.dimen.paypal_payment_button_label_text_size
-    ),
-    LARGE(
-        value = 2,
-        minHeightResId = R.dimen.paypal_payment_button_min_height_large,
-        verticalPaddingResId = R.dimen.paypal_payment_button_vertical_padding_large,
-        labelTextSizeResId = R.dimen.paypal_payment_button_label_text_size_large
-    );
-
-    companion object {
-        /**
-         * Given an [attributeIndex] this will provide the correct [PaymentButtonSize].
-         * If an invalid [attributeIndex] is provided then it will throw an [IllegalArgumentException].
-         *
-         * @throws [IllegalArgumentException] when an invalid index is provided.
-         */
-        operator fun invoke(attributeIndex: Int): PaymentButtonSize {
-            return when (attributeIndex) {
-                SMALL.value -> SMALL
-                MEDIUM.value -> MEDIUM
-                LARGE.value -> LARGE
-                else -> throw createFormattedIllegalArgumentException("PaymentButtonSize", values().size)
-            }
-        }
-    }
-}
diff --git a/PaymentButtons/src/main/res/layout/paypal_ui_payment_button_view.xml b/PaymentButtons/src/main/res/layout/paypal_ui_payment_button_view.xml
index c94e14f47..1bf97d157 100644
--- a/PaymentButtons/src/main/res/layout/paypal_ui_payment_button_view.xml
+++ b/PaymentButtons/src/main/res/layout/paypal_ui_payment_button_view.xml
@@ -5,9 +5,10 @@
     tools:gravity="center"
     tools:layout_height="wrap_content"
     tools:layout_width="match_parent"
-    tools:minHeight="48dp"
+    tools:minHeight="@dimen/paypal_payment_button_min_height"
     tools:orientation="horizontal"
-    tools:parentTag="LinearLayout">
+    tools:paddingVertical="@dimen/paypal_payment_button_vertical_padding"
+    tools:parentTag="android.widget.LinearLayout">
 
     <TextView
         android:id="@+id/prefixText"
@@ -15,6 +16,7 @@
         android:layout_height="wrap_content"
         android:layout_marginEnd="@dimen/paypal_payment_button_text_margin"
         android:fontFamily="@font/paypalopen_regular"
+        android:textSize="@dimen/paypal_payment_button_label_text_size"
         android:visibility="gone"
         tools:text="Buy turnips with"
         tools:textColor="@color/paypal_spb_on_light_surface"
@@ -27,7 +29,7 @@
         android:contentDescription="@null"
         android:visibility="gone"
         tools:srcCompat="@drawable/wordmark_paypal_credit_monochrome"
-        tools:visibility="gone"/>
+        tools:visibility="gone" />
 
     <TextView
         android:id="@+id/suffixText"
@@ -35,6 +37,7 @@
         android:layout_height="wrap_content"
         android:layout_marginStart="@dimen/paypal_payment_button_text_margin"
         android:fontFamily="@font/paypalopen_regular"
+        android:textSize="@dimen/paypal_payment_button_label_text_size"
         android:visibility="gone"
         tools:text="Checkout"
         tools:textColor="@color/paypal_spb_on_light_surface"


Reviews:
user: login: sshropshire
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-28T21:46:49Z
user: login: KunJeongPark
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T14:37:22Z
user: login: KunJeongPark
body: Loos good!
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T14:43:21Z
user: login: kgangineni
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-01T19:47:08Z
user: login: sshropshire
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-01T20:46:17Z
user: login: KunJeongPark
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T21:30:56Z

Review comments:
diff_hunk: @@ -118,7 +118,7 @@ enum class PayPalCreditButtonColor(
                 BLACK.value -> BLACK
                 GOLD.value -> GOLD
                 WHITE.value -> WHITE
-                else -> throw createFormattedIllegalArgumentException("PaymentButtonSize", values().size)
+                else -> throw createFormattedIllegalArgumentException("PayPalCreditButtonColor", values().size)
path: PaymentButtons/src/main/java/com/paypal/android/paymentbuttons/PayPalCreditButton.kt
user: login: sshropshire
body: This appears to be a typo. Cleaning up in this PR even though its technically unrelated.
created_at: 2025-04-28T21:46:49Z
author_association: COLLABORATOR
diff_hunk: @@ -223,11 +203,21 @@ abstract class PaymentButton<C : PaymentButtonColor> @JvmOverloads constructor(
 
     private fun initAttributes(attributeSet: AttributeSet?, defStyleAttr: Int) {
         context.obtainStyledAttributes(attributeSet, R.styleable.PaymentButton).use { typedArray ->
-            updateSizeFrom(typedArray)
             updateShapeFrom(typedArray, attributeSet, defStyleAttr)
         }
     }
 
+    private fun applyDefaultAttributes() {
path: PaymentButtons/src/main/java/com/paypal/android/paymentbuttons/PaymentButton.kt
user: login: KunJeongPark
body: I like this approach
created_at: 2025-05-01T14:37:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,5 +1,12 @@
 # PayPal Android SDK Release Notes
 
+## unreleased
path: CHANGELOG.md
user: login: kgangineni
body: Q: Will all these entries get added to release notes when releasing new version of SDK or we need to manually add
created_at: 2025-05-01T19:35:45Z
author_association: COLLABORATOR
diff_hunk: @@ -1,5 +1,12 @@
 # PayPal Android SDK Release Notes
 
+## unreleased
path: CHANGELOG.md
user: login: sshropshire
body: Yes definitely. For now, they'll accumulate on the `v3` branch. Eventually, they'll get added to the `main` branch release notes once we make it generally available.
created_at: 2025-05-01T20:46:17Z
author_association: COLLABORATOR

PR comments:
user: login: KunJeongPark
created_at: 2025-05-01T14:12:33Z
body: Hey Steven, are we putting this on a feature branch?
I am thinking we were planning on releasing the BCDC feature first in 2.1 version and release this in 3.0
author_association: CONTRIBUTOR
user: login: sshropshire
created_at: 2025-05-01T14:33:26Z
body: > Hey Steven, are we putting this on a feature branch?

This is a good callout yeah. I meant to set the base branch to `v3`. I updated it now.
author_association: COLLABORATOR
user: login: KunJeongPark
created_at: 2025-05-01T14:33:45Z
body: I just did the same. I did the same thing as you.
author_association: CONTRIBUTOR
user: login: KunJeongPark
created_at: 2025-05-01T21:31:10Z
body: oh sorry, I thought I approved this earlier!
author_association: CONTRIBUTOR