Skip to content

[Android] Render checkout in bottom sheet#381

Open
kiftio wants to merge 1 commit into
mainfrom
dk/custom-bottom-sheet
Open

[Android] Render checkout in bottom sheet#381
kiftio wants to merge 1 commit into
mainfrom
dk/custom-bottom-sheet

Conversation

@kiftio

@kiftio kiftio commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Replace dialog-based checkout presentation with a native bottom sheet on Android

The Android checkout presentation has been migrated from a Dialog to a custom native bottom sheet. CheckoutDialog is removed and replaced by CheckoutBottomSheet, a ComponentDialog subclass that hosts the checkout WebView inside a full-screen edge-to-edge window with a slide-up sheet panel.

The bottom sheet includes:

  • A custom CheckoutBottomSheetLayout (RelativeLayout subclass) that owns open/close/settle animations using PathInterpolator curves and drag-to-dismiss gesture handling
  • A CheckoutBottomSheetScrollHandoff touch listener that coordinates exclusive gesture ownership between the WebView scroll and sheet drag, so a gesture that starts as a WebView scroll stays with the WebView even after reaching scroll-top
  • Rounded top corners on the sheet header via CheckoutSheetHeaderBackgroundDrawable
  • Edge-to-edge window configuration with transparent system bars, SOFT_INPUT_ADJUST_RESIZE for keyboard handling, and inset listeners for bottom padding and top margin
  • Accessibility focus routed to the close button after the opening animation, with a fallback announcement when the button is unavailable

CheckoutKitDialog is renamed to CheckoutHandle to reflect that it is a generic handle to a presented checkout rather than a reference to a dialog. present() returns CheckoutHandle? and dismiss() on the handle triggers the sheet's animated dismissal. Activity lifecycle teardown calls dismiss(animate = false) to skip the animation and immediately release the WebView.

The CheckoutWebViewListener is updated to accept a hideLoadingBackground callback alongside the existing progress bar callbacks, so the loading cover view is hidden once checkout content is ready.


Before you merge

Important

  • I've added tests to support my implementation
  • I have read and agree with the Contribution Guidelines
  • I have read and agree with the Code of Conduct
  • I've updated the relevant platform README (platforms/swift/README.md and/or platforms/android/README.md)

Releasing a new Swift version?
  • I have bumped the version in ShopifyCheckoutKit.podspec
  • I have bumped the version in platforms/swift/Sources/ShopifyCheckoutKit/ShopifyCheckoutKit.swift
  • I have updated the SwiftPM/CocoaPods version snippets in platforms/swift/README.md (major version only)
Releasing a new Embedded Checkout Protocol version?
  • I have bumped embeddedCheckoutProtocolAndroid in platforms/android/gradle/libs.versions.toml
  • I have updated protocol/languages/kotlin/embedded-checkout-protocol/api/embedded-checkout-protocol.api if the public API changed
Releasing a new Android version?
  • I have bumped checkoutKitAndroid in platforms/android/gradle/libs.versions.toml
  • I have updated the Gradle/Maven version snippets in platforms/android/README.md

Tip

See the Contributing documentation for the full release process per platform.

@github-actions github-actions Bot added the #gsd:50662 Rebase Checkout Kit on UCP label Jun 30, 2026

kiftio commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

@kiftio kiftio mentioned this pull request Jun 30, 2026
11 tasks
@kiftio kiftio force-pushed the dk/custom-bottom-sheet branch 5 times, most recently from 33688c9 to 3e920bb Compare June 30, 2026 13:32
## Troubleshooting

- Use `LogLevel.DEBUG` while integrating.
- For production release builds, use Android app shrinking and optimization

@kiftio kiftio Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mainly adding this note for unused protocol classes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we give them the example exclude paths here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a couple of gradle settings worth toggling

public static final fun present (Ljava/lang/String;Landroidx/activity/ComponentActivity;Lcom/shopify/checkoutkit/DefaultCheckoutListener;Lcom/shopify/checkoutkit/CheckoutProtocol$Client;)Lcom/shopify/checkoutkit/CheckoutKitDialog;
public static final synthetic fun present (Ljava/lang/String;Landroidx/activity/ComponentActivity;Lkotlin/jvm/functions/Function1;)Lcom/shopify/checkoutkit/CheckoutKitDialog;
public static synthetic fun present$default (Ljava/lang/String;Landroidx/activity/ComponentActivity;Lcom/shopify/checkoutkit/DefaultCheckoutListener;Lcom/shopify/checkoutkit/CheckoutProtocol$Client;ILjava/lang/Object;)Lcom/shopify/checkoutkit/CheckoutKitDialog;
public static final fun present (Ljava/lang/String;Landroidx/activity/ComponentActivity;Lcom/shopify/checkoutkit/DefaultCheckoutListener;)Lcom/shopify/checkoutkit/CheckoutHandle;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking to decouple a little from a type of presentation (Dialog), to a more general CheckoutHandle

dismissing = false
dismissFinalized = false

requestWindowFeature(Window.FEATURE_NO_TITLE)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can probably drop this line, we have R.style.CheckoutKitBottomSheetDialog, which has

<item name="android:windowNoTitle">true</item>

@kiftio kiftio force-pushed the dk/custom-bottom-sheet branch 2 times, most recently from 568a78a to fe0e2e8 Compare July 1, 2026 10:58
@kiftio kiftio force-pushed the dk/custom-bottom-sheet branch from fe0e2e8 to 5a4e62e Compare July 3, 2026 20:16
private val checkoutListener: CheckoutListener,
private val activity: ComponentActivity,
private val protocolClient: CheckoutProtocol.Client? = null,
) : ComponentDialog(activity, R.style.CheckoutKitBottomSheetDialog) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extending Dialog to pick up a lot of behaviour from that

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, what kind of behaviour is inherited?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We get lifecycle awareness.. So dealing with window attach/detach, show/dismiss, cacnel, outside touch, activity teardown and things like that.. And things like back handling, and some accessibility semantics

Hopefully a kind of stable base to build on top of

android:configChanges="orientation|keyboardHidden"
android:exported="true"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removing to ensure it wasn't masking issues with our webview softInputmode

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And do we want to keep this disabled, does this not affect the keyboard handling behaviour?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the manifest for the sample. So it does affect it keyboard handling in the sample.

I was thinking to keep it for ongoing validation/testing.. We could undo if preferred though

@kiftio kiftio force-pushed the dk/custom-bottom-sheet branch from 5a4e62e to 33b1303 Compare July 3, 2026 21:05
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="checkout_sheet_top_gap">24dp</dimen>
<dimen name="checkout_sheet_corner_radius">32dp</dimen>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made customizable up-stack

@kiftio kiftio marked this pull request as ready for review July 3, 2026 21:26
@kiftio kiftio requested a review from a team as a code owner July 3, 2026 21:26
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

React Native — Coverage Report

Lines Statements Branches Functions
Coverage: 92%
91.85% (327/356) 87.98% (183/208) 100% (86/86)

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

Package Size

Platform Artifact Base Head Delta
Android release AAR 160.8 KiB 190.2 KiB +29.4 KiB
Android file breakdown
File Base Head Delta
classes.jar 170.2 KiB 201.0 KiB +30.8 KiB
res/layout/checkout_sheet_content.xml 3.4 KiB +3.4 KiB
res/layout/dialog_checkout.xml 1.3 KiB -1.3 KiB
res/values/values.xml 564 B 1.1 KiB +535 B
R.txt 522 B 867 B +345 B
proguard.txt 798 B 798 B 0 B
AndroidManifest.xml 578 B 578 B 0 B
res/drawable/close.xml 431 B 431 B 0 B
res/menu/checkout_menu.xml 354 B 354 B 0 B
META-INF/com/android/build/gradle/aar-metadata.properties 157 B 157 B 0 B

Measured from the PR base SHA and PR head SHA. The file breakdown shows uncompressed sizes within each package artifact, so individual files do not sum to the compressed artifact total. This comment reports package artifact sizes only; it is not a final app binary-size report.

@kiftio kiftio changed the title [Android][Prototype] Render checkout in custom bottom sheet [Android] Render checkout in bottom sheet Jul 3, 2026
Comment thread .gitignore
.gradle/
.kotlin/
build/
*.apk

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a little unrleated, but ignore build artifacts

}

private const val LOG_TAG = "CheckoutBottomSheet"
private const val WINDOW_DIM_AMOUNT = 0.32f

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

customization added upstack

context: Context,
@ColorInt color: Int,
): GradientDrawable {
val cornerRadius = context.resources.getDimension(R.dimen.checkout_sheet_corner_radius)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved out to the Configuration class upstack

android:layout_height="match_parent"
android:background="@android:color/transparent">

<View

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

transparent View to catch taps outside the sheet for cancellation

@kiftio kiftio force-pushed the dk/custom-bottom-sheet branch 2 times, most recently from f6c2458 to aba1a8c Compare July 6, 2026 08:58
@kiftio kiftio force-pushed the dk/custom-bottom-sheet branch from aba1a8c to b02925f Compare July 6, 2026 09:14

@kieran-osgood-shopify kieran-osgood-shopify left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My comments are small but adding request changes for the swipe to dismiss sheet behaviour (noted in slack)

## Troubleshooting

- Use `LogLevel.DEBUG` while integrating.
- For production release builds, use Android app shrinking and optimization

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we give them the example exclude paths here?

private val checkoutListener: CheckoutListener,
private val activity: ComponentActivity,
private val protocolClient: CheckoutProtocol.Client? = null,
) : ComponentDialog(activity, R.style.CheckoutKitBottomSheetDialog) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, what kind of behaviour is inherited?

android:configChanges="orientation|keyboardHidden"
android:exported="true"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And do we want to keep this disabled, does this not affect the keyboard handling behaviour?

@kiftio kiftio force-pushed the dk/custom-bottom-sheet branch from b02925f to c746257 Compare July 6, 2026 12:37
Assisted-By: devx/6db0ff39-6d19-4074-ab7f-a027dc8b067f
@kiftio kiftio force-pushed the dk/custom-bottom-sheet branch from c746257 to 3e70d57 Compare July 6, 2026 13:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

#gsd:50662 Rebase Checkout Kit on UCP

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants