On my android app, first time when app runs, user must type a license. The license's format is ###-XXX-###-### where # is a number, X is a character. I put the format as hint but it is not sufficient. How can I make like this and user does not enter -, it just appear after 3 characters ?
UPDATE :
That's my code and it works :
licenseEditText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
System.out.println("afterTextChanged");
if (s.length() == 3) {
s.append("-");
}
if (s.length() == 7) {
s.append("-");
}
if (s.length() == 11) {
s.append("-");
}
if (s.length() == 15)
ok.performClick();
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
System.out.println("beforeTextChanged");
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
System.out.println("onTextChanges");
}
});
set a TextWatcher , inside it compare intered text with a regularExpression . and put other code like after first 3 charachets append "-" to intered characterSet .
you can use 4 EditTexts and attach textwathers to them - a windows-like license input
Try to use the % operator
if( s.length() == 15) {
// s.length() = 15
} else if( s.length() % 4 == 3) {
// s.length = {3, 7, 11, 19, ....}
// so s.length != 15
}
In this way you have less code duplication. For more information check: Wikipedia - Modulo operation
Related
I made a code where user can't enter first space in a string.
User is allowed to enter white space after min 2 characters.
I need to redefine my method so user enters white space once, and only once after the two or more characters. After that it should be prevented. How do I do that?
case UPDATE_NAME:
if (firstName.getText().toString().startsWith(" "))
firstName.setText(firstName.getText().toString().trim());
if (firstName.getText().toString().contains(" "))
firstName.setText(firstName.getText().toString().replace(" ", " "));
int indexOfSpace = firstName.getText().toString().lastIndexOf(" ");
if (indexOfSpace > 0) {
String beforeSpace = firstName.getText().toString().substring(0, indexOfSpace);
String[] splitted = beforeSpace.split(" ");
if (splitted != null && splitted.length > 0) {
if (splitted[splitted.length - 1].length() < 2)
firstName.setText(firstName.getText().toString().trim());
}
}
Use a regex pattern. I made one that should match your requirements.
\S{2}\S*\s\S*\n
Explanation:
\S{2} two non whitespace
\S* n non whitespace
\s a whitespace
\S* n non whitespace
\n newline (i only added that for regexr, you may not need it)
Alternate way:
Iterate over String.charAt(int), return false if there is a whitespace in the first two chars, count all whitespaces, return false if n > 1.
This method should meet your requirements:
private static boolean isValidFirstName(String firstName) {
if (firstName != null && !firstName.startsWith(" ")) {
int numberOfSpaces = firstName.length() - firstName.replace(" ", "").length();
if (firstName.length() < 2 || numberOfSpaces <= 1) {
return true;
}
}
return false;
}
What you need to do is use a TextWatcher
public class CustomWatcher implements TextWatcher {
private String myText;
private int count = 0;
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after){
myText= s;
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
//check if there is a space in the first 2 characters, if so, sets the string to the previous before the space
if(s.length() < 3 && s.contains(" "))
s= myText;
//if the length is higher than 2, and the count is higher than 0 (1 space added already), puts the string back if a space is entered
else if(s.contains(" ") && count > 0)
s= myText;
//If none of the above is verified and you enter a space, increase count so the previous if statement can do its job
else if(s.contains(" "))
count++;
}
}
And then, set it to your EditText
mTargetEditText.addTextChangedListener(new CustomWatcher());
You can control your editText(I assume) with a TextWatcher, you would only need to check inside afterTextChanged() if length is <2 and else if the string contains the char " ".
I have an edit text in my android application and I want to avoid from the user to enter an input when the string length in bytes reaches to the limit.
It works fine in english, but not in hebrew.
The limit is 256, so when the input is in hebrew, I can insert only 128 characters. The problem is while I insert hebrew letters with punctuation.
Lets say that I insert a dot, which is 1 byte, it allows me to enter more than 128 characters , even when the characters are only hebrew letters and punctuation.
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
int length = s.toString().getBytes().length;
if (length == bytes_limit)
{
str = s.toString();
}
else if (length > bytes_limit)
{
input.setText(str);
input.setSelection(str.length());
}
}
Update:
String example: "שלום, מה שלומך"
Update 2:
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
int length = s.toString().getBytes().length;
if (length <= bytes_limit)
{
str = s.toString();
}
else if (length > bytes_limit)
{
input.setText(str);
input.setSelection(str.length());
}
}
Try specifying the charset eg
int length = s.toString().getBytes("UTF-8").length;
replacing UTF-8 with the character set that you need
See
bytes of a string in java?
And
Will String.getBytes("UTF-16") return the same result on all platforms?
Punctuations are characters too, you write them in addition to the hebrew letter you want to write (if i am not wrong, you can add them with ALT + XXXX).
They are character like any others so when you write them, you are adding characters.
A dot(.) doesn't have punctuation so it takes only one byte.
To solve it, you can remove all of the punctuatuion.
You can create a function to ignore all the punctuation:
private String removePunctuation(String s)
{
for(int i = 0; i < s.length(); i++)
{
if(!(s.charAt(i) <= 'ת' && s.charAt(i) >= 'א'))
{
s = s.substring(0,i) + s.substring(i+1);
}
}
return s;
}
note the it will delete all of the punctuation, including - and : and so on...
You can add exceptions to the condition, enabling '-' or others.
Good luck :)
I have an EditText where the user wants to enter the price. In order to maintain uniformity, I decided to automatically include the decimal values.
Hence "1" entered by user would become "1.00" for example.
Now, after working with my inefficient code, I can across a better code in StackOverFlow
amountEditText.setRawInputType(Configuration.KEYBOARD_12KEY);
amountEditText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(!s.toString().matches("^\\$(\\d{1,3}(\\,\\d{3})*|(\\d+))(\\.\\d{2})?$"))
{
String userInput= ""+s.toString().replaceAll("[^\\d]", "");
StringBuilder cashAmountBuilder = new StringBuilder(userInput);
while (cashAmountBuilder.length() > 3 && cashAmountBuilder.charAt(0) == '0') {
cashAmountBuilder.deleteCharAt(0);
}
while (cashAmountBuilder.length() < 3) {
cashAmountBuilder.insert(0, '0');
}
cashAmountBuilder.insert(cashAmountBuilder.length()-2, '.');
cashAmountBuilder.insert(0, '$');
amountEditText.setText(cashAmountBuilder.toString());
// keeps the cursor always to the right
Selection.setSelection(amountEditText.getText(), cashAmountBuilder.toString().length());
}
}
});
With the above code, the decimal value starts getting included once the user starts entering the number. But, the numerical value added by the user will be displayed with $ symbol. Hence, I made a little modification to the code in Line 07 and deleted Line 19.
The new code is
returnPrice.setRawInputType(Configuration.KEYBOARD_12KEY);
returnPrice.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(!s.toString().matches("^(\\d{1,3}(\\,\\d{3})*|(\\d+))(\\.\\d{2})?$"))
{
String userInput= ""+s.toString().replaceAll("[^\\d]", "");
StringBuilder cashAmountBuilder = new StringBuilder(userInput);
while (cashAmountBuilder.length() > 3 && cashAmountBuilder.charAt(0) == '0') {
cashAmountBuilder.deleteCharAt(0);
}
while (cashAmountBuilder.length() < 3) {
cashAmountBuilder.insert(0, '0');
}
cashAmountBuilder.insert(cashAmountBuilder.length()-2, '.');
returnPrice.setText(cashAmountBuilder.toString());
// keeps the cursor always to the right
Selection.setSelection(returnPrice.getText(), cashAmountBuilder.toString().length());
}
}
});
My Problem
So the problem I am facing in case 02 is, when I am entering the numeric value in EditText - unless I am entering the decimal dot, the numeric value in EditText gets displayed as an integer.
For example : Case 01
For displaying 100.00 as I go on typing, the value starts displaying as $0.01, then $0.10, then $1.00, $10.00 and finally $100.00. At any instance, I don't need to enter a decimal dot manually in this case.
For example : Case 02
For displaying 100.00 as I go on typing, the value starts displaying as 1, then 10, then 100. Now, if I press the decimal dot on soft keyboard, the 100 becomes 1.00 and on typing the value turns 10.00 and finally 100.00. If the decimal dot is not touched on the keyboard, the resulting value on entering 10000 is 10000 and not 100.00.
What's the error I made? Any suggestions?
Suppose when a field is loaded, its empty. When the user types 1, it says 0.01, then he types another 0 after the 1 (10) it becomes 0.10. When he types another 1, it becomes 1.10.
Just like entering the price of a product. How do I do that on Android? I'm quite stumped to be honest since I've never tried something like this. Is there some special input method for this?
Here's the code I wrote for myself:
private String addCurrencySign(String digits) {
String string = "£";
// Amount length greater than 2 means we need to add a decimal point
if (digits.length() > 2) {
String pound = digits.substring(0, digits.length() - 2); // Pound part
String pence = digits.substring(digits.length() - 2); // Pence part
string += pound + "." + pence;
} else if (digits.length() == 1) {
string += "0.0" + digits;
Log.d(TAG, "length 1 " + string);
} else if (digits.length() == 2) {
string += "0." + digits;
Log.d(TAG, "length 2 " + string);
}
return string;
}
This addCurrencySign method is triggered each time when user trying to type on the number pad. The number pad is consist of several digit buttons (just like POS handheld or calculator).
Since you don't need to build a keypad with buttons, could you try intercept the keyboard events, which is described in Handling Keyboard Actions and maybe write something like this:
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_0:
return true;
case KeyEvent.KEYCODE_1:
return true;
case KeyEvent.KEYCODE_2:
return true;
case KeyEvent.KEYCODE_3:
return true;
......
default:
return super.onKeyUp(keyCode, event);
}
}
Maybe you don't have to use switch clause, my idea is to intercept the key entering 0~9 digits and for each 0~9, call addCurrencySign method.
Use:
TextWatcher watcher = new TextWatcher(){
afterTextChanged(Editable s){}
beforeTextChanged(CharSequence s, int start, int count, int after){}
onTextChanged(CharSequence s, int start, int before, int count){}
}
yourEditText.addTextChangedListener(watcher);
Here you will find more info about TextWatcher http://developer.android.com/reference/android/text/TextWatcher.html
OK guys.. I have a temporary workaround. This can't be termed as the perfect solution but its a workaround that works well in my case.
I couldn't figure out a way to stop the stackoverflow error. My workaround? Make the EditText field take input, but display the currency output onto a TextView, and make the EditText disappear from the UI so the user can't see that he is typing just 1234 instead of 12.34.
Here is the code. The addCurrencySign function comes from #ss1271.
amountpaid.addTextChangedListener(new TextWatcher()
{
#Override public void onTextChanged(CharSequence s, int start, int before, int count)
{
amount.setText(addCurrencySign(s.toString()));
}
#Override public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
}
#Override public void afterTextChanged(Editable s)
{
}
});
Here's the function that the user posted. It works very well.
private String addCurrencySign(String digits)
{
String string = "&"; // Your currency
// Amount length greater than 2 means we need to add a decimal point
if (digits.length() > 2)
{
String pound = digits.substring(0, digits.length() - 2); // Pound
// part
String pence = digits.substring(digits.length() - 2); // Pence part
string += pound + "." + pence;
}
else if (digits.length() == 1)
{
string += "0.0" + digits;
Log.d("TextWatcher", "length 1 " + string);
}
else if (digits.length() == 2)
{
string += "0." + digits;
Log.d("TextWatcher", "length 2 " + string);
}
return string;
}
Here's the 'invisible' edittext:
<EditText
android:id="#+id/amoundpaid"
android:layout_width="1dp"
android:layout_height="1dp"
android:background="#00000000"
android:ems="10"
android:inputType="number"
android:textColor="#00ffffff" >
<requestFocus />
Here's the field that will show the output text (with currency sign and proper decimal point value):
<TextView
android:id="#+id/amount"
android:layout_width="210dp"
android:layout_height="50dp"
android:background="#80000000"
android:gravity="center|center_vertical"
android:textColor="#ffffff"
android:text=""
android:textAppearance="?android:attr/textAppearanceMedium" />
I know this is not a optimum solution, but it works. I needed the functionality and this is what I had to do to get it. If someone can fix the stackoverflow error, please post and mods will change the answer to that one (once its verified).
Stuck on this which im sure there is an easy solution to, just cannot work it out!!
I have tried decmialformat, numberformat, string.format() etc and nothing works. .
code below, i want to calculation to just show the output limited to 2 decimal places. Have spent the last 2 hours trying various methods all of which causes the app to crash when run...
Output = (Output1 / (1 -(Output2/100)))
String OutputString = String.valueOf(Output);
Num.setText(OutputString);
Try this :
String OutputString = String.format("%.2f", Output);
Num.setText(OutputString);
String.format() to make sure you only get 2 decimal places in your output.
please try this:
double Output = (Output1 / (1 -(Output2/100d)))
Num.setText(String.format("%.2f",Output));
Hope this solves your problem.
Best regards
If you want to Limit the number of Digits before and after the 'decimal_point' then you can use my solution.
private class DecimalNumberFormatTextWatcher implements TextWatcher{
int pos;
int digitsBeforeDecimal = 6;
int digitsAfterDecimal = 2;
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if(s.length() > 2)
pos = start;
else {
pos = start + 2;
}
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
mEdittext.removeTextChangedListener(this);
String text = s.toString();
if(text!= null && !text.equals("")){
if(!text.contains("$")){ //if it does not contains $
text = "$"+text;
} else {
if (text.indexOf("$") > 0) { //user entered value before $
text = s.delete(0, text.indexOf("$")).toString();
}else {
if(!text.contains(".")){ // not a fractional value
if(text.length() > digitsBeforeDecimal+1) { //cannot be more than 6 digits
text = s.delete(pos, pos+1).toString();
}
} else { //a fractional value
if(text.indexOf(".") - text.indexOf("$") > digitsBeforeDecimal+1){ //non fractional part cannot be more than 6
text = s.delete(pos,pos+1).toString();
}
if((text.length() - text.indexOf(".")) > digitsAfterDecimal+1) { //fractinal part cannot be more than 2 digits
text = s.delete(text.indexOf(".") + 2, text.length() - 1).toString();
}
}
}
}
}
mEdittext.setText(text);
mEdittext.setSelection(pos);
mEdittext.addTextChangedListener(this);
}
}
mEdittext.addTextChangedListener(new DecimalNumberFormatTextWatcher());
This also adds a currency sign as soon as the user types the value.
HOPE THIS HELPS ANYONE.