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 " ".
Related
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 :)
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.
I have an AutoCompleteTextView in my app. The app makes use of the Facebook SDK. I followed the code from this question on SO: https://stackoverflow.com/a/12363961/450534 to the dot and have a functioning search (filtering) activity.
Now, how do I get an inline Autocomplete like the Facebook App after the # symbol is typed and still hold the other text typed by the user? The activity in question is for a Status Update and can contain the user's Friends along with other text. The AutoCompleteTextView or the EditText will naturally be a multi-line one. For a status update you see.
I know for the lack of any code in this post, I risk getting downvoted or perhaps even having the question closed. But it's really a standard boiler plate list filtering code.
EDIT: The FriendCaster app for Android also does the same.
First make your EditText into a MultiAutoCompleteTextView. A MultiAutoCompleteTextView allows you to replace certain parts of the text, for example text after '#'.
The you can do something like this:
final MultiAutoCompleteTextView inputEditText = (MultiAutoCompleteTextView) dialog.findViewById(R.id.MyEditText);
String[] COUNTRIES = new String[] { "Belgium", "France", "Italy", "Germany", "Spain" };
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, COUNTRIES);
inputEditText.setAdapter(adapter);
inputEditText.setThreshold(1); //Set number of characters before the dropdown should be shown
//Create a new Tokenizer which will get text after '#' and terminate on ' '
inputEditText.setTokenizer(new Tokenizer() {
#Override
public CharSequence terminateToken(CharSequence text) {
int i = text.length();
while (i > 0 && text.charAt(i - 1) == ' ') {
i--;
}
if (i > 0 && text.charAt(i - 1) == ' ') {
return text;
} else {
if (text instanceof Spanned) {
SpannableString sp = new SpannableString(text + " ");
TextUtils.copySpansFrom((Spanned) text, 0, text.length(), Object.class, sp, 0);
return sp;
} else {
return text + " ";
}
}
}
#Override
public int findTokenStart(CharSequence text, int cursor) {
int i = cursor;
while (i > 0 && text.charAt(i - 1) != '#') {
i--;
}
//Check if token really started with #, else we don't have a valid token
if (i < 1 || text.charAt(i - 1) != '#') {
return cursor;
}
return i;
}
#Override
public int findTokenEnd(CharSequence text, int cursor) {
int i = cursor;
int len = text.length();
while (i < len) {
if (text.charAt(i) == ' ') {
return i;
} else {
i++;
}
}
return len;
}
});
One "problem" with this is that the popup will appear under the EditText view. To move it up and place it under the text that is currently written you can do something like this:
inputEditText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Layout layout = inputEditText.getLayout();
int pos = inputEditText.getSelectionStart();
int line = layout.getLineForOffset(pos);
int baseline = layout.getLineBaseline(line);
int bottom = inputEditText.getHeight();
inputEditText.setDropDownVerticalOffset(baseline - bottom);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
Note: This does not currently take care of the dropdown position in the case that there are more lines in the edittext than the edittext can show.
https://github.com/dhaval001/linkable_text_view.git
Simple way to create link text, such as #username or #hashtag, in Android TextView and EditText with multiautocomplete textview. link facebook and instagram
Features
Match single strings or regex pattern to set links
Change the color of the linked text
Set the style of the linked text: BOLD, ITALIC, or BOLD_ITALIC
Set the underlined of the linked text
Specify click actions of a specific word
OnTextChangedListener listener for LinkableEditText
I try to add an event handle to a EditText object (a text area the use can edit) in my Android App to control what the use can edit or not.
Say I have this text in my EditText:
* Hello
* World
* On You...
I will attach a controller that allows the user to only edit the Hello, World or On You, and if the user try to edit or remove the * and the first space after * the system will stop the edit.
On Java SE I can use Document.remove(int, int) for getting event while an user try to remove or replace a part of the text and then stop the edit.
Is there a similar API for android EditText?
I have tried using TextWatcher but from what I know this is not going to help me,
I know method public void onTextChanged(CharSequence s, int start, int before, int count) give some notes about the which text user remove but this seem unreliable.
And this give me not a way for this matter to stop the edit of use.
EDIT:
Can I use a Spanner for prevent edit to be do for a part of the text? As a readonly spanner?
Someone knows a good way to fix my problems?
I think I has final find a working solustion, but has to be try more deeply to know if this exist some buggs or errors.
public abstract class TextListener implements InputFilter {
public abstract CharSequence removeStr(CharSequence removeChars, int startPos);
public abstract CharSequence insertStr(CharSequence newChars, int startPos);
public abstract CharSequence updateStr(CharSequence oldChars, int startPos, CharSequence newChars);
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
CharSequence returnStr = source;
String curStr = dest.subSequence(dstart, dend).toString();
String newStr = source.toString();
int length = end - start;
int dlength = dend - dstart;
if (dlength > 0 && length == 0) {
// Case: Remove chars, Simple
returnStr = TextListener.this.removeStr(dest.subSequence(dstart, dend), dstart);
} else if (length > 0 && dlength == 0) {
// Case: Insert chars, Simple
returnStr = TextListener.this.insertStr(source.subSequence(start, end), dstart);
} else if (curStr.length() > newStr.length()) {
// Case: Remove string or replace
if (curStr.startsWith(newStr)) {
// Case: Insert chars, by append
returnStr = TextUtils.concat(curStr.subSequence(0, newStr.length()), TextListener.this.removeStr(curStr.subSequence(newStr.length(), curStr.length()), dstart + curStr.length()));
} else {
// Case Replace chars.
returnStr = TextListener.this.updateStr(curStr, dstart, newStr);
}
} else if (curStr.length() < newStr.length()) {
// Case: Append String or rrepace.
if (newStr.startsWith(curStr)) {
// Addend, Insert
returnStr = TextUtils.concat(curStr, TextListener.this.insertStr(newStr.subSequence(curStr.length(), newStr.length()), dstart + curStr.length()));
} else {
returnStr = TextListener.this.updateStr(curStr, dstart, newStr);
}
} else {
// No update os str...
}
// If the return value is same as the source values, return the source value.
return TextUtils.equals(source, returnStr) ? source : returnStr;
}
}
From this code I can easy prevent edit on select part of the text by lookup were in the text I try to edit.
is there a way to set a custom space (in pixels) between letters to an editText? I found only how to set spaces between the lines, but bot between letters on the same row
Using android:letterSpacing i was able to add spacing between characters in a textview
<android.support.v7.widget.AppCompatTextView
android:id="#+id/textViewValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:letterSpacing="0.35"
android:maxLines="1" />
Related methods:
setLetterSpacing(float)
I had to do this myself today so here are some updates about this problem :
From API 21 you can use XML attribute android:letterSpacing="2" or from code myEditText.setLetterSpacing(2);
Before API 21, use a TextWatcher with the following code
private static final String LETTER_SPACING = " ";
private EditText myEditText;
private String myPreviousText;
...
// Get the views
myEditText = (EditText) v.findViewById(R.id.edt_code);
myEditText.addTextChangedListener(this);
...
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// Nothing here
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Nothing here
}
#Override
public void afterTextChanged(Editable s) {
String text = s.toString();
// Only update the EditText when the user modify it -> Otherwise it will be triggered when adding spaces
if (!text.equals(myPreviousText)) {
// Remove spaces
text = text.replace(" ", "");
// Add space between each character
StringBuilder newText = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
if (i == text.length() - 1) {
// Do not add a space after the last character -> Allow user to delete last character
newText.append(Character.toUpperCase(text.charAt(text.length() - 1)));
}
else {
newText.append(Character.toUpperCase(text.charAt(i)) + LETTER_SPACING);
}
}
myPreviousText = newText.toString();
// Update the text with spaces and place the cursor at the end
myEditText.setText(newText);
myEditText.setSelection(newText.length());
}
}
You could implament a custom TextWatcher, and add X spaces every time the user enteres 1.
i have used this, and works for most API levels if not all of them.
KerningViews
Provides a set of views which allows to adjust the spacing between the characters of that view, AKA, Kerning effect.
https://github.com/aritraroy/KerningViews