diff --git a/stripe/res/drawable/stripe_google_pay_mark.xml b/stripe/res/drawable/stripe_google_pay_mark.xml
new file mode 100644
index 00000000000..eeb63d1efe8
--- /dev/null
+++ b/stripe/res/drawable/stripe_google_pay_mark.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/stripe/res/layout/google_pay_row.xml b/stripe/res/layout/google_pay_row.xml
new file mode 100644
index 00000000000..a963e43d1b5
--- /dev/null
+++ b/stripe/res/layout/google_pay_row.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/stripe/src/main/java/com/stripe/android/view/PaymentMethodSwipeCallback.kt b/stripe/src/main/java/com/stripe/android/view/PaymentMethodSwipeCallback.kt
index 751a16ba50b..e9dd9844f2f 100644
--- a/stripe/src/main/java/com/stripe/android/view/PaymentMethodSwipeCallback.kt
+++ b/stripe/src/main/java/com/stripe/android/view/PaymentMethodSwipeCallback.kt
@@ -50,7 +50,7 @@ internal class PaymentMethodSwipeCallback(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int {
- return if (viewHolder is PaymentMethodsAdapter.PaymentMethodViewHolder) {
+ return if (viewHolder is PaymentMethodsAdapter.ViewHolder.PaymentMethodViewHolder) {
// only allow swiping on Payment Method items
super.getSwipeDirs(recyclerView, viewHolder)
} else {
@@ -68,7 +68,7 @@ internal class PaymentMethodSwipeCallback(
isCurrentlyActive: Boolean
) {
super.onChildDraw(canvas, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
- if (viewHolder is PaymentMethodsAdapter.PaymentMethodViewHolder) {
+ if (viewHolder is PaymentMethodsAdapter.ViewHolder.PaymentMethodViewHolder) {
val itemView = viewHolder.itemView
val startTransition = itemView.width * START_TRANSITION_THRESHOLD
diff --git a/stripe/src/main/java/com/stripe/android/view/PaymentMethodsActivity.kt b/stripe/src/main/java/com/stripe/android/view/PaymentMethodsActivity.kt
index 09b56d8ffed..6a6e2f72f6e 100644
--- a/stripe/src/main/java/com/stripe/android/view/PaymentMethodsActivity.kt
+++ b/stripe/src/main/java/com/stripe/android/view/PaymentMethodsActivity.kt
@@ -70,9 +70,9 @@ class PaymentMethodsActivity : AppCompatActivity() {
args: PaymentMethodsActivityStarter.Args
) {
adapter = PaymentMethodsAdapter(
- viewModel.selectedPaymentMethodId,
args,
- args.paymentMethodTypes
+ args.paymentMethodTypes,
+ viewModel.selectedPaymentMethodId
)
adapter.listener = object : PaymentMethodsAdapter.Listener {
diff --git a/stripe/src/main/java/com/stripe/android/view/PaymentMethodsAdapter.kt b/stripe/src/main/java/com/stripe/android/view/PaymentMethodsAdapter.kt
index 03b4ab034e3..5727b942731 100644
--- a/stripe/src/main/java/com/stripe/android/view/PaymentMethodsAdapter.kt
+++ b/stripe/src/main/java/com/stripe/android/view/PaymentMethodsAdapter.kt
@@ -15,10 +15,10 @@ import java.util.ArrayList
* A [RecyclerView.Adapter] that holds a set of [MaskedCardView] items for a given set
* of [PaymentMethod] objects.
*/
-internal class PaymentMethodsAdapter @JvmOverloads internal constructor(
- initiallySelectedPaymentMethodId: String?,
+internal class PaymentMethodsAdapter constructor(
private val intentArgs: PaymentMethodsActivityStarter.Args,
- private val addableTypes: List = listOf(PaymentMethod.Type.Card)
+ private val addableTypes: List = listOf(PaymentMethod.Type.Card),
+ initiallySelectedPaymentMethodId: String? = null
) : RecyclerView.Adapter() {
internal val paymentMethods = ArrayList()
@@ -52,15 +52,16 @@ internal class PaymentMethodsAdapter @JvmOverloads internal constructor(
return if (position < paymentMethods.size) {
val type = paymentMethods[position].type
if (PaymentMethod.Type.Card.code == type) {
- TYPE_CARD
+ ViewType.Card.ordinal
} else {
super.getItemViewType(position)
}
} else {
- val paymentMethodType = addableTypes[getAddableTypesPosition(position)]
+ val paymentMethodType =
+ addableTypes[getAddableTypesPosition(position)]
return when (paymentMethodType) {
- PaymentMethod.Type.Card -> TYPE_ADD_CARD
- PaymentMethod.Type.Fpx -> TYPE_ADD_FPX
+ PaymentMethod.Type.Card -> ViewType.AddCard.ordinal
+ PaymentMethod.Type.Fpx -> ViewType.AddFpx.ordinal
else ->
throw IllegalArgumentException(
"Unsupported PaymentMethod type: ${paymentMethodType.code}")
@@ -77,7 +78,7 @@ internal class PaymentMethodsAdapter @JvmOverloads internal constructor(
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
- if (holder is PaymentMethodViewHolder) {
+ if (holder is ViewHolder.PaymentMethodViewHolder) {
val paymentMethod = paymentMethods[position]
holder.setPaymentMethod(paymentMethod)
holder.setSelected(paymentMethod.id == selectedPaymentMethodId)
@@ -109,31 +110,48 @@ internal class PaymentMethodsAdapter @JvmOverloads internal constructor(
notifyItemChanged(position)
}
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
- return when (viewType) {
- TYPE_CARD -> createPaymentMethodViewHolder(parent)
- TYPE_ADD_CARD -> createAddCardPaymentMethodViewHolder(parent)
- TYPE_ADD_FPX -> createAddFpxPaymentMethodViewHolder(parent)
- else -> throw IllegalArgumentException("Unsupported viewType: $viewType")
+ override fun onCreateViewHolder(
+ parent: ViewGroup,
+ viewType: Int
+ ): RecyclerView.ViewHolder {
+ return when (ViewType.values()[viewType]) {
+ ViewType.Card -> createPaymentMethodViewHolder(parent)
+ ViewType.AddCard -> createAddCardPaymentMethodViewHolder(parent)
+ ViewType.AddFpx -> createAddFpxPaymentMethodViewHolder(parent)
+ ViewType.GooglePay -> createGooglePayViewHolder(parent)
}
}
- private fun createAddCardPaymentMethodViewHolder(parent: ViewGroup): AddCardPaymentMethodViewHolder {
- return AddCardPaymentMethodViewHolder(
+ private fun createAddCardPaymentMethodViewHolder(
+ parent: ViewGroup
+ ): ViewHolder.AddCardPaymentMethodViewHolder {
+ return ViewHolder.AddCardPaymentMethodViewHolder(
AddPaymentMethodCardRowView(parent.context as Activity, intentArgs)
)
}
- private fun createAddFpxPaymentMethodViewHolder(parent: ViewGroup): AddFpxPaymentMethodViewHolder {
- return AddFpxPaymentMethodViewHolder(
+ private fun createAddFpxPaymentMethodViewHolder(
+ parent: ViewGroup
+ ): ViewHolder.AddFpxPaymentMethodViewHolder {
+ return ViewHolder.AddFpxPaymentMethodViewHolder(
AddPaymentMethodFpxRowView(parent.context as Activity, intentArgs)
)
}
- private fun createPaymentMethodViewHolder(parent: ViewGroup): PaymentMethodViewHolder {
+ private fun createPaymentMethodViewHolder(
+ parent: ViewGroup
+ ): ViewHolder.PaymentMethodViewHolder {
val itemView = LayoutInflater.from(parent.context)
.inflate(R.layout.masked_card_row, parent, false)
- return PaymentMethodViewHolder(itemView)
+ return ViewHolder.PaymentMethodViewHolder(itemView)
+ }
+
+ private fun createGooglePayViewHolder(
+ parent: ViewGroup
+ ): ViewHolder.GooglePayViewHolder {
+ val itemView = LayoutInflater.from(parent.context)
+ .inflate(R.layout.google_pay_row, parent, false)
+ return ViewHolder.GooglePayViewHolder(itemView)
}
internal fun deletePaymentMethod(paymentMethod: PaymentMethod) {
@@ -151,35 +169,46 @@ internal class PaymentMethodsAdapter @JvmOverloads internal constructor(
}
}
- private fun getAddableTypesPosition(position: Int) = position - paymentMethods.size
+ private fun getAddableTypesPosition(position: Int): Int {
+ return position - paymentMethods.size
+ }
- internal class PaymentMethodViewHolder constructor(
- itemView: View
- ) : RecyclerView.ViewHolder(itemView) {
- private val cardView: MaskedCardView = itemView.findViewById(R.id.masked_card_item)
+ internal sealed class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ internal class AddCardPaymentMethodViewHolder(
+ itemView: View
+ ) : RecyclerView.ViewHolder(itemView)
- fun setPaymentMethod(paymentMethod: PaymentMethod) {
- cardView.setPaymentMethod(paymentMethod)
- }
+ internal class AddFpxPaymentMethodViewHolder(
+ itemView: View
+ ) : RecyclerView.ViewHolder(itemView)
- fun setSelected(selected: Boolean) {
- cardView.isSelected = selected
- }
- }
+ internal class GooglePayViewHolder(
+ itemView: View
+ ) : RecyclerView.ViewHolder(itemView)
+
+ internal class PaymentMethodViewHolder constructor(
+ itemView: View
+ ) : ViewHolder(itemView) {
+ private val cardView: MaskedCardView = itemView.findViewById(R.id.masked_card_item)
- internal class AddCardPaymentMethodViewHolder(itemView: View) :
- RecyclerView.ViewHolder(itemView)
+ fun setPaymentMethod(paymentMethod: PaymentMethod) {
+ cardView.setPaymentMethod(paymentMethod)
+ }
- internal class AddFpxPaymentMethodViewHolder(itemView: View) :
- RecyclerView.ViewHolder(itemView)
+ fun setSelected(selected: Boolean) {
+ cardView.isSelected = selected
+ }
+ }
+ }
internal interface Listener {
fun onClick(paymentMethod: PaymentMethod)
}
- private companion object {
- private const val TYPE_CARD = 1
- private const val TYPE_ADD_CARD = 2
- private const val TYPE_ADD_FPX = 3
+ private enum class ViewType {
+ Card,
+ AddCard,
+ AddFpx,
+ GooglePay
}
}
diff --git a/stripe/src/test/java/com/stripe/android/view/PaymentMethodsAdapterTest.kt b/stripe/src/test/java/com/stripe/android/view/PaymentMethodsAdapterTest.kt
index ad050517ac7..555df4a31e5 100644
--- a/stripe/src/test/java/com/stripe/android/view/PaymentMethodsAdapterTest.kt
+++ b/stripe/src/test/java/com/stripe/android/view/PaymentMethodsAdapterTest.kt
@@ -1,6 +1,7 @@
package com.stripe.android.view
import androidx.recyclerview.widget.RecyclerView
+import com.nhaarman.mockitokotlin2.verify
import com.stripe.android.model.PaymentMethodFixtures
import kotlin.test.BeforeTest
import kotlin.test.Test
@@ -10,7 +11,6 @@ import kotlin.test.assertNull
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import org.robolectric.RobolectricTestRunner
@@ -21,15 +21,15 @@ import org.robolectric.RobolectricTestRunner
class PaymentMethodsAdapterTest {
@Mock
private lateinit var adapterDataObserver: RecyclerView.AdapterDataObserver
- private lateinit var paymentMethodsAdapter: PaymentMethodsAdapter
+
+ private val paymentMethodsAdapter: PaymentMethodsAdapter =
+ PaymentMethodsAdapter(PaymentMethodsActivityStarter.Args.Builder()
+ .build()
+ )
@BeforeTest
fun setup() {
- PaymentMethodFixtures.createCard()
MockitoAnnotations.initMocks(this)
- paymentMethodsAdapter = PaymentMethodsAdapter(null,
- PaymentMethodsActivityStarter.Args.Builder()
- .build())
paymentMethodsAdapter.registerAdapterDataObserver(adapterDataObserver)
}
@@ -37,7 +37,7 @@ class PaymentMethodsAdapterTest {
fun setSelection_changesSelection() {
paymentMethodsAdapter.setPaymentMethods(PaymentMethodFixtures.CARD_PAYMENT_METHODS)
assertEquals(4, paymentMethodsAdapter.itemCount)
- verify(adapterDataObserver).onChanged()
+ verify(adapterDataObserver).onChanged()
paymentMethodsAdapter.selectedPaymentMethodId = paymentMethodsAdapter.paymentMethods[2].id
assertEquals(
@@ -75,7 +75,7 @@ class PaymentMethodsAdapterTest {
PaymentMethodFixtures.CARD_PAYMENT_METHODS[2].id,
paymentMethodsAdapter.selectedPaymentMethod?.id
)
- verify(adapterDataObserver, times(2))
+ verify(adapterDataObserver, times(2))
.onChanged()
}
@@ -96,18 +96,21 @@ class PaymentMethodsAdapterTest {
@Test
fun setPaymentMethods_whenNoInitialSpecified_returnsNull() {
- val adapter = PaymentMethodsAdapter(null,
- PaymentMethodsActivityStarter.Args.Builder()
- .build())
+ val adapter = PaymentMethodsAdapter(
+ intentArgs = PaymentMethodsActivityStarter.Args.Builder()
+ .build()
+ )
adapter.setPaymentMethods(PaymentMethodFixtures.CARD_PAYMENT_METHODS)
assertNull(adapter.selectedPaymentMethod)
}
@Test
fun setPaymentMethods_whenInitialSpecified_selectsIt() {
- val adapter = PaymentMethodsAdapter("pm_1000",
- PaymentMethodsActivityStarter.Args.Builder()
- .build())
+ val adapter = PaymentMethodsAdapter(
+ intentArgs = PaymentMethodsActivityStarter.Args.Builder()
+ .build(),
+ initiallySelectedPaymentMethodId = "pm_1000"
+ )
adapter.setPaymentMethods(PaymentMethodFixtures.CARD_PAYMENT_METHODS)
assertEquals("pm_1000", adapter.selectedPaymentMethod?.id)
}