From 9a1f9b2954f762395d998eb8cbab9263df864fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?ibrahim=20s=C3=BCren?= Date: Wed, 30 Sep 2020 23:46:22 +0300 Subject: [PATCH] update number formatting --- .../ibrahimsn/phonenumberkit/MainActivity.kt | 2 - .../main/java/me/ibrahimsn/lib/Constants.kt | 8 ++ .../java/me/ibrahimsn/lib/PhoneNumberKit.kt | 79 +++++++++++++------ .../main/java/me/ibrahimsn/lib/core/Core.kt | 4 +- .../java/me/ibrahimsn/lib/util/Extensions.kt | 6 +- .../lib/util/PhoneNumberTextWatcher.kt | 4 +- 6 files changed, 73 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/me/ibrahimsn/phonenumberkit/MainActivity.kt b/app/src/main/java/me/ibrahimsn/phonenumberkit/MainActivity.kt index de945f6..8a4c8fd 100644 --- a/app/src/main/java/me/ibrahimsn/phonenumberkit/MainActivity.kt +++ b/app/src/main/java/me/ibrahimsn/phonenumberkit/MainActivity.kt @@ -39,7 +39,5 @@ class MainActivity : AppCompatActivity() { // Provides country name, iso2 for given country code val country = phoneNumberKit.getCountry(90) - - editText.setText("+905066840880") } } \ No newline at end of file diff --git a/lib/src/main/java/me/ibrahimsn/lib/Constants.kt b/lib/src/main/java/me/ibrahimsn/lib/Constants.kt index c6fe6d4..6f65dc6 100644 --- a/lib/src/main/java/me/ibrahimsn/lib/Constants.kt +++ b/lib/src/main/java/me/ibrahimsn/lib/Constants.kt @@ -3,4 +3,12 @@ package me.ibrahimsn.lib object Constants { const val VIEW_TAG = "#" + + const val KEY_DIGIT = '0' + const val KEY_SPACE = '1' + const val KEY_DASH = '-' + + const val CHAR_SPACE = ' ' + const val CHAR_DASH = '-' + const val CHAR_PLUS = '+' } diff --git a/lib/src/main/java/me/ibrahimsn/lib/PhoneNumberKit.kt b/lib/src/main/java/me/ibrahimsn/lib/PhoneNumberKit.kt index d40a342..69d3c32 100644 --- a/lib/src/main/java/me/ibrahimsn/lib/PhoneNumberKit.kt +++ b/lib/src/main/java/me/ibrahimsn/lib/PhoneNumberKit.kt @@ -7,12 +7,16 @@ import android.text.InputType import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import com.google.android.material.textfield.TextInputLayout +import me.ibrahimsn.lib.Constants.CHAR_DASH +import me.ibrahimsn.lib.Constants.CHAR_PLUS +import me.ibrahimsn.lib.Constants.CHAR_SPACE +import me.ibrahimsn.lib.Constants.KEY_DASH +import me.ibrahimsn.lib.Constants.KEY_DIGIT +import me.ibrahimsn.lib.Constants.KEY_SPACE import me.ibrahimsn.lib.bottomsheet.CountryPickerBottomSheet import me.ibrahimsn.lib.core.Core import me.ibrahimsn.lib.util.PhoneNumberTextWatcher -import me.ibrahimsn.lib.util.PhoneNumberValidator import me.ibrahimsn.lib.util.prependPlus -import me.ibrahimsn.lib.util.startsWithPlus class PhoneNumberKit(private val context: Context) { @@ -22,39 +26,60 @@ class PhoneNumberKit(private val context: Context) { private var country: Country? = null - private var rawInput: String? - get() = input?.editText?.text?.toString() + private var format: String = "" + + private var hasManualCountry = false + + private var rawInput: CharSequence? + get() = input?.editText?.text set(value) { input?.tag = Constants.VIEW_TAG - input?.editText?.setText(value) - value?.let { - input?.editText?.setSelection(value.length) - } + input?.editText?.setText("") + input?.editText?.append(value) input?.tag = null } - val isValid: Boolean - get() = PhoneNumberValidator.validate(rawInput) - private val textWatcher = object: PhoneNumberTextWatcher() { - override fun onTextChanged(text: CharSequence?, p1: Int, p2: Int, p3: Int) { - if (input?.tag != Constants.VIEW_TAG) { - if (!text.isNullOrEmpty() && !text.startsWithPlus()) { - rawInput = text.prependPlus() - } - val parsedNumber = core.parsePhoneNumber(rawInput, country?.iso2) + override fun onTextChanged(text: CharSequence?, start: Int, before: Int, count: Int) { + if (input?.tag != Constants.VIEW_TAG) { + val parsedNumber = core.parsePhoneNumber(rawInput.toString(), country?.iso2) // Update country flag and mask if detected as a different one if (country == null || country?.countryCode != parsedNumber?.countryCode) { - setCountry(getCountry(parsedNumber?.countryCode)) + if (!hasManualCountry) { + setCountry(getCountry(parsedNumber?.countryCode)) + } + } + + if (count != 0) { + applyFormat() } + } + } + } + + private fun applyFormat() { + rawInput?.let { raw -> + val pureNumber = raw.filter { i -> i.isDigit() }.toMutableList() + + pureNumber.add(0, CHAR_PLUS) - // Update input text as formatted phone number - core.formatPhoneNumber(parsedNumber)?.let { number -> - rawInput = number + for (i in format.indices) { + if (pureNumber.size > i) { + if (format[i] == KEY_SPACE && pureNumber[i] != CHAR_SPACE) { + pureNumber.add(i, CHAR_SPACE) + continue + } + + if (format[i] == KEY_DASH && pureNumber[i] != CHAR_DASH) { + pureNumber.add(i, CHAR_DASH) + continue + } } } + + rawInput = pureNumber.joinToString("") } } @@ -65,6 +90,7 @@ class PhoneNumberKit(private val context: Context) { // Clear input if a country code selected manually if (isManual) { rawInput = country.countryCode.prependPlus() + hasManualCountry = true } // Setup country icon @@ -75,10 +101,18 @@ class PhoneNumberKit(private val context: Context) { // Set text length limit according to the example phone number core.formatPhoneNumber(core.getExampleNumber(country.iso2))?.let { number -> input?.editText?.filters = arrayOf(InputFilter.LengthFilter(number.length)) + format = createNumberFormat(number) + applyFormat() } } } + private fun createNumberFormat(number: String): String { + var format = number.replace("(\\d)".toRegex(), KEY_DIGIT.toString()) + format = format.replace("(\\s)".toRegex(), KEY_SPACE.toString()) + return format + } + /** * Attaches to textInputLayout */ @@ -92,7 +126,8 @@ class PhoneNumberKit(private val context: Context) { input.setStartIconTintList(null) // Set initial country - setCountry(getCountry(defaultCountry) ?: Countries.list[0], true) + setCountry(getCountry(defaultCountry) ?: Countries.list[0]) + rawInput = country?.countryCode?.prependPlus() } /** diff --git a/lib/src/main/java/me/ibrahimsn/lib/core/Core.kt b/lib/src/main/java/me/ibrahimsn/lib/core/Core.kt index f14230b..5e661c6 100644 --- a/lib/src/main/java/me/ibrahimsn/lib/core/Core.kt +++ b/lib/src/main/java/me/ibrahimsn/lib/core/Core.kt @@ -3,6 +3,8 @@ package me.ibrahimsn.lib.core import com.google.i18n.phonenumbers.NumberParseException import com.google.i18n.phonenumbers.PhoneNumberUtil import com.google.i18n.phonenumbers.Phonenumber +import me.ibrahimsn.lib.util.prependPlus +import me.ibrahimsn.lib.util.startsWithPlus import java.util.* class Core { @@ -15,7 +17,7 @@ class Core { ): Phonenumber.PhoneNumber? { return try { phoneUtil.parseAndKeepRawInput( - number, + if (number.startsWithPlus()) number else number.prependPlus(), defaultRegion?.toUpperCase(Locale.ROOT) ) } catch(e: NumberParseException) { diff --git a/lib/src/main/java/me/ibrahimsn/lib/util/Extensions.kt b/lib/src/main/java/me/ibrahimsn/lib/util/Extensions.kt index 8e6b956..9c3c3ad 100644 --- a/lib/src/main/java/me/ibrahimsn/lib/util/Extensions.kt +++ b/lib/src/main/java/me/ibrahimsn/lib/util/Extensions.kt @@ -1,6 +1,6 @@ package me.ibrahimsn.lib.util -fun CharSequence.prependPlus(): String { +fun CharSequence?.prependPlus(): String { return StringBuilder() .append("+") .append(this) @@ -14,6 +14,6 @@ fun Int.prependPlus(): String { .toString() } -fun CharSequence.startsWithPlus(): Boolean { - return this.startsWith("+") +fun CharSequence?.startsWithPlus(): Boolean { + return this?.startsWith("+") == true } diff --git a/lib/src/main/java/me/ibrahimsn/lib/util/PhoneNumberTextWatcher.kt b/lib/src/main/java/me/ibrahimsn/lib/util/PhoneNumberTextWatcher.kt index cb38992..0aea1bc 100644 --- a/lib/src/main/java/me/ibrahimsn/lib/util/PhoneNumberTextWatcher.kt +++ b/lib/src/main/java/me/ibrahimsn/lib/util/PhoneNumberTextWatcher.kt @@ -5,11 +5,11 @@ import android.text.TextWatcher abstract class PhoneNumberTextWatcher : TextWatcher { - override fun afterTextChanged(text: Editable?) { + override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { // no-op } - override fun beforeTextChanged(text: CharSequence?, p1: Int, p2: Int, p3: Int) { + override fun afterTextChanged(text: Editable?) { // no-op } }