# Customize the Frames Android SDK > **Note** > > Frames will be deprecated on June 30, 2026. [Upgrade to Flow for mobile](https://www.checkout.com/docs/payments/accept-payments/upgrade-to-flow-from-frames/upgrade-from-frames-for-android.md), our pre-built, customizable payment user interface. Flow provides a more flexible, scalable, and feature-rich integration, as well as access to additional payment methods. When a customer initiates a payment with the Frames Android SDK, their payment information is collected via three customizable forms: - Payment Form: prompts users for their payment card details - Billing Form: prompts users for their billing information - Country Picker: prompts the user to select a country The styling of these forms can be customized through the use of the `PaymentDetailsStyle`, `BillingAddressDetailsStyle` and `CountryPickerStyle` objects, which are wrapped in the `PaymentFormStyle` wrapper. ```kotlin public data class PaymentFormStyle( public var paymentDetailsStyle: PaymentDetailsStyle = PaymentDetailsStyle(), public var billingFormStyle: BillingFormStyle = BillingFormStyle() ) public data class BillingFormStyle( public var billingAddressDetailsStyle: BillingAddressDetailsStyle = BillingAddressDetailsStyle(), public var countryPickerStyle: CountryPickerStyle = DefaultCountryPickerStyle.light() ) ``` You can choose between three different styling options for customization, depending on how much control you need over the forms' UI design. In order of increasing complexity these are: - [Default](#Default_form) - [Themed](#Themed_form) - [Custom](#Custom_form) --- ## Default form The default integration is the quickest way to display the forms required to collect payment information, with no additional customization required. Localization support for the following languages is built into the default integration: - Arabic - Dutch - English - French - German - Italian - Romanian - Spanish You can also add your own localized strings to add support for additional languages. For basic customization, the `PaymentDetailsStyle`, `BillingFormStyle`, `BillingAddressDetailsStyle` and `CountryPickerStyle` objects expose properties that allow you to change the text and colors displayed on the forms. ```kotlin // Create a default style val paymentFormStyle = PaymentFormStyle() // Create a custom input component style val customInputComponentStyle = DefaultLightStyle.inputComponentStyle( titleTextId = R.string.custom_card_number_title, withLeadingIcon = true, margin = Margin(bottom = 16) ) // Modify payment form style with custom input component style paymentFormStyle.paymentDetailsStyle.cardNumberStyle.inputStyle = customInputComponentStyle // Hide flag images for country picker paymentFormStyle.billingFormStyle.countryPickerStyle.withFlag = false ``` --- ## Themed form If you want to customize your forms beyond what is supported by the default integration, you can apply a theme using the `Theme` object. When instantiating a new `Theme` object, you must supply the following fields at a minimum: - `accentColor` - `textColor` - `errorColor` - `backgroundColor` - `fieldBackgroundColor` - `enabledButtonColor` - `disabledButtonColor` You can then optionally provide additional values to customize other elements including button styling, custom placeholder and error text, and field input controls. Dynamic font sizing based on the user's device is built into the `Theme` object. ```kotlin // Create a color object with generic colors which will be used on all screens private val paymentFormThemeColors = PaymentFormThemeColors( accentColor = 0XFF00CC2D, textColor = 0XFFB1B1B1, errorColor = 0XFFFF0000, backgroundColor = 0xFF17201E, fieldBackgroundColor = 0XFF24302D, enabledButtonColor = 0xFFFFFFFF, disabledButtonColor = 0XFF003300 ) // Customize card number component private val cardNumber = PaymentFormComponentBuilder() .setPaymentFormField(PaymentFormComponentField.CardNumber) .setTitleTextId(R.string.cko_card_number_title) .setSubTitleText("Card number is required") .build() // Customize address line 1 component private val addressLineOne = PaymentFormComponentBuilder() .setPaymentFormField(PaymentFormComponentField.AddressLineOne) .setTitleTextId(R.string.cko_billing_form_input_field_address_line_one) .setSubTitleText("E.g. street address, apartment number") .setInfoTextId(R.string.cko_input_field_optional_info) .setIsFieldOptional(true) .setIsFieldHidden(false) .build() // Customize address line 2 component private val addressLineTwo = PaymentFormComponentBuilder() .setPaymentFormField(PaymentFormComponentField.AddressLineTwo) .setIsFieldHidden(true) .build() // Customize summary button private val addBillingSummaryButton = PaymentFormComponentBuilder() .setPaymentFormField(PaymentFormComponentField.AddBillingSummaryButton) .setIsFieldOptional(false) .setTitleText("Add billing address") .build() // Customize billing summary button private val editBillingSummaryButton = PaymentFormComponentBuilder() .setPaymentFormField(PaymentFormComponentField.EditBillingSummaryButton) .setTitleText("Edit billing address") .build() // Create a payment form theme fun providePaymentFormTheme(): PaymentFormTheme { return PaymentFormTheme( paymentFormThemeColors = paymentFormThemeColors, / * option 1: Use combination of default and custom components */ paymentFormComponents = DefaultPaymentFormTheme.providePaymentFormComponents cardNumber = cardNumber, addressLineOne = addressLineOne, addressLineTwo = addressLineTwo, addBillingSummaryButton = addBillingSummaryButton, editBillingSummaryButton = editBillingSummaryButton ), / * option 2: Use default components * paymentFormComponents = DefaultPaymentFormTheme.provideComponents() */ paymentFormShape = PaymentFormShape( inputFieldShape = Shape.RoundCorner, addressSummaryShape = Shape.Rectangle, buttonShape = Shape.Circle ), paymentFormCornerRadius = PaymentFormCornerRadius( inputFieldCornerRadius = CornerRadius(INPUT_FIELD_CORNER_RADIUS), addressSummaryCornerRadius = CornerRadius(INPUT_FIELD_CORNER_RADIUS) ) ) } ``` --- ## Custom form For complete control over how the various UI elements on your forms look, you can use the fully custom solution. You can use the following objects and properties to edit each individual UI component displayed across the forms: ### Custom PaymentDetailsStyle ```kotlin object CustomPaymentDetailsStyle { fun providePaymentDetailsStyle() = PaymentDetailsStyle( paymentDetailsHeaderStyle = provideHeaderStyle(), cardSchemeStyle = provideCardSchemeStyle(), cardNumberStyle = provideCardNumberStyle(), expiryDateStyle = provideExpiryDateStyle(), cvvStyle = provideCVVStyle(), addressSummaryStyle = provideAddressSummaryStyle(), payButtonStyle = providePayButtonStyle(), fieldsContainerStyle = ContainerStyle( color = backgroundColor, padding = Padding( start = PaymentFormConstants.padding, end = PaymentFormConstants.padding ) ) ) private fun providePayButtonStyle(): PayButtonComponentStyle { val buttonStyle = DefaultButtonStyle.lightSolid( textId = R.string.cko_pay, contentColor = inputFieldColor, containerColor = textColor, disabledContentColor = PaymentButtonConstants.disabledContentColor, disabledContainerColor = PaymentButtonConstants.disabledContainerColor, contentPadding = PaymentButtonConstants.contentPadding, fontWeight = FontWeight.Bold, margin = Margin(top = marginBottom), shape = Shape.Circle, cornerRadius = inputFieldCornerRadius ) return PayButtonComponentStyle(buttonStyle = buttonStyle) } private fun provideAddressSummaryStyle(): AddressSummaryComponentStyle { var style = DefaultAddressSummaryComponentStyle.light(isOptional = false) val containerStyle = ContainerStyle(color = inputFieldColor, shape = Shape.RoundCorner, cornerRadius = inputFieldCornerRadius) style = style.copy( titleStyle = null, subTitleStyle = null, containerStyle = containerStyle, addAddressButtonStyle = DefaultButtonStyle.lightSolid( textId = R.string.cko_add_billing_address, trailingIconStyle = DefaultImageStyle.buttonTrailingImageStyle(tinColor = textColor), fontWeight = FontWeight.SemiBold, contentColor = textColor ), summarySectionStyle = style.summarySectionStyle.copy( editAddressButtonStyle = DefaultButtonStyle.lightSolid( textId = R.string.cko_edit_billing_address, trailingIconStyle = DefaultImageStyle.buttonTrailingImageStyle(tinColor = textColor), fontWeight = FontWeight.SemiBold, contentColor = textColor ), containerStyle = containerStyle ) ) return style } private fun provideCardNumberStyle(): CardNumberComponentStyle { val inputStyle = DefaultLightStyle.inputComponentStyle( placeholderResourceTextId = R.string.cko_card_number_title, withLeadingIcon = false, ) return CardNumberComponentStyle( inputStyle = inputStyle.copy( errorMessageStyle = provideErrorMessageStyle(), inputFieldStyle = inputStyle.inputFieldStyle.copy( containerStyle = provideContainerStyle(inputFieldCornerRadius.copy(bottomStart = 0, bottomEnd = 0)), indicatorStyle = provideIndicatorStyle(), placeholderStyle = inputStyle.inputFieldStyle.placeholderStyle.copy( color = placeHolderTextColor ) ) ) ) } private fun provideExpiryDateStyle(): ExpiryDateComponentStyle { val inputStyle = DefaultLightStyle.inputComponentStyle( placeholderResourceTextId = R.string.cko_expiry_date_component_title, margin = Margin(top = 2) ) return ExpiryDateComponentStyle( inputStyle.copy( errorMessageStyle = provideErrorMessageStyle(), inputFieldStyle = inputStyle.inputFieldStyle.copy( containerStyle = provideContainerStyle(CornerRadius()), indicatorStyle = provideIndicatorStyle(), placeholderStyle = inputStyle.inputFieldStyle.placeholderStyle.copy( color = placeHolderTextColor ) ) ) ) } private fun provideCVVStyle(): CvvComponentStyle { val inputStyle = DefaultLightStyle.inputComponentStyle( placeholderResourceTextId = R.string.cko_cvv_component_title, margin = Margin(top = 2, bottom = margin) ) return CvvComponentStyle( inputStyle.copy( errorMessageStyle = provideErrorMessageStyle(), inputFieldStyle = inputStyle.inputFieldStyle.copy( containerStyle = provideContainerStyle(inputFieldCornerRadius.copy(topStart = 0, topEnd = 0)), indicatorStyle = provideIndicatorStyle(), placeholderStyle = inputStyle.inputFieldStyle.placeholderStyle.copy( color = placeHolderTextColor ) ) ) ) } private fun provideErrorMessageStyle(): TextLabelStyle = DefaultTextLabelStyle.error( padding = Padding( top = ErrorConstants.errorMessageTopPadding, bottom = ErrorConstants.errorMessageTopPadding ) ) private fun provideIndicatorStyle(): InputFieldIndicatorStyle = InputFieldIndicatorStyle.Underline( focusedUnderlineThickness = 0, unfocusedUnderlineThickness = 0 ) private fun provideContainerStyle(cornerRadius: CornerRadius): ContainerStyle { return ContainerStyle( shape = inputFieldBorderShape, color = inputFieldColor, cornerRadius = cornerRadius ) } private fun provideCardSchemeStyle() = DefaultLightStyle.cardSchemeComponentStyle() .copy( containerStyle = ContainerStyle( margin = Margin( top = marginTop, bottom = marginBottom ) ), titleStyle = DefaultTextLabelStyle.subtitle(textId = R.string.accepted_card_schemes, color = textColor), imageStyle = null ) private fun provideHeaderStyle() = DefaultLightStyle.screenHeader( textId = R.string.cko_payment_details_title, imageId = R.drawable.ic_back_arrow, leadingIconSize = backIconSize, textColor = textColor, fontWeight = FontWeight.Bold ).copy( containerStyle = ContainerStyle(color = backgroundColor) ) } ``` ### Custom BillingFormStyle ```kotlin object CustomBillingFormStyle { private val defaultKeyboardOptions = KeyboardOptions(imeAction = ImeAction.Next) fun provideBillingFormStyle() = BillingFormStyle( billingAddressDetailsStyle = provideBillingAddressDetailsStyle(), countryPickerStyle = provideCountryPickerStyle() ) private fun provideCountryPickerStyle(): CountryPickerStyle { var style = DefaultCountryPickerStyle.light() style = style.copy( screenTitleStyle = style.screenTitleStyle.copy( textStyle = style.screenTitleStyle.textStyle.copy(color = textColor), leadingIconStyle = style.screenTitleStyle.leadingIconStyle?.copy(tinColor = textColor) ), containerStyle = style.containerStyle.copy( color = backgroundColor ), searchFieldStyle = with(style.searchFieldStyle) { copy( containerStyle = provideContainerStyle().copy( margin = Margin( start = CountryPickerScreenConstants.margin, end = CountryPickerScreenConstants.margin, bottom = CountryPickerScreenConstants.margin ) ), indicatorStyle = provideIndicatorStyle(), placeholderStyle = placeholderStyle.copy(color = PaymentFormConstants.placeHolderTextColor), leadingIconStyle = leadingIconStyle?.copy( tinColor = textColor ), trailingIconStyle = trailingIconStyle?.copy( tinColor = textColor ) ) }, searchItemStyle = style.searchItemStyle.copy( textStyle = style.searchItemStyle.textStyle.copy( color = textColor ) ) ) return style } private fun provideBillingAddressDetailsStyle() = BillingAddressDetailsStyle( headerComponentStyle = provideHeaderComponentStyle(), inputComponentsContainerStyle = InputComponentsContainerStyle(fetchInputComponentStyleValues()), countryComponentStyle = provideCountryComponentStyle(), containerStyle = ContainerStyle(color = backgroundColor) ) private fun provideCountryComponentStyle(): CountryComponentStyle { var style = DefaultCountryComponentStyle.light() var inputStyle = style.inputStyle inputStyle = inputStyle.copy( inputFieldStyle = provideInputFieldStyle(inputStyle.inputFieldStyle), titleStyle = inputStyle.titleStyle?.copy( textStyle = inputStyle.titleStyle?.textStyle?.copy(color = textColor) ?: TextStyle(), containerStyle = ContainerStyle(padding = Padding(start = cornerRadius, bottom = paddingTenDp)) ) ) style = style.copy( inputStyle = inputStyle ) return style } private fun provideHeaderComponentStyle(): HeaderComponentStyle { var style = DefaultBillingAddressDetailsStyle.headerComponentStyle() style = style.copy( headerTitleStyle = style.headerTitleStyle.copy( textStyle = style.headerTitleStyle.textStyle.copy( color = textColor, fontWeight = FontWeight.Bold ), ), headerButtonStyle = style.headerButtonStyle .copy( contentColor = inputFieldColor, containerColor = textColor, shape = Shape.Circle, cornerRadius = inputFieldCornerRadius ) ) return style } @Suppress("LongMethod") private fun fetchInputComponentStyleValues(): LinkedHashMap { val inputComponentsStyles: LinkedHashMap = linkedMapOf() inputComponentsStyles[BillingFormFields.AddressLineOne] = provideInputComponentStyle( placeholderTextId = R.string.cko_billing_form_input_field_address_line_one, isFieldOptional = false, keyboardOptions = defaultKeyboardOptions, padding = Padding( start = LightStyleConstants.inputComponentLeftPadding, end = LightStyleConstants.inputComponentRightPadding, ) ) inputComponentsStyles[BillingFormFields.AddressLineTwo] = provideInputComponentStyle( placeholderTextId = R.string.cko_billing_form_input_field_address_line_two, infoTextId = R.string.cko_input_field_optional_info, isFieldOptional = true, keyboardOptions = defaultKeyboardOptions, padding = Padding( start = LightStyleConstants.inputComponentLeftPadding, end = LightStyleConstants.inputComponentRightPadding, bottom = LightStyleConstants.inputComponentBottomPadding ) ) inputComponentsStyles[BillingFormFields.City] = provideInputComponentStyle( placeholderTextId = R.string.cko_billing_form_input_field_city, isFieldOptional = false, keyboardOptions = defaultKeyboardOptions, padding = Padding( start = LightStyleConstants.inputComponentLeftPadding, end = LightStyleConstants.inputComponentRightPadding ) ) inputComponentsStyles[BillingFormFields.State] = provideInputComponentStyle( placeholderTextId = R.string.cko_billing_form_input_field_state, infoTextId = R.string.cko_input_field_optional_info, isFieldOptional = true, keyboardOptions = defaultKeyboardOptions, padding = Padding( start = LightStyleConstants.inputComponentLeftPadding, end = LightStyleConstants.inputComponentRightPadding, bottom = LightStyleConstants.inputComponentBottomPadding ) ) inputComponentsStyles[BillingFormFields.PostCode] = provideInputComponentStyle( placeholderTextId = R.string.cko_billing_form_input_field_postcode, isFieldOptional = false, keyboardOptions = defaultKeyboardOptions, padding = Padding( start = LightStyleConstants.inputComponentLeftPadding, end = LightStyleConstants.inputComponentRightPadding, bottom = LightStyleConstants.inputComponentBottomPadding ) ) inputComponentsStyles[BillingFormFields.Phone] = provideInputComponentStyle( placeholderTextId = R.string.cko_billing_form_input_field_phone_title, isFieldOptional = false, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done), padding = Padding( start = LightStyleConstants.inputComponentLeftPadding, end = LightStyleConstants.inputComponentRightPadding, bottom = paddingTenDp ) ) return inputComponentsStyles } private fun provideInputComponentStyle( @StringRes placeholderTextId: Int? = null, @StringRes infoTextId: Int? = null, isFieldOptional: Boolean = false, keyboardOptions: KeyboardOptions = KeyboardOptions.Default, padding: Padding = Padding() ): InputComponentStyle { var style = DefaultLightStyle.inputComponentStyle( placeholderResourceTextId = placeholderTextId, infoTextId = infoTextId, padding = padding, isFieldOptional = isFieldOptional, keyboardOptions = keyboardOptions ) style = style.copy( infoStyle = style.infoStyle?.copy( containerStyle = ContainerStyle( padding = Padding( top = paddingSixDp, bottom = paddingSixDp, end = cornerRadius ) ) ), inputFieldStyle = provideInputFieldStyle(style.inputFieldStyle) ) return style } private fun provideInputFieldStyle(inputFieldStyle: InputFieldStyle): InputFieldStyle { return inputFieldStyle.copy( containerStyle = provideContainerStyle(), indicatorStyle = provideIndicatorStyle(), placeholderStyle = inputFieldStyle.placeholderStyle.copy( color = PaymentFormConstants.placeHolderTextColor ), trailingIconStyle = inputFieldStyle.trailingIconStyle?.copy( tinColor = textColor ) ) } private fun provideIndicatorStyle(): InputFieldIndicatorStyle = InputFieldIndicatorStyle.Underline( focusedUnderlineThickness = 0, unfocusedUnderlineThickness = 0 ) private fun provideContainerStyle(): ContainerStyle { return ContainerStyle( shape = inputFieldBorderShape, color = inputFieldColor, cornerRadius = inputFieldCornerRadius ) } } ``` ### Custom PaymentFormStyle ```kotlin PaymentFormStyle( CustomPaymentDetailsStyle.providePaymentDetailsStyle(), CustomBillingFormStyle.provideBillingFormStyle() ) ```