Skip to content

Commit

Permalink
Add support for configuring a footer layout in payment methods screen (
Browse files Browse the repository at this point in the history
…#2895)

Summary
The footer layout id can be specified via
- `PaymentSessionConfig.Builder#setPaymentMethodsFooter()`
- `PaymentMethodsActivityStarter.Args.Builder#setPaymentMethodsFooter()`

Motivation
ANDROID-576
  • Loading branch information
mshafrir-stripe authored Sep 24, 2020
1 parent 0f55b00 commit a55d667
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class PaymentSessionActivity : AppCompatActivity() {
return PaymentSession(
activity = this,
config = PaymentSessionConfig.Builder()
.setPaymentMethodsFooter(R.layout.add_payment_method_footer)
.setAddPaymentMethodFooter(R.layout.add_payment_method_footer)
.setPrepopulatedShippingInfo(EXAMPLE_SHIPPING_INFO)
.setHiddenShippingInfoFields()
Expand Down
11 changes: 10 additions & 1 deletion stripe/res/layout/payment_methods_activity.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,21 @@
android:layout_below="@id/toolbar"
android:visibility="gone" />

<FrameLayout
android:id="@+id/footer_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:visibility="gone"/>

<com.stripe.android.view.PaymentMethodsRecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/toolbar"
android:layout_marginTop="@dimen/stripe_list_top_margin" />
android:layout_above="@+id/footer_container"
android:layout_marginTop="@dimen/stripe_list_top_margin"
android:layout_marginBottom="@dimen/stripe_list_top_margin"/>
</RelativeLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>
1 change: 1 addition & 0 deletions stripe/res/values/ids.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
<item type="id" name="stripe_payment_methods_add_fpx" />
<item type="id" name="stripe_add_payment_method_form" />
<item type="id" name="stripe_add_payment_method_footer" />
<item type="id" name="stripe_payment_methods_footer" />
</resources>
1 change: 1 addition & 0 deletions stripe/src/main/java/com/stripe/android/PaymentSession.kt
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ class PaymentSession @VisibleForTesting internal constructor(
.setInitialPaymentMethodId(
viewModel.getSelectedPaymentMethodId(selectedPaymentMethodId)
)
.setPaymentMethodsFooter(config.paymentMethodsFooterLayoutId)
.setAddPaymentMethodFooter(config.addPaymentMethodFooterLayoutId)
.setIsPaymentSessionActive(true)
.setPaymentConfiguration(PaymentConfiguration.getInstance(context))
Expand Down
20 changes: 20 additions & 0 deletions stripe/src/main/java/com/stripe/android/PaymentSessionConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,15 @@ data class PaymentSessionConfig internal constructor(
val prepopulatedShippingInfo: ShippingInformation? = null,
val isShippingInfoRequired: Boolean = false,
val isShippingMethodRequired: Boolean = false,

@LayoutRes
@get:LayoutRes
val paymentMethodsFooterLayoutId: Int = 0,

@LayoutRes
@get:LayoutRes
val addPaymentMethodFooterLayoutId: Int = 0,

val paymentMethodTypes: List<PaymentMethod.Type> = listOf(PaymentMethod.Type.Card),
val shouldShowGooglePay: Boolean = false,
val allowedShippingCountryCodes: Set<String> = emptySet(),
Expand Down Expand Up @@ -104,6 +110,9 @@ data class PaymentSessionConfig internal constructor(
private var shouldPrefetchCustomer: Boolean = true
private var canDeletePaymentMethods: Boolean = true

@LayoutRes
private var paymentMethodsFooterLayoutId: Int = 0

@LayoutRes
private var addPaymentMethodFooterLayoutId: Int = 0

Expand Down Expand Up @@ -164,6 +173,16 @@ data class PaymentSessionConfig internal constructor(
this.shippingMethodsRequired = shippingMethodsRequired
}

/**
* @param paymentMethodsFooterLayoutId optional layout id that will be inflated and
* displayed beneath the payment method selection list on [PaymentMethodsActivity]
*/
fun setPaymentMethodsFooter(
@LayoutRes paymentMethodsFooterLayoutId: Int
): Builder = apply {
this.paymentMethodsFooterLayoutId = paymentMethodsFooterLayoutId
}

/**
* @param addPaymentMethodFooterLayoutId optional layout id that will be inflated and
* displayed beneath the payment details collection form on [AddPaymentMethodActivity]
Expand Down Expand Up @@ -266,6 +285,7 @@ data class PaymentSessionConfig internal constructor(
prepopulatedShippingInfo = shippingInformation,
isShippingInfoRequired = shippingInfoRequired,
isShippingMethodRequired = shippingMethodsRequired,
paymentMethodsFooterLayoutId = paymentMethodsFooterLayoutId,
addPaymentMethodFooterLayoutId = addPaymentMethodFooterLayoutId,
paymentMethodTypes = paymentMethodTypes,
shouldShowGooglePay = shouldShowGooglePay,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@ package com.stripe.android.view

import android.app.Activity
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.text.method.LinkMovementMethod
import android.text.util.Linkify
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.text.util.LinkifyCompat
import androidx.core.view.ViewCompat
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.snackbar.Snackbar
import com.stripe.android.CustomerSession
import com.stripe.android.R
import com.stripe.android.databinding.PaymentMethodsActivityBinding
import com.stripe.android.exception.StripeException
import com.stripe.android.model.PaymentMethod
Expand Down Expand Up @@ -114,6 +122,15 @@ class PaymentMethodsActivity : AppCompatActivity() {
setDisplayShowHomeEnabled(true)
}

createFooterView(viewBinding.footerContainer)?.let { footer ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
viewBinding.recycler.accessibilityTraversalBefore = footer.id
footer.accessibilityTraversalAfter = viewBinding.recycler.id
}
viewBinding.footerContainer.addView(footer)
viewBinding.footerContainer.visibility = View.VISIBLE
}

fetchCustomerPaymentMethods()

// This prevents the first click from being eaten by the focus.
Expand Down Expand Up @@ -260,6 +277,27 @@ class PaymentMethodsActivity : AppCompatActivity() {
finish()
}

private fun createFooterView(
contentRoot: ViewGroup
): View? {
return if (args.paymentMethodsFooterLayoutId > 0) {
val footerView = layoutInflater.inflate(
args.paymentMethodsFooterLayoutId,
contentRoot,
false
)
footerView.id = R.id.stripe_payment_methods_footer
if (footerView is TextView) {
LinkifyCompat.addLinks(footerView, Linkify.ALL)
ViewCompat.enableAccessibleClickableSpanSupport(footerView)
footerView.movementMethod = LinkMovementMethod.getInstance()
}
footerView
} else {
null
}
}

override fun onDestroy() {
viewModel.selectedPaymentMethodId = adapter.selectedPaymentMethod?.id
super.onDestroy()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class PaymentMethodsActivityStarter : ActivityStarter<PaymentMethodsActivity, Ar
@Parcelize
data class Args internal constructor(
internal val initialPaymentMethodId: String?,
@LayoutRes val paymentMethodsFooterLayoutId: Int,
@LayoutRes val addPaymentMethodFooterLayoutId: Int,
internal val isPaymentSessionActive: Boolean,
internal val paymentMethodTypes: List<PaymentMethod.Type>,
Expand All @@ -61,6 +62,9 @@ class PaymentMethodsActivityStarter : ActivityStarter<PaymentMethodsActivity, Ar
private var paymentConfiguration: PaymentConfiguration? = null
private var windowFlags: Int? = null

@LayoutRes
private var paymentMethodsFooterLayoutId: Int = 0

@LayoutRes
private var addPaymentMethodFooterLayoutId: Int = 0

Expand Down Expand Up @@ -113,6 +117,16 @@ class PaymentMethodsActivityStarter : ActivityStarter<PaymentMethodsActivity, Ar
this.shouldShowGooglePay = shouldShowGooglePay
}

/**
* @param paymentMethodsFooterLayoutId optional layout id that will be inflated and
* displayed beneath the payment method selection list on [PaymentMethodsActivity]
*/
fun setPaymentMethodsFooter(
@LayoutRes paymentMethodsFooterLayoutId: Int
): Builder = apply {
this.paymentMethodsFooterLayoutId = paymentMethodsFooterLayoutId
}

/**
* @param addPaymentMethodFooterLayoutId optional layout id that will be inflated and
* displayed beneath the payment details collection form on [AddPaymentMethodActivity]
Expand Down Expand Up @@ -148,6 +162,7 @@ class PaymentMethodsActivityStarter : ActivityStarter<PaymentMethodsActivity, Ar
shouldShowGooglePay = shouldShowGooglePay,
useGooglePay = useGooglePay,
paymentConfiguration = paymentConfiguration,
paymentMethodsFooterLayoutId = paymentMethodsFooterLayoutId,
addPaymentMethodFooterLayoutId = addPaymentMethodFooterLayoutId,
windowFlags = windowFlags,
billingAddressFields = billingAddressFields,
Expand Down

0 comments on commit a55d667

Please sign in to comment.