Set Button enabled if Regex phone number is valid Android - android

How to enable a button if regex expression is valid for number ,
here is my code in ViewModel
private val changeButtonAvailable = MutableLiveData(false)
fun changeNumbers() {
val regex = "(\\+7|8)[0-9]{10}".toRegex()
if (regex.pattern.length == NUMBER_LENGTH){
changeButtonAvailable.value = true
}
changeButtonAvailable.value = true
}
fun formatNumber(mobile: String): String {
val regex = "(\\+7|8)[0-9]{10}"
val pattern = Pattern.compile(regex)
val matcher = pattern.matcher(mobile)
return if (matcher.matches()) {
val firstNumber = matcher.group(1)
changeButtonAvailable.value = firstNumber?.length == NUMBER_LENGTH
"$firstNumber"
} else {
mobile
}
}
I want make Request +7999999999 not like +7 999 999 999 99
how to make Enable button ? above methods not working for me. thank advance

You should use this regex instead "+7[0-9]{9}". The prefix number is excluded from the count that you mention. Removed the extra slash and 8 length option. You can find appropriate screenshot attached here that verifies this.
You can use this website for testing regex. https://regex101.com/

Related

How to input a decimal number in a textEdit

I have a TextEdit that has the input type of numberDecimal and I executes some code with inputted number
when I enter a whole number it works fine but when I enter a number with a decimal point the app completely restarts
So how would I make it work with a decimal number?
if you do end up helping me thank you in advanced
KT file
class f_to_c : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.f_to_c)
val actionBar = supportActionBar
val calculate = findViewById<Button>(R.id.calculate)
val tempEntered = findViewById<TextView>(R.id.tempEntered)
val result = findViewById<TextView>(R.id.result)
val temp = findViewById<EditText>(R.id.temp)
if (actionBar != null){
actionBar.title = "Fahrenheit To Celsius"
actionBar.setDisplayHomeAsUpEnabled(true)
}
calculate.setOnClickListener {
var x = Integer.parseInt(temp.getText().toString()).toString().toInt()
tempEntered.text = x.toDouble().toString()
result.text = ((x-32).toFloat()*5/9).toString()
}
}
}
If you want to handle decimal numbers, you shouldn't use Integer.parseInt. That will throw an error on something like "1.23". The following should work (or you could use Double.parseDouble)
val x = temp.getText().toString().toDoubleOrNull() ?: 0.0
tempEntered.text = x.toString()
result.text = ((x-32.0)*5.0/9.0).toString()
You may want to handle the null case differently in case the user enters an invalid number like "1..3", but this would just default to 0 in that case instead of throwing.
Also, if this is to be used internationally, you should consider that some locales use a comma for a decimal separator ("1,23") - which will break here. You could either use a locale-aware number parser for that, or just replace commas with periods before converting.
val xs = temp.getText().toString().replace(",",".")
val x = xs.toDoubleOrNull() ?: 0.0

split string between 2 char based index

How can we split a text between two char in Kotlin?
Example string:
base_id:94, user_id: 320903, is_Active=1
I want to get only user_id so "320903". But I couldn't do that.
One way to get it is using regex and you can customize it to cover base_id and is_Active
val pattern = Pattern.compile("user_id: (?<id>[0-9]+)")
val matcher = pattern.matcher(text)
if (matcher.find()) {
val group = matcher.group("id").trim()
println(group)
}
The output will be : 320903
Or you can do that with split only and you will get the same result
val items = text.split(",")
val userId = items[1].split(":")[1].trim()
println(userId)
That will work correctly with your example but make sure but for other cases, you may need to customize it or give us many examples to cover them
You can handle the 3 values with one function that support optional whitespace and : or =
fun getValueByTagName(text : String, tag : String) : String {
val pattern = Pattern.compile("$tag[:=][ ]*(?<id>[0-9]+)")
val matcher = pattern.matcher(text)
return if (matcher.find())
matcher.group("id").trim()
else ""
}
To use it
println(getValueByTagName(text, "base_id")) // 94
println(getValueByTagName(text, "user_id")) // 320903
println(getValueByTagName(text, "is_Active")) // 1
Another solution:
Method 1: If your string has exactly the same format that you have shown in the example.
val indexOfUserId = s.indexOf("user_id") // find index of the substring "user_id"
val end = s.indexOf(',', indexOfUserId) // find index of ',' after user_id
val userId s.substring(indexOfUserId + 9, end) // take the substring assuming that userId starts exactly 9 characters after the "u" in "user_id"
Method 2: If your format can vary (in spaces and symbols). Also assuming that user_id is always a number.
val indexOfUserId = s.indexOf("user_id")
val start = s.findAnyOf(List(10) { "$it" }, indexOfUserId)!!.first // find the first digit after "user_id"
val userId = s.substring(start).takeWhile { it.isDigit() } // start from the first digit and continue as long as you are getting digits
Here, List(10) { "$it" } is just a list of all digits in string format and findAnyOf:
Finds the first occurrence of any of the specified [strings] in this char sequence, starting from the specified [startIndex]
Try it yourself

Kotlin how to format Double number to String without zero after comma

Suppose I have Double number which I want to convert to String.
I want to have an option which based on that I would have String number without trailing zeroes.
So for example:
option with trailing zeros 123.00 -> "123,00", 123.324 -> "123,32"
option without trailing zeroes 123.00 -> "123", 123.324 -> "123,32"
Is there a nice way to do this in Kotlin?
This is code which I have which I feel is rather ugly:
private const val VALUE_DIVIDER = 100
private const val DIGITS_AMOUNT = 2
private val defaultLocale = Locale("us")
private val currency = "$"
private val cents = 10000
fun print(withoutTrailingZeros: Boolean = true): String {
val price = (cents.toDouble() / VALUE_DIVIDER)
.valueToString()
.let { if (withoutTrailingZeros) it.removeSuffix(",00") else it }
return "$price $currency"
}
private fun Double.valueToString() = round(DIGITS_AMOUNT).replace(".", ",")
private fun Double.round(digits: Int): String =
NumberFormat.getInstance(defaultLocale).apply {
maximumFractionDigits = digits
minimumFractionDigits = digits
isGroupingUsed = false
}.format(this)
UPDATE: The solution provided by #Roma Pochanin works partially, but strangely only as jUnit tests.
After I am running integration tests on Android emulator using this logic this is not working for 0 (it is formatted as "0,00" even when the withoutTrailingZeros flag is true). I heard about some bug related to that Why does new BigDecimal("0.0").stripTrailingZeros() have a scale of 1?
but how it is connected with my case? Can anyone explain?
Please, see the exact sessions from debugger:
working, as jUnit tests: https://ibb.co/HN9n41T
bug, when running instrumentation tests on Android emulator: https://ibb.co/VCrmrMh
There is no function for that in the Kotlin standard library, but you can specify the number of decimal places and the decimal format symbol using Java's DecimalFormat:
val formatSymbols = DecimalFormatSymbols.getInstance().apply {
decimalSeparator = ','
}
val twoDecimalDigitsFormat = DecimalFormat("#.##").apply {
decimalFormatSymbols = formatSymbols
}
val twoTrailingZerosFormat = DecimalFormat("#.00").apply {
decimalFormatSymbols = formatSymbols
}
fun formatPrice(price: Double, withDecimalZeros: Boolean) = if (withDecimalZeros) {
twoTrailingZerosFormat
} else {
// Is number still the same after discarding places?
if (price.toInt().toDouble() == price) {
twoDecimalDigitsFormat
} else {
twoTrailingZerosFormat
}
}.format(price)
println(formatPrice(123.00, true)) // 123,00
println(formatPrice(123.324, true)) // 132,32
println(formatPrice(123.00, false)) // 123
println(formatPrice(123.324, false)) // 123,32
Why don't you use BigDecimal? It's like the default way to deal with prices and similar stuff. You also can consider using BigDecimal's method stripTrailingZeros:
private const val VALUE_DIVIDER = 100
private const val DIGITS_AMOUNT = 2
private val currency = "$"
private val cents = 1298379
fun formatPrice(withoutDecimalZeros: Boolean = true) =
BigDecimal(cents)
.divide(BigDecimal(VALUE_DIVIDER), DIGITS_AMOUNT, RoundingMode.UP)
.let { if (withoutDecimalZeros) it.stripTrailingZeros() else it }
.toString().replace(".", ",")
.let { "$it $currency" }

Android implement text completion on swipe

How can I implement text completion,Like Gmail's smart compose?
I've an edit text where the user enters server address and I want to detect when they start typing the domain suffix and suggest completion.
Thanks.
First you need an algorithm to get suggestion from a given dictionary.
I've created a simple class named SuggestionManager to get suggestion from a given dictionary for a string input. Instead of returning the full match, it'll only return the remaining part of the given input. Below given a simple unit test along with full source code of the class. You can also go here to run the test online.
SuggestionManager.kt
class SuggestionManager(private val dictionary: Array<String>) {
companion object {
private val WORD_SPLIT_REGEX = Regex("[^A-Za-z0-9'\\-]")
/**
* To get reversed list
*/
private fun getReversedList(list: List<String>): MutableSet<String> {
val reversed = mutableSetOf<String>()
for (item in list.withIndex()) {
if (item.index != 0) {
val rev = list.subList(list.size - item.index, list.size).joinToString(" ")
reversed.add(rev)
}
}
// finally, add the full string
reversed.add(list.joinToString(" "))
return reversed
}
}
fun getSuggestionFor(_text: String?): String? {
var text = _text
// empty text
if (text.isNullOrBlank()) {
return null
}
// Getting last line only
if (text.contains("\n")) {
text = text.split("\n").last()
if (text.trim().isEmpty()) {
return null
}
}
// Splitting words by space
val words = text.split(WORD_SPLIT_REGEX).filter { it.isNotBlank() }
// Getting last word
val lastWord = if (text.endsWith(" ")) "${words.last()} " else words.last()
// Matching if last word exist in any dictionary
val suggestions = mutableSetOf<String>()
for (dicItem in dictionary) {
if (dicItem.contains(lastWord, true)) {
// Storing founded matches
suggestions.add(dicItem)
}
}
// Reverse ordering split-ed words
val pyramidWords = getReversedList(words)
val matchList = mutableListOf<String>()
for (pw in pyramidWords) {
for (sug in suggestions) {
// Storing suggestions starts with reversed word
if (sug.startsWith(pw, true)) {
matchList.add("$pw:$sug")
}
}
}
// Checking if second level match is not empty
if (matchList.isNotEmpty()) {
// Ordering by matched reversed word - (largest key first)
matchList.sortBy { -it.split(":")[0].length }
// Looping through in ascending order
for (m in matchList) {
val match = m.split(":")
val selPw: String = match[0]
var selSug: String = match.subList(1, match.size).joinToString(":")
// trimming to
selSug = selSug.replace(selPw, "", true)
if (text.endsWith(" ")) {
selSug = selSug.trim()
}
return selSug
}
}
return null
}
}
Unit Test
class SuggestionManagerUrlTest {
private val suggestionManager by lazy {
val dictionary = arrayOf(
"google.com",
"facebook.com",
"gmail.com",
"yahoo.com",
"192.168.354.45"
)
SuggestionManager(dictionary)
}
#Test
fun test() {
// null of empty and null input
assertNull(suggestionManager.getSuggestionFor(null))
assertNull(suggestionManager.getSuggestionFor(""))
// matching
assertEquals("ogle.com", suggestionManager.getSuggestionFor("go"))
assertEquals("book.com", suggestionManager.getSuggestionFor("face"))
assertEquals(".168.354.45", suggestionManager.getSuggestionFor("192"))
// no match
assertNull(suggestionManager.getSuggestionFor("somesite"))
}
}
Then, you'll have to set text in EditText with two colors. One for input and other for the suggestion. You may use the Html.fromHtml method to do this.
val text = "<font color=#cc0029>$input</font> <font color=#ffcc00>$suggestion</font>";
yourEditText.setText(Html.fromHtml(text));
Combining these two aspects, you can create a custom EditText.

how to sort string that contains number in kotlin

I have a model that contains some field. I wanna sort this model before a show in recycler by sorted title. my title contains number into a string in some part like session 1 - episode 22. I use this algorithm for sort number in string type with two-digits like episode 22.
sortData.toObservable()
.sorted { o1, o2 ->
val pattern = Pattern.compile("\\d+")
val matcher = pattern.matcher(o1.title)
val matcher2 = pattern.matcher(o2.title)
if (matcher.find()) {
val isFind = matcher2.find()
val o1Num = matcher.group(0).toInt()
val o2Num = if (isFind) {
matcher2.group(0).toInt()
} else {
o1Num + 1
}
return#sorted o1Num - o2Num
} else {
return#sorted o1.title?.compareTo(o2.title ?: "") ?: 0
}
}
.toList()
.subscribeBy(
onError = {
it
},
onSuccess = {
sortData = it
}
)
my problem with this algorithm is when my title contains just simple format like episode 22 and just digits are between 0-99 it's work good but when I have a title that in this format: session 1 - episode 22 and digits are between 0-999 this algorithm won't work and I haven't any sort in my recycler. may please help me for fix this?
I found the solution :)
I must replace the first part with whitespace. then we can get the second part number from string and convert it to int and sort it.
val matcher = pattern.matcher(o1.title?.replace("session 1", ""))
val matcher2 = pattern.matcher(o2.title?.replace("session 1", ""))

Categories

Resources