Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow the user to set the default EditText color. #3457

Merged
merged 8 commits into from
Mar 19, 2021
4 changes: 3 additions & 1 deletion stripe/api/stripe.api
Original file line number Diff line number Diff line change
Expand Up @@ -5859,7 +5859,7 @@ public class com/stripe/android/view/StripeEditText : com/google/android/materia
public fun <init> (Landroid/content/Context;Landroid/util/AttributeSet;I)V
public synthetic fun <init> (Landroid/content/Context;Landroid/util/AttributeSet;IILkotlin/jvm/internal/DefaultConstructorMarker;)V
protected fun getAccessibilityText ()Ljava/lang/String;
public final fun getCachedColorStateList ()Landroid/content/res/ColorStateList;
public final fun getDefaultColorState ()Landroid/content/res/ColorStateList;
public final fun getDefaultErrorColorInt ()I
public final fun getShouldShowError ()Z
protected final fun isLastKeyDelete ()Z
Expand All @@ -5872,6 +5872,8 @@ public class com/stripe/android/view/StripeEditText : com/google/android/materia
public final fun setErrorMessageListener (Lcom/stripe/android/view/StripeEditText$ErrorMessageListener;)V
protected final fun setLastKeyDelete (Z)V
public final fun setShouldShowError (Z)V
public fun setTextColor (I)V
public fun setTextColor (Landroid/content/res/ColorStateList;)V
}

public abstract interface class com/stripe/android/view/StripeEditText$AfterTextChangedListener {
Expand Down
43 changes: 29 additions & 14 deletions stripe/src/main/java/com/stripe/android/view/StripeEditText.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputConnection
import android.view.inputmethod.InputConnectionWrapper
import androidx.annotation.ColorInt
import androidx.annotation.VisibleForTesting
import androidx.core.content.ContextCompat
import androidx.core.widget.doAfterTextChanged
import com.google.android.material.textfield.TextInputEditText
Expand All @@ -30,8 +31,15 @@ open class StripeEditText @JvmOverloads constructor(

private var afterTextChangedListener: AfterTextChangedListener? = null
private var deleteEmptyListener: DeleteEmptyListener? = null
var cachedColorStateList: ColorStateList? = null
private set

var defaultColorState: ColorStateList
michelleb-stripe marked this conversation as resolved.
Show resolved Hide resolved
@VisibleForTesting
internal set
private var externalColorState: ColorStateList? = null
@ColorInt
private var defaultErrorColor: Int = 0
@ColorInt
private var externalErrorColor: Int? = null
michelleb-stripe marked this conversation as resolved.
Show resolved Hide resolved
michelleb-stripe marked this conversation as resolved.
Show resolved Hide resolved

/**
* Gets whether or not the text should be displayed in error mode.
Expand All @@ -48,9 +56,9 @@ open class StripeEditText @JvmOverloads constructor(
if (field != shouldShowError) {
// only update the view's UI if the property's value is changing
if (shouldShowError) {
setTextColor(errorColor ?: defaultErrorColor)
super.setTextColor(externalErrorColor ?: defaultErrorColor)
} else {
setTextColor(cachedColorStateList)
super.setTextColor(externalColorState ?: defaultColorState)
}
refreshDrawableState()
}
Expand All @@ -65,12 +73,6 @@ open class StripeEditText @JvmOverloads constructor(
return text?.toString().orEmpty()
}

@ColorInt
private var defaultErrorColor: Int = 0

@ColorInt
private var errorColor: Int? = null

private var errorMessageListener: ErrorMessageListener? = null

/**
Expand All @@ -89,12 +91,26 @@ open class StripeEditText @JvmOverloads constructor(
maxLines = 1
listenForTextChanges()
listenForDeleteEmpty()
defaultColorState = textColors
determineDefaultErrorColor()
cachedColorStateList = textColors
}

protected open val accessibilityText: String? = null

override fun setTextColor(colors: ColorStateList?) {
super.setTextColor(colors)

// This will only use textColors and not colors because textColor is never null
externalColorState = textColors
}

override fun setTextColor(color: Int) {
super.setTextColor(color)

// This will only use textColors and not colors because textColor is never null
externalColorState = ColorStateList.valueOf(color)
}
michelleb-stripe marked this conversation as resolved.
Show resolved Hide resolved

override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection? {
val inputConnection = super.onCreateInputConnection(outAttrs)
return inputConnection?.let {
Expand Down Expand Up @@ -135,7 +151,7 @@ open class StripeEditText @JvmOverloads constructor(
* @param errorColor a [ColorInt]
*/
fun setErrorColor(@ColorInt errorColor: Int) {
this.errorColor = errorColor
this.externalErrorColor = errorColor
}

override fun onInitializeAccessibilityNodeInfo(info: AccessibilityNodeInfo) {
Expand All @@ -146,10 +162,9 @@ open class StripeEditText @JvmOverloads constructor(
}

private fun determineDefaultErrorColor() {
cachedColorStateList = textColors
defaultErrorColor = ContextCompat.getColor(
context,
if (StripeColorUtils.isColorDark(textColors.defaultColor)) {
mshafrir-stripe marked this conversation as resolved.
Show resolved Hide resolved
if (StripeColorUtils.isColorDark(defaultColorState.defaultColor)) {
// Note: if the _text_ color is dark, then this is a
// light theme, and vice-versa.
R.color.stripe_error_text_light_theme
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.stripe.android.view

import android.content.Context
import android.content.res.ColorStateList
import androidx.annotation.ColorInt
import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.content.ContextCompat
Expand Down Expand Up @@ -81,7 +82,7 @@ internal class StripeEditTextTest {

@Test
fun getDefaultErrorColorInt_onDarkTheme_returnsDarkError() {
editText.setTextColor(ContextCompat.getColor(context, android.R.color.primary_text_dark))
editText.defaultColorState = ColorStateList.valueOf(ContextCompat.getColor(context, android.R.color.primary_text_dark))
assertThat(editText.defaultErrorColorInt)
.isEqualTo(ContextCompat.getColor(context, R.color.stripe_error_text_dark_theme))
}
Expand All @@ -104,9 +105,35 @@ internal class StripeEditTextTest {
.isEqualTo(blueError)
}

@Test
fun setTextColor() {
editText.setTextColor(
ColorStateList.valueOf(
ContextCompat.getColor(
context,
android.R.color.holo_red_dark
)
)
)

// The field state must be toggled to show an error
editText.shouldShowError = true
editText.shouldShowError = false

assertThat(editText.textColors)
.isEqualTo(
ColorStateList.valueOf(
ContextCompat.getColor(
context,
android.R.color.holo_red_dark
)
)
)
}

@Test
fun getCachedColorStateList_afterInit_returnsNotNull() {
assertThat(editText.cachedColorStateList)
assertThat(editText.defaultColorState)
.isNotNull()
}

Expand Down