Skip to content

Custom form styling

Last updated: December 21, 2022

For complete control over how the various UI elements on your forms look, you can use our fully custom solution.

The default payment form

The default billing form

The default country picker

You can use the objects and properties listed below to edit each individual UI component displayed across the forms:

Custom PaymentDetailsStyle

1
object CustomPaymentDetailsStyle {
2
3
fun providePaymentDetailsStyle() = PaymentDetailsStyle(
4
paymentDetailsHeaderStyle = provideHeaderStyle(),
5
cardSchemeStyle = provideCardSchemeStyle(),
6
cardNumberStyle = provideCardNumberStyle(),
7
expiryDateStyle = provideExpiryDateStyle(),
8
cvvStyle = provideCVVStyle(),
9
addressSummaryStyle = provideAddressSummaryStyle(),
10
payButtonStyle = providePayButtonStyle(),
11
fieldsContainerStyle = ContainerStyle(
12
color = backgroundColor,
13
padding = Padding(
14
start = PaymentFormConstants.padding,
15
end = PaymentFormConstants.padding
16
)
17
)
18
)
19
20
private fun providePayButtonStyle(): PayButtonComponentStyle {
21
val buttonStyle = DefaultButtonStyle.lightSolid(
22
textId = R.string.cko_pay,
23
contentColor = inputFieldColor,
24
containerColor = textColor,
25
disabledContentColor = PaymentButtonConstants.disabledContentColor,
26
disabledContainerColor = PaymentButtonConstants.disabledContainerColor,
27
contentPadding = PaymentButtonConstants.contentPadding,
28
fontWeight = FontWeight.Bold,
29
margin = Margin(top = marginBottom),
30
shape = Shape.Circle,
31
cornerRadius = inputFieldCornerRadius
32
)
33
return PayButtonComponentStyle(buttonStyle = buttonStyle)
34
}
35
36
private fun provideAddressSummaryStyle(): AddressSummaryComponentStyle {
37
var style = DefaultAddressSummaryComponentStyle.light(isOptional = false)
38
val containerStyle =
39
ContainerStyle(color = inputFieldColor, shape = Shape.RoundCorner, cornerRadius = inputFieldCornerRadius)
40
41
style = style.copy(
42
titleStyle = null,
43
subTitleStyle = null,
44
containerStyle = containerStyle,
45
addAddressButtonStyle = DefaultButtonStyle.lightSolid(
46
textId = R.string.cko_add_billing_address,
47
trailingIconStyle = DefaultImageStyle.buttonTrailingImageStyle(tinColor = textColor),
48
fontWeight = FontWeight.SemiBold,
49
contentColor = textColor
50
),
51
summarySectionStyle = style.summarySectionStyle.copy(
52
editAddressButtonStyle = DefaultButtonStyle.lightSolid(
53
textId = R.string.cko_edit_billing_address,
54
trailingIconStyle = DefaultImageStyle.buttonTrailingImageStyle(tinColor = textColor),
55
fontWeight = FontWeight.SemiBold,
56
contentColor = textColor
57
),
58
containerStyle = containerStyle
59
)
60
)
61
return style
62
}
63
64
private fun provideCardNumberStyle(): CardNumberComponentStyle {
65
val inputStyle = DefaultLightStyle.inputComponentStyle(
66
placeholderResourceTextId = R.string.cko_card_number_title,
67
withLeadingIcon = false,
68
)
69
return CardNumberComponentStyle(
70
inputStyle = inputStyle.copy(
71
errorMessageStyle = provideErrorMessageStyle(),
72
inputFieldStyle = inputStyle.inputFieldStyle.copy(
73
containerStyle = provideContainerStyle(inputFieldCornerRadius.copy(bottomStart = 0, bottomEnd = 0)),
74
indicatorStyle = provideIndicatorStyle(),
75
placeholderStyle = inputStyle.inputFieldStyle.placeholderStyle.copy(
76
color = placeHolderTextColor
77
)
78
)
79
)
80
)
81
}
82
83
private fun provideExpiryDateStyle(): ExpiryDateComponentStyle {
84
val inputStyle = DefaultLightStyle.inputComponentStyle(
85
placeholderResourceTextId = R.string.cko_expiry_date_component_title,
86
margin = Margin(top = 2)
87
)
88
return ExpiryDateComponentStyle(
89
inputStyle.copy(
90
errorMessageStyle = provideErrorMessageStyle(),
91
inputFieldStyle = inputStyle.inputFieldStyle.copy(
92
containerStyle = provideContainerStyle(CornerRadius()),
93
indicatorStyle = provideIndicatorStyle(),
94
placeholderStyle = inputStyle.inputFieldStyle.placeholderStyle.copy(
95
color = placeHolderTextColor
96
)
97
)
98
)
99
)
100
}
101
102
private fun provideCVVStyle(): CvvComponentStyle {
103
val inputStyle = DefaultLightStyle.inputComponentStyle(
104
placeholderResourceTextId = R.string.cko_cvv_component_title,
105
margin = Margin(top = 2, bottom = margin)
106
)
107
return CvvComponentStyle(
108
inputStyle.copy(
109
errorMessageStyle = provideErrorMessageStyle(),
110
inputFieldStyle = inputStyle.inputFieldStyle.copy(
111
containerStyle = provideContainerStyle(inputFieldCornerRadius.copy(topStart = 0, topEnd = 0)),
112
indicatorStyle = provideIndicatorStyle(),
113
placeholderStyle = inputStyle.inputFieldStyle.placeholderStyle.copy(
114
color = placeHolderTextColor
115
)
116
)
117
)
118
)
119
}
120
121
private fun provideErrorMessageStyle(): TextLabelStyle =
122
DefaultTextLabelStyle.error(
123
padding = Padding(
124
top = ErrorConstants.errorMessageTopPadding,
125
bottom = ErrorConstants.errorMessageTopPadding
126
)
127
)
128
129
private fun provideIndicatorStyle(): InputFieldIndicatorStyle = InputFieldIndicatorStyle.Underline(
130
focusedUnderlineThickness = 0,
131
unfocusedUnderlineThickness = 0
132
)
133
134
private fun provideContainerStyle(cornerRadius: CornerRadius): ContainerStyle {
135
return ContainerStyle(
136
shape = inputFieldBorderShape,
137
color = inputFieldColor,
138
cornerRadius = cornerRadius
139
)
140
}
141
142
private fun provideCardSchemeStyle() = DefaultLightStyle.cardSchemeComponentStyle()
143
.copy(
144
containerStyle = ContainerStyle(
145
margin = Margin(
146
top = marginTop,
147
bottom = marginBottom
148
)
149
),
150
titleStyle = DefaultTextLabelStyle.subtitle(textId = R.string.accepted_card_schemes, color = textColor),
151
imageStyle = null
152
)
153
154
private fun provideHeaderStyle() = DefaultLightStyle.screenHeader(
155
textId = R.string.cko_payment_details_title,
156
imageId = R.drawable.ic_back_arrow,
157
leadingIconSize = backIconSize,
158
textColor = textColor,
159
fontWeight = FontWeight.Bold
160
).copy(
161
containerStyle = ContainerStyle(color = backgroundColor)
162
)
163
}

See an example on our GitHub project.

Custom BillingFormStyle

1
object CustomBillingFormStyle {
2
private val defaultKeyboardOptions = KeyboardOptions(imeAction = ImeAction.Next)
3
4
fun provideBillingFormStyle() = BillingFormStyle(
5
billingAddressDetailsStyle = provideBillingAddressDetailsStyle(),
6
countryPickerStyle = provideCountryPickerStyle()
7
)
8
9
private fun provideCountryPickerStyle(): CountryPickerStyle {
10
var style = DefaultCountryPickerStyle.light()
11
12
style = style.copy(
13
screenTitleStyle = style.screenTitleStyle.copy(
14
textStyle = style.screenTitleStyle.textStyle.copy(color = textColor),
15
leadingIconStyle = style.screenTitleStyle.leadingIconStyle?.copy(tinColor = textColor)
16
),
17
containerStyle = style.containerStyle.copy(
18
color = backgroundColor
19
),
20
searchFieldStyle = with(style.searchFieldStyle) {
21
copy(
22
containerStyle = provideContainerStyle().copy(
23
margin = Margin(
24
start = CountryPickerScreenConstants.margin,
25
end = CountryPickerScreenConstants.margin,
26
bottom = CountryPickerScreenConstants.margin
27
)
28
),
29
indicatorStyle = provideIndicatorStyle(),
30
placeholderStyle = placeholderStyle.copy(color = PaymentFormConstants.placeHolderTextColor),
31
leadingIconStyle = leadingIconStyle?.copy(
32
tinColor = textColor
33
),
34
trailingIconStyle = trailingIconStyle?.copy(
35
tinColor = textColor
36
)
37
)
38
},
39
searchItemStyle = style.searchItemStyle.copy(
40
textStyle = style.searchItemStyle.textStyle.copy(
41
color = textColor
42
)
43
)
44
)
45
return style
46
}
47
48
private fun provideBillingAddressDetailsStyle() = BillingAddressDetailsStyle(
49
headerComponentStyle = provideHeaderComponentStyle(),
50
inputComponentsContainerStyle = InputComponentsContainerStyle(fetchInputComponentStyleValues()),
51
countryComponentStyle = provideCountryComponentStyle(),
52
containerStyle = ContainerStyle(color = backgroundColor)
53
)
54
55
private fun provideCountryComponentStyle(): CountryComponentStyle {
56
var style = DefaultCountryComponentStyle.light()
57
var inputStyle = style.inputStyle
58
59
inputStyle = inputStyle.copy(
60
inputFieldStyle = provideInputFieldStyle(inputStyle.inputFieldStyle),
61
titleStyle = inputStyle.titleStyle?.copy(
62
textStyle = inputStyle.titleStyle?.textStyle?.copy(color = textColor) ?: TextStyle(),
63
containerStyle = ContainerStyle(padding = Padding(start = cornerRadius, bottom = paddingTenDp))
64
)
65
)
66
67
style = style.copy(
68
inputStyle = inputStyle
69
)
70
71
return style
72
}
73
74
private fun provideHeaderComponentStyle(): HeaderComponentStyle {
75
var style = DefaultBillingAddressDetailsStyle.headerComponentStyle()
76
style = style.copy(
77
headerTitleStyle = style.headerTitleStyle.copy(
78
textStyle = style.headerTitleStyle.textStyle.copy(
79
color = textColor, fontWeight = FontWeight.Bold
80
),
81
),
82
headerButtonStyle = style.headerButtonStyle
83
.copy(
84
contentColor = inputFieldColor,
85
containerColor = textColor,
86
shape = Shape.Circle,
87
cornerRadius = inputFieldCornerRadius
88
)
89
)
90
91
return style
92
}
93
94
@Suppress("LongMethod")
95
private fun fetchInputComponentStyleValues(): LinkedHashMap<BillingFormFields, InputComponentStyle> {
96
val inputComponentsStyles: LinkedHashMap<BillingFormFields, InputComponentStyle> = linkedMapOf()
97
98
inputComponentsStyles[BillingFormFields.AddressLineOne] = provideInputComponentStyle(
99
placeholderTextId = R.string.cko_billing_form_input_field_address_line_one,
100
isFieldOptional = false,
101
keyboardOptions = defaultKeyboardOptions,
102
padding = Padding(
103
start = LightStyleConstants.inputComponentLeftPadding,
104
end = LightStyleConstants.inputComponentRightPadding,
105
)
106
)
107
108
inputComponentsStyles[BillingFormFields.AddressLineTwo] = provideInputComponentStyle(
109
placeholderTextId = R.string.cko_billing_form_input_field_address_line_two,
110
infoTextId = R.string.cko_input_field_optional_info,
111
isFieldOptional = true,
112
keyboardOptions = defaultKeyboardOptions,
113
padding = Padding(
114
start = LightStyleConstants.inputComponentLeftPadding,
115
end = LightStyleConstants.inputComponentRightPadding,
116
bottom = LightStyleConstants.inputComponentBottomPadding
117
)
118
)
119
120
inputComponentsStyles[BillingFormFields.City] = provideInputComponentStyle(
121
placeholderTextId = R.string.cko_billing_form_input_field_city,
122
isFieldOptional = false,
123
keyboardOptions = defaultKeyboardOptions,
124
padding = Padding(
125
start = LightStyleConstants.inputComponentLeftPadding,
126
end = LightStyleConstants.inputComponentRightPadding
127
)
128
)
129
130
inputComponentsStyles[BillingFormFields.State] = provideInputComponentStyle(
131
placeholderTextId = R.string.cko_billing_form_input_field_state,
132
infoTextId = R.string.cko_input_field_optional_info,
133
isFieldOptional = true,
134
keyboardOptions = defaultKeyboardOptions,
135
padding = Padding(
136
start = LightStyleConstants.inputComponentLeftPadding,
137
end = LightStyleConstants.inputComponentRightPadding,
138
bottom = LightStyleConstants.inputComponentBottomPadding
139
)
140
)
141
142
inputComponentsStyles[BillingFormFields.PostCode] = provideInputComponentStyle(
143
placeholderTextId = R.string.cko_billing_form_input_field_postcode,
144
isFieldOptional = false,
145
keyboardOptions = defaultKeyboardOptions,
146
padding = Padding(
147
start = LightStyleConstants.inputComponentLeftPadding,
148
end = LightStyleConstants.inputComponentRightPadding,
149
bottom = LightStyleConstants.inputComponentBottomPadding
150
)
151
)
152
153
inputComponentsStyles[BillingFormFields.Phone] = provideInputComponentStyle(
154
placeholderTextId = R.string.cko_billing_form_input_field_phone_title,
155
isFieldOptional = false,
156
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
157
padding = Padding(
158
start = LightStyleConstants.inputComponentLeftPadding,
159
end = LightStyleConstants.inputComponentRightPadding,
160
bottom = paddingTenDp
161
)
162
)
163
164
return inputComponentsStyles
165
}
166
167
private fun provideInputComponentStyle(
168
@StringRes placeholderTextId: Int? = null,
169
@StringRes infoTextId: Int? = null,
170
isFieldOptional: Boolean = false,
171
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
172
padding: Padding = Padding()
173
): InputComponentStyle {
174
var style = DefaultLightStyle.inputComponentStyle(
175
placeholderResourceTextId = placeholderTextId,
176
infoTextId = infoTextId,
177
padding = padding,
178
isFieldOptional = isFieldOptional,
179
keyboardOptions = keyboardOptions
180
)
181
182
style = style.copy(
183
infoStyle = style.infoStyle?.copy(
184
containerStyle = ContainerStyle(
185
padding = Padding(
186
top = paddingSixDp, bottom = paddingSixDp, end = cornerRadius
187
)
188
)
189
),
190
inputFieldStyle = provideInputFieldStyle(style.inputFieldStyle)
191
)
192
193
return style
194
}
195
196
private fun provideInputFieldStyle(inputFieldStyle: InputFieldStyle): InputFieldStyle {
197
return inputFieldStyle.copy(
198
containerStyle = provideContainerStyle(),
199
indicatorStyle = provideIndicatorStyle(),
200
placeholderStyle = inputFieldStyle.placeholderStyle.copy(
201
color = PaymentFormConstants.placeHolderTextColor
202
),
203
trailingIconStyle = inputFieldStyle.trailingIconStyle?.copy(
204
tinColor = textColor
205
)
206
)
207
}
208
209
private fun provideIndicatorStyle(): InputFieldIndicatorStyle = InputFieldIndicatorStyle.Underline(
210
focusedUnderlineThickness = 0, unfocusedUnderlineThickness = 0
211
)
212
213
private fun provideContainerStyle(): ContainerStyle {
214
return ContainerStyle(
215
shape = inputFieldBorderShape, color = inputFieldColor, cornerRadius = inputFieldCornerRadius
216
)
217
}
218
}

See an example on our GitHub project.

Custom PaymentFormStyle

1
PaymentFormStyle(
2
CustomPaymentDetailsStyle.providePaymentDetailsStyle(),
3
CustomBillingFormStyle.provideBillingFormStyle()
4
)

See an example on our our GitHub project.