Regex to split string in kotlin - android

I want to group strings based on character.
For eg. I want to split following url in two groups
group 1 - /viewarticle/abd-fdj-gfg-to
group2 - 628882 (last string)
/viewarticle/abd-fdj-gfg-to-628882
I tried this " -(?!.*-) " but it is not working.
I have to use only regex not split function.
Any help would be appreciated.

You can simply use groups () with .*- to capture the first input and the rest as second so use:
(.*-)([a-zA-Z\\d]+)
Demo
val regex = "(.*-)([a-zA-Z\\d]+)".toRegex() // use only (\\d+) for digits
val matchResults = regex.find("/viewarticle/abd-fdj-gfg-to-628882")!!
val (link, id) = matchResults.destructured
println("Link: $link \nID: $id")
Details:
.*- : match anything till last -
[a-zA-Z\\d]+ : match 0 or more characters a-zA-Z or digits

You may try splitting using a lookbehind, e.g. split on:
(?<=-to)-
You could also make the lookbehind more specific:
(?<=abd-fdj-gfg-to)-
But this would only make sense if what precedes -to would always be the same.
Edit:
If you need to split on the last hyphen, then use the negative lookahead:
-(?!.*-)

Related

How could I add or substract Two EditTex Values currency formatted with a TextWatcher?

I want to calculate user repayment capacity by subtracting users input from two formatted and text-watched editTexts. However, I'm getting this error:
java.lang.NumberFormatException: For input string: "100,000.0"
I used https://github.com/BlacKCaT27/CurrencyEditText and https://github.com/zihadrizkyef/TextWatcherForMoney with no success. Here's my code:
ingresos.addTextChangedListener(CurrencyTextWatcher(ingresosEditText))
val IngresosNetos =
(ingresos.text.toString().toInt() - egresos.text.toString().toInt())
val formatear = NumberFormat.getCurrencyInstance().format(IngresosNetos)
val formateados = "$formatear"
capacidadpagotv.text = formateados
Any help would be appreciated. Thanks.
The standard way for number parsing as far as i know, is '.' for decimals, and no "," for separating the thousands/millions, etc. Because of this, your strings can't be parsed to a valid numerical value.
By loooking at the library you are using, they provide a getRawValue() for
Providing back the raw numeric values as they were input by the user, and should be treated as if it were a whole value of the users local currency. For example, if the text of the field is $13.37, this method will return a Long with a value of 1337, as penny is the lowest denomination for USD.
My advice would be to use this instead of your current approach since handling different locale/standard where '.' and ',' shift around is very hard to accomplish reliably.
Edit: The library's MavenCentral repo seems to be missing, so you should use the jitpack one.
maven { url "https://jitpack.io" }
and
implementation 'com.github.BlacKCaT27:CurrencyEditText:2.0.2'
This works for me
<com.blackcat.currencyedittext.CurrencyEditText
android:id="#+id/myCurrency"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
val curencyValue = binding.myCurrency.rawValue // returns a long
and to then set the value, use the formatCurrency from the same library.
binding.myCurrency.formatCurrency(curencyValue.toString())

How to pass multiple delimiters to a substring (Kotlin/Android)?

I'm trying to make a calculator app, and I need to be able to get the last value after someone presses an operator (+,*,-,/) after the second time (the first value is saved with no issues since it's the only number on the screen).
So if the top of the screen has something like (222 * 3333 / 12), I need to get 12. Once I learn how to do this, I can figure out how to save the previous number/sum, then do calculations on the next number (I haven't made that part yet though).
I know this is a janky way of doing things, and any suggestions are appreciated.
So I can grab this number if I use substringAfterLast() and insert an operator there, however, if mix things up and use multiple operators (like 222 * 3333 / 12), my y variable (see below) just shows "222 * 3333 / 12" instead of 12.
How can I use multiple delimiters for substring?
Here's my code by the way (forgive me)
multiplybutton.setOnClickListener {
var x = numbersEntered.toString()
var y = ""
//creates an array that holds the operators so it can be easily filtered out
val operators = arrayOf<Char>('*','/','+','-')
//prevents app from crashing by saving the last value before the operator is added, allowing us to create infinite number of operations
if (x.any(operators :: contains)){
// x.split(operators.toString())
y = x.substringAfterLast('*') // can't use my operator character array here? why? how do I iterate through it?
Toast.makeText(this, y.toString(), Toast.LENGTH_SHORT).show()
// previousvalue = y.toInt()
} else {
previousvalue = x.toInt()
}
numbersEntered.append("*")
numbersEnteredBox.setText(numbersEntered.toString())
isMultiply = true;
Toast.makeText(this, previousvalue.toString(), Toast.LENGTH_SHORT).show()
}
edit: ignore italics plz, not sure what went wrong
sorry, maybe I not fully understand what you want to do but you can use split function to get last number from string like this 222 * 3333 / 12:
println("222 * 3333 / 12".split('+', '-', '*', '/').last().trim().toInt())
// prints 12
Use split with a regular expression
Using a regular expression gives you a great deal of control over how the string is split. In your case, anything that isn't a numeric digit is probably a delimiter. Regex has a built-in character class, denoted by \D, that will match any character that isn't a digit.
val pattern = Regex("""\D+""") // matches one or more non-digit characters
"1 * 2 / 3".split(pattern).last() // returns "3"
Equally, you could create your own character class, using [], to be more specific about which characters you want to use as delimiters:
val pattern = Regex("""\s*[-\+*]\s*""") // matches -\+*, and any spaces around them
"1 * 2 / 3".split(pattern).last() // returns "3"

Adding mask and thousand delimeter to EditText

I need to put currency at the start of text and this text should be divide thousands by dots. Now I am using MaskedTextChangedListener from this library, so my code is following:
val listener = MaskedTextChangedListener(
"[000].[000].[000]",
true,monthlyInstallment.editText!!, null,null)
listener.rightToLeft = true
monthlyInstallment.editText?.addTextChangedListener(listener)
Here you can see that I added mask and used rightToLeft value in order to divide amount by dots. The problem is that if I will put currency to the start of mask like $[000].[000].[000], the currency appears only after I will fill all the mask, whereas I need to appear it when I will start typing.
Also I tried to put logic for adding currency in other TextChangeListener. My code is following
if(!monthlyInstallment.editText?.text.toString().startsWith("$ ")){
monthlyInstallment.editText?.setText("$ " + monthlyInstallment.editText?.text.toString())
Logger.msg("check " + monthlyInstallment.editText?.text.toString().length)
}
monthlyInstallment.editText?.setSelection(monthlyInstallment.editText?.text.toString().length)
Here problem is that my cursor is set somewhere, but not at the end of text. By the way, this code is placed into afterTextChangedListener method.
So can someone help me with one of the problem?

String is read as number rather than reading it digit by digit when talk back is on in android

I have a string "9039662543", and when talk back is on, this string is read as "nine million...." in 4.3 android devices, above 4.3 devices its working fine, by reading "nine zero three...". What should I do to fix this?
I'm assuming this is a phone number? I can't tell because there is no formatting. Which is the heart of the problem. There are multiple fixes for this.
A: Leave it alone. TalkBack users have the option of parsing elements by view, paragraph, sentence, word, character, etc. If a user can't tell it's a phone number by the context, you need more context. The number itself is fine!
B: Format it better. (903)-966-2542 vs 9039662543, without any additional context, are two different pieces of information. It may still read out as something like "Parentheses nine-hundread and three........" but it will be more obvious it is a phone number, and the chunks are easy to keep track of. Sorry I dno't have a pre 4.3 device to check out what the actual announcement is.
C: Override the content description. If the text representation is:
Text: 9039662543
Content Description: 9 0 3 9 6 6 2 5 4 3
I recommend against this approach. These two values are not the same. Just because you are uncomfortable with the announcement doesn't mean a TalkBack user would be. As you get accustomed to using TalkBack you get accustom to switching to different text parsing modes. A user who doesn't care about the phone number would be frustrated by the slower read out of the separated version. Leave them the option of ignoring it, and having it blow by quickly in the more compressed form. Also, informatively, if there is no context those two numbers don't really represent the same thing. The solution in this case is provide this context NOT to change the presentation. Separate is NOT equal.
For EditText, add a space between characters and set this text in Accessibility Node Info.
ViewCompat.setAccessibilityDelegate(editText,object : AccessibilityDelegateCompat(){
override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) {
super.onInitializeAccessibilityNodeInfo(host, info)
info.text = editText.text.toString().replace(".".toRegex(),"$0 ")
}
})
While I see multiple people recommending what ChrisCM has posted. I see that the default contacts application does this differently.
The default contact application reads the phone number digit-by-digit. It also does a little more than that and it can be reused. The API that is used is:
https://developer.android.com/reference/android/telephony/PhoneNumberUtils.html#createTtsSpan(java.lang.String)
The details of how it works could be found here :
https://android.googlesource.com/platform/frameworks/base/+/master/telephony/java/android/telephony/PhoneNumberUtils.java
//add extra space to text and set that text as contentDescription
textView.setText(readbleText);
StringBuilder builder = new StringBuilder();
for (int i = 0; i < readbleText.length(); i++) {
builder.append(readbleText.charAt(i));
builder.append("\u00A0");
}
textView.setContentDescription(builder);
Make sure the input type on the edittext is phone and not number:
android:inputType="phone"
and not:
android:inputType="number"
I know it's already answered but inspired by this answer
I wrote an extension function for textView (in Kotlin of course ) which can be re-used as a utility function overall by those who might have this problem.
fun TextView.separateText() {
val textView = this
ViewCompat.setAccessibilityDelegate(textView, object : AccessibilityDelegateCompat() {
override fun onInitializeAccessibilityNodeInfo(
host: View,
info: AccessibilityNodeInfoCompat
) {
super.onInitializeAccessibilityNodeInfo(host, info)
info.text = textView.text.toString().replace(".".toRegex(), "$0 ")
}
})
}
PS: I was not able to post this under his/her answer, because I do not enough reputation.
You can add zero-width non-breaking space characters "\ufeff" to separate the numbers invisibly. It will read the number as digits. Do refer the comment in the below link for more details
How to change Android Talkback in case of App name

String to text field in android app

I have the following data scanned from a pdf417 and need to extract certain text to certain text fields (already created), not sure how to go about this... Data scanned with manatee works plugin and android app using android studio.
All help will be appreciated.
Data that was returned from scan -
%MVL1CC18%0154%4025M003%4025012RP01C%DC62XBGP%NISSAN%SILVER/SILWER%
Each part between the %'s need to go to a text field. I know that I need to make use of String substr=mysourcestring.substring(startIndex,endIndex); but this will work up to the first 2 % signs. How do I continue to the next few?
Thanks.
If you want to split string based on a delimiter, use the following
String delimitter="%";
String[] parts = inputString.split(delimitter);
Why not use String.split()?
In your case it would look something like this:
String[] extractedStrings = mysourcestring.split("%");
You can work on your string by using split method:
String yourString = "%MVL1CC18%0154%4025M003%4025012RP01C%DC62XBGP%NISSAN%SILVER/SILWER%";
String[] split = yourString.split("%");
In this way you will get an array where each item is a substring between two % chars.

Categories

Resources