I am using RxTextView.textChanges for EditText that when the user is typing change value of EditText to convert numbers to currency format like below:
1,000
But I can't see any convert numbers to currency format.
I am using from: NumberFormat.getNumberInstance(Locale.US).format(productPrice);
My code is like bellow:
Observable<CharSequence> observableDiscountPrice = RxTextView.textChanges(discountPriceEdittext);
observableDiscountPrice.map(new Function<CharSequence, Boolean>() {
#Override
public Boolean apply(#io.reactivex.annotations.NonNull CharSequence charSequence) throws Exception {
try {
if (charSequence.length() > 0) {
String pPrice = NumberFormat.getNumberInstance(Locale.US).format(charSequence.toString());
originalPriceEdittext.setText(String.valueOf(pPrice));
return true;
} else {
return false;
}
} catch (Exception e) {
return true;
}
}
}).subscribe(new Subject<Boolean>() {
#Override
public boolean hasObservers() {
return false;
}
#Override
public boolean hasThrowable() {
return false;
}
#Override
public boolean hasComplete() {
return false;
}
#Override
public Throwable getThrowable() {
return null;
}
#Override
protected void subscribeActual(Observer<? super Boolean> observer) {
}
#Override
public void onSubscribe(#io.reactivex.annotations.NonNull Disposable d) {
}
#Override
public void onNext(#io.reactivex.annotations.NonNull Boolean aBoolean) {
}
#Override
public void onError(#io.reactivex.annotations.NonNull Throwable e) {
}
#Override
public void onComplete() {
}
});
Use this TextWatcher class:
public class NumberTextWatcherWithSeperator implements TextWatcher {
private EditText editText;
public NumberTextWatcherWithSeperator(EditText editText) {
this.editText = editText;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
try {
editText.removeTextChangedListener(this);
String value = editText.getText().toString();
if (!value.equals("")) {
if (value.startsWith(".")) {
editText.setText("0.");
}
if (value.startsWith("0") && !value.startsWith("0.")) {
editText.setText("");
}
String str = editText.getText().toString().replaceAll(",", "");
if (!value.equals(""))
editText.setText(getDecimalFormattedString(str));
editText.setSelection(editText.getText().toString().length());
}
editText.addTextChangedListener(this);
} catch (Exception ex) {
ex.printStackTrace();
editText.addTextChangedListener(this);
}
}
private static String getDecimalFormattedString(String value) {
StringTokenizer lst = new StringTokenizer(value, ".");
String str1 = value;
String str2 = "";
if (lst.countTokens() > 1) {
str1 = lst.nextToken();
str2 = lst.nextToken();
}
String str3 = "";
int i = 0;
int j = -1 + str1.length();
if (str1.charAt(-1 + str1.length()) == '.') {
j--;
str3 = ".";
}
for (int k = j; ; k--) {
if (k < 0) {
if (str2.length() > 0)
str3 = str3 + "." + str2;
return str3;
}
if (i == 3) {
str3 = "," + str3;
i = 0;
}
str3 = str1.charAt(k) + str3;
i++;
}
}
}
and
yourEditText.addTextChangedListener(new NumberTextWatcherWithSeperator(yourEditText));
Take a look at https://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html
DecimalFormat myFormatter = new DecimalFormat("###,###.###");
String output = myFormatter.format(156456.673);
System.out.println(156456.673 + " " + "###,###.###" + " " + output);
// I/System.out: 156456.673 ###,###.### 156,456.673
I'm using this watcher to do the same thing:
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Locale;
public class CurrencyTextWatcher implements TextWatcher {
private EditText ed;
private String lastText;
private boolean bDel = false;
private boolean bInsert = false;
private int pos;
public CurrencyTextWatcher(EditText ed) {
this.ed = ed;
}
public static String getStringWithSeparator(long value) {
DecimalFormat formatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US);
String f = formatter.format(value);
return f;
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
bDel = false;
bInsert = false;
if (before == 1 && count == 0) {
bDel = true;
pos = start;
} else if (before == 0 && count == 1) {
bInsert = true;
pos = start;
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
lastText = s.toString();
}
#Override
public void afterTextChanged(Editable s) {
ed.removeTextChangedListener(this);
StringBuilder sb = new StringBuilder();
String text = s.toString();
for (int i = 0; i < text.length(); i++) {
if ((text.charAt(i) >= 0x30 && text.charAt(i) <= 0x39) || text.charAt(i) == '.' || text.charAt(i) == ',')
sb.append(text.charAt(i));
}
if (!sb.toString().equals(s.toString())) {
bDel = bInsert = false;
}
String newText = getFormattedString(sb.toString());
s.clear();
s.append(newText);
ed.addTextChangedListener(this);
if (bDel) {
int idx = pos;
if (lastText.length() - 1 > newText.length())
idx--;
if (idx < 0)
idx = 0;
ed.setSelection(idx);
} else if (bInsert) {
int idx = pos + 1;
if (lastText.length() + 1 < newText.length())
idx++;
if (idx > newText.length())
idx = newText.length();
ed.setSelection(idx);
}
}
private String getFormattedString(String text) {
String res = "";
try {
String temp = text.replace(",", "");
long part1;
String part2 = "";
int dotIndex = temp.indexOf(".");
if (dotIndex >= 0) {
part1 = Long.parseLong(temp.substring(0, dotIndex));
if (dotIndex + 1 <= temp.length()) {
part2 = temp.substring(dotIndex + 1).trim().replace(".", "").replace(",", "");
}
} else
part1 = Long.parseLong(temp);
res = getStringWithSeparator(part1);
if (part2.length() > 0)
res += "." + part2;
else if (dotIndex >= 0)
res += ".";
} catch (Exception ex) {
ex.printStackTrace();
}
return res;
}
}
In case you want to and a dollar sign
fun multiply_two_numbers() {
val x = etValOne.text.toString()
val y = etValTwo.text.toString()
val c = x.toDouble().times(y.toDouble())
//val c = (x.toDouble() * y.toDouble())
val df = DecimalFormat("$ "+"0.00")
df.roundingMode = RoundingMode.CEILING
df.format(c)
etANS.setText(df.format(c))
}
Related
I have working on mention edit text in below code i am extracting text after typing # but this code in working in some device and not in some device.
I have uploaded both video of working and not working in which showing also that which text is getting in text-watcher in red colour in autocomplete list.
This is working video
This is not working video
Any one help me for getting out this problem .This code is working in some devices but in some devices.
public class SocialMentionAutoComplete extends AppCompatMultiAutoCompleteTextView {
UserSearchChatAdapter userSearchChatAdapter;
ArrayMap<String, UserModel> map = new ArrayMap<>();
String formattedOfString = "#%s ";
Context context;
public SocialMentionAutoComplete(Context context) {
super(context);
initializeComponents(context);
}
public SocialMentionAutoComplete(Context context, AttributeSet attrs) {
super(context, attrs);
initializeComponents(context);
}
public SocialMentionAutoComplete(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initializeComponents(context);
}
private void initializeComponents(Context context) {
this.context = context;
addTextChangedListener(textWatcher);
setOnItemClickListener(onItemSelectedListener);
setTokenizer(new SpaceTokenizer());
}
AdapterView.OnItemClickListener onItemSelectedListener = new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
UserModel mentionPerson = (UserModel) adapterView.getItemAtPosition(i);
map.put("#" + mentionPerson.username, mentionPerson);
}
};
/***
*This function returns the contents of the AppCompatMultiAutoCompleteTextView into my desired Format
*You can write your own function according to your needs
**/
public String getProcessedString() {
String s = getText().toString();
for (Map.Entry<String, UserModel> stringMentionPersonEntry : map.entrySet()) {
s = s.replace(stringMentionPersonEntry.getKey(), stringMentionPersonEntry.getValue().getFormattedValue());
}
return s;
}
/**
* This function will process the incoming text into mention format
* You have to implement the processing logic
*/
public void setMentioningText(String text) {
map.clear();
Pattern p = Pattern.compile("\\[([^]]+)]\\(([^ )]+)\\)");
Matcher m = p.matcher(text);
String finalDesc = text;
while (m.find()) {
UserModel mentionPerson = new UserModel();
String name = m.group(1);
String username = m.group(2);
//Processing Logic
finalDesc = finalDesc.replace("#[" + name + "](" + username + ")", "#" + username);
mentionPerson.name = name;
mentionPerson.username = username;
map.put("#" + username, mentionPerson);
}
int textColor = ResourcesCompat.getColor(getResources(), R.color.colorPrimary, null);
Spannable spannable = new SpannableString(finalDesc);
for (Map.Entry<String, UserModel> stringMentionPersonEntry : map.entrySet()) {
int startIndex = finalDesc.indexOf(stringMentionPersonEntry.getKey());
int endIndex = startIndex + stringMentionPersonEntry.getKey().length();
spannable.setSpan(new ForegroundColorSpan(textColor), startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
setText(spannable);
}
TextWatcher textWatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence s, int start, int lengthBefore, int lengthAfter) {
try {
if (!s.toString().isEmpty() && s.length() > 1) {//start < s.length()
String name;
if (lengthAfter > lengthBefore) {
name = s.toString().substring(0, start + 1);
} else {
name = s.toString().substring(0, start);
}
if (name.contains("\n")) {
name = name.replaceAll("\n", "");
}
s = name;// this is main passing
int lastTokenIndex = name.lastIndexOf(" #");
int lastIndexOfSpace = name.lastIndexOf(" ");
int nextIndexOfSpace = name.indexOf(" ", start);
if (lastIndexOfSpace > 0 && lastTokenIndex < lastIndexOfSpace) {
String afterString = s.toString().substring(lastIndexOfSpace, s.length());
if (afterString.startsWith(" ") && !afterString.startsWith(" \n")) return;
}
if (lastTokenIndex < 0) {
if (!name.isEmpty() && name.length() >= 1 && name.startsWith("#")) {
lastTokenIndex = 1;
} else
return;
}
int tokenEnd = lastIndexOfSpace;
if (lastIndexOfSpace <= lastTokenIndex) {
tokenEnd = name.length();
if (nextIndexOfSpace != -1 && nextIndexOfSpace < tokenEnd) {
tokenEnd = nextIndexOfSpace;
}
}
if (lastTokenIndex >= 0) {
name = s.toString().substring(lastTokenIndex, tokenEnd).trim();
Pattern pattern = Pattern.compile("^(.+)\\s.+");
Matcher matcher = pattern.matcher(name);
if (!matcher.find()) {
// name = name.replace("#", "").trim();
if (name.equals("#")) {
// getPollsDetail("#");
} else if (!name.isEmpty()) {
getUsers(name);
}
}
}
} else if (!s.toString().isEmpty() && s.length() == 1 && s.toString().equals("#")) {
{
// getPollsDetail("#");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void afterTextChanged(Editable editable) {
}
};
/*
*This function returns results from the web server according to the user name
* I have used Retrofit for Api Communications
* */
public void getUsers(String name) {
AndroidNetworking.cancel("SearchUser");
String url = WebServiceUrl.SEARCH_USER + name.replace("#", "");
new WebTask().nameSearchAPI(context, url, new WebCompleteTaskNew() {
#Override
public void onComplete(String response, int taskcode, String callUrl) {
try {
JSONObject baseResponse = new JSONObject(response);
JSONObject jsonValue = baseResponse.getJSONObject("value");
if (taskcode == RequestCode.CODE_SEARCH_PEOPLE) {
List<UserModel> peopleArrayList = new Gson().fromJson(jsonValue.getJSONArray("data").toString(), new TypeToken<List<UserModel>>() {
}.getType());
userSearchChatAdapter = new UserSearchChatAdapter(getContext(), peopleArrayList, name);
SocialMentionAutoComplete.this.setAdapter(userSearchChatAdapter);
System.out.println("URLL::" + url + "::CLLLLL::" + callUrl);
if (callUrl.equals(url)) {
showDropDown();
}
// SocialMentionAutoComplete.this.showDropDown();
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onError(String message, int taskcode) {
}
});
}
public class SpaceTokenizer implements MultiAutoCompleteTextView.Tokenizer {
public int findTokenStart(CharSequence text, int cursor) {
int i = cursor;
while (i > 0 && text.charAt(i - 1) != ' ') {
i--;
}
while (i < cursor && text.charAt(i) == ' ') {
i++;
}
return i;
}
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;
}
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 {
// Returns colored text for selected token
SpannableString sp = new SpannableString(String.format(formattedOfString, text));
int textColor = ResourcesCompat.getColor(getResources(), R.color.colorPrimary, null);
sp.setSpan(new ForegroundColorSpan(textColor), 0, text.length() + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return sp;
}
}
}
}
I am using from bellow code for converting numbers to currency format when text changes but when I scrolled the recyclerView I lost true data. What can I do :
public class ManagePriceProductsAdapter extends RecyclerView.Adapter<ManagePriceProductsAdapter.ViewHolder> {
private List<ManagePriceProductsModel.DataValue> managePriceProductsModelList;
private Context context;
private getListDiscountInterface getListDiscountInterface;
private int vendorId = -1;
public ManagePriceProductsAdapter(Context context,
List<ManagePriceProductsModel.DataValue> managePriceProductsModelList,
getListDiscountInterface getListDiscountInterface,
int vendorId) {
this.context = context;
this.managePriceProductsModelList = managePriceProductsModelList;
this.getListDiscountInterface = getListDiscountInterface;
this.vendorId = vendorId;
}
#Override
public ManagePriceProductsAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(context)
.inflate(R.layout.list_item_manage_price_products, viewGroup, false);
return new ManagePriceProductsAdapter.ViewHolder(view,
new DiscountNumberTextWatcherWithSeperator(),
new OriginalNumberTextWatcherWithSeperator());
}
public void getListDiscount() {
getListDiscountInterface.sendGetListDiscountToActivity(managePriceProductsModelList);
}
public void backButton() {
getListDiscountInterface.backButtonForListDiscount(managePriceProductsModelList);
}
public void resetAdapter() {
this.managePriceProductsModelList.clear();
notifyDataSetChanged();
}
#Override
public void onBindViewHolder(final ManagePriceProductsAdapter.ViewHolder viewHolder, int position) {
viewHolder.discountNumberTextWatcherWithSeperator.updatePosition(viewHolder.getAdapterPosition(),
viewHolder.discountPriceEdittext,
viewHolder.originalPriceEdittext);
viewHolder.originalNumberTextWatcherWithSeperator.updatePosition(viewHolder.getAdapterPosition(),
viewHolder.originalPriceEdittext);
try {
if (managePriceProductsModelList.get(viewHolder.getAdapterPosition()).getTitle() != null) {
if (!TextUtils.isEmpty(managePriceProductsModelList.get(viewHolder.getAdapterPosition()).getTitle().trim())) {
String productName = managePriceProductsModelList.get(viewHolder.getAdapterPosition()).getTitle().trim();
viewHolder.titleTextview.setText(productName);
} else {
viewHolder.titleTextview.setText("----");
}
} else {
viewHolder.titleTextview.setText("----");
}
} catch (Exception ex) {
if (vendorId != -1) {
Throwable t = new Throwable(ex + ", vendorId: " + vendorId).fillInStackTrace();
FirebaseCrash.report(t);
} else {
Throwable t = new Throwable(ex + ", vendorId: empty").fillInStackTrace();
FirebaseCrash.report(t);
}
}
try {
if (managePriceProductsModelList.get(viewHolder.getAdapterPosition()).getPrice() != null) {
Long productPrice = managePriceProductsModelList.get(viewHolder.getAdapterPosition()).getPrice();
if (productPrice != null && productPrice != 0 && productPrice > 0) {
viewHolder.originalPriceEdittext.setText(String.valueOf(productPrice));
} else {
viewHolder.originalPriceEdittext.setText("");
}
}
} catch (Exception ex) {
if (vendorId != -1) {
Throwable t = new Throwable(ex + ", vendorId: " + vendorId).fillInStackTrace();
FirebaseCrash.report(t);
} else {
Throwable t = new Throwable(ex + ", vendorId: empty").fillInStackTrace();
FirebaseCrash.report(t);
}
}
try {
if (managePriceProductsModelList.get(viewHolder.getAdapterPosition()).getDiscountedPrice() != null) {
Long discountPrice = managePriceProductsModelList.get(viewHolder.getAdapterPosition()).getDiscountedPrice();
if (discountPrice != null && discountPrice != 0 && discountPrice > 0) {
viewHolder.discountPriceEdittext.setText(String.valueOf(discountPrice));
} else {
viewHolder.discountPriceEdittext.setText("");
}
}
} catch (Exception ex) {
if (vendorId != -1) {
Throwable t = new Throwable(ex + ", vendorId: " + vendorId).fillInStackTrace();
FirebaseCrash.report(t);
} else {
Throwable t = new Throwable(ex + ", vendorId: empty").fillInStackTrace();
FirebaseCrash.report(t);
}
}
}
#Override
public int getItemCount() {
return managePriceProductsModelList.size();
}
public interface getListDiscountInterface {
void sendGetListDiscountToActivity(List<ManagePriceProductsModel.DataValue> managePriceProductsModelList);
void backButtonForListDiscount(List<ManagePriceProductsModel.DataValue> managePriceProductsModelList);
}
class ViewHolder extends RecyclerView.ViewHolder {
//region ViewBinding
#BindView(R.id.title_textview)
TextView titleTextview;
#BindView(R.id.original_price_edittext)
EditText originalPriceEdittext;
#BindView(R.id.discount_price_edittext)
EditText discountPriceEdittext;
DiscountNumberTextWatcherWithSeperator discountNumberTextWatcherWithSeperator;
OriginalNumberTextWatcherWithSeperator originalNumberTextWatcherWithSeperator;
//endregion
ViewHolder(View view,
DiscountNumberTextWatcherWithSeperator discountNumberTextWatcherWithSeperator,
OriginalNumberTextWatcherWithSeperator originalNumberTextWatcherWithSeperator) {
super(view);
ButterKnife.bind(this, itemView);
this.discountNumberTextWatcherWithSeperator = discountNumberTextWatcherWithSeperator;
this.discountPriceEdittext.addTextChangedListener(discountNumberTextWatcherWithSeperator);
this.originalNumberTextWatcherWithSeperator = originalNumberTextWatcherWithSeperator;
this.originalPriceEdittext.addTextChangedListener(originalNumberTextWatcherWithSeperator);
}
}
private class DiscountNumberTextWatcherWithSeperator implements TextWatcher {
private EditText discountEditText;
private EditText originalEditText;
private int position;
private String getDecimalFormattedString(String value) {
StringTokenizer lst = new StringTokenizer(value, ".");
String str1 = value;
String str2 = "";
if (lst.countTokens() > 1) {
str1 = lst.nextToken();
str2 = lst.nextToken();
}
String str3 = "";
int i = 0;
int j = -1 + str1.length();
if (str1.charAt(-1 + str1.length()) == '.') {
j--;
str3 = ".";
}
for (int k = j; ; k--) {
if (k < 0) {
if (str2.length() > 0)
str3 = str3 + "." + str2;
return str3;
}
if (i == 3) {
str3 = "," + str3;
i = 0;
}
str3 = str1.charAt(k) + str3;
i++;
}
}
public void updatePosition(int position,
EditText discountEditText,
EditText originalEditText) {
this.position = position;
this.discountEditText = discountEditText;
this.originalEditText = originalEditText;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
if (charSequence.length() > 0) {
originalEditText.setPaintFlags(originalEditText.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
ManagePriceProductsModel.DataValue dataValue = new ManagePriceProductsModel.DataValue();
dataValue.setTitle(managePriceProductsModelList.get(position).getTitle().trim());
dataValue.setId(managePriceProductsModelList.get(position).getId());
dataValue.setPrice(managePriceProductsModelList.get(position).getPrice());
dataValue.setDiscountedPrice(Long.parseLong(charSequence.toString().replace(",", "")));
managePriceProductsModelList.set(position, dataValue);
} else if (charSequence.length() == 0) {
originalEditText.setPaintFlags(originalEditText.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
ManagePriceProductsModel.DataValue dataValue = new ManagePriceProductsModel.DataValue();
dataValue.setTitle(managePriceProductsModelList.get(position).getTitle().trim());
dataValue.setId(managePriceProductsModelList.get(position).getId());
dataValue.setPrice(managePriceProductsModelList.get(position).getPrice());
dataValue.setDiscountedPrice(null);
managePriceProductsModelList.set(position, dataValue);
}
}
#Override
public void afterTextChanged(Editable editable) {
try {
discountEditText.removeTextChangedListener(this);
String value = discountEditText.getText().toString();
if (!value.equals("")) {
if (value.startsWith(".")) {
discountEditText.setText("0.");
}
if (value.startsWith("0") && !value.startsWith("0.")) {
discountEditText.setText("");
}
String str = discountEditText.getText().toString().replaceAll(",", "");
if (!value.equals(""))
discountEditText.setText(getDecimalFormattedString(str));
discountEditText.setSelection(discountEditText.getText().toString().length());
}
discountEditText.addTextChangedListener(this);
} catch (Exception ex) {
ex.printStackTrace();
discountEditText.addTextChangedListener(this);
}
}
}
private class OriginalNumberTextWatcherWithSeperator implements TextWatcher {
private EditText editText;
private int position;
private String getDecimalFormattedString(String value) {
StringTokenizer lst = new StringTokenizer(value, ".");
String str1 = value;
String str2 = "";
if (lst.countTokens() > 1) {
str1 = lst.nextToken();
str2 = lst.nextToken();
}
String str3 = "";
int i = 0;
int j = -1 + str1.length();
if (str1.charAt(-1 + str1.length()) == '.') {
j--;
str3 = ".";
}
for (int k = j; ; k--) {
if (k < 0) {
if (str2.length() > 0)
str3 = str3 + "." + str2;
return str3;
}
if (i == 3) {
str3 = "," + str3;
i = 0;
}
str3 = str1.charAt(k) + str3;
i++;
}
}
public void updatePosition(int position,
EditText editText) {
this.position = position;
this.editText = editText;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
if (charSequence.length() > 0) {
ManagePriceProductsModel.DataValue dataValue = new ManagePriceProductsModel.DataValue();
dataValue.setTitle(managePriceProductsModelList.get(position).getTitle().trim());
dataValue.setId(managePriceProductsModelList.get(position).getId());
dataValue.setPrice(Long.parseLong(charSequence.toString().replace(",", "")));
dataValue.setDiscountedPrice(managePriceProductsModelList.get(position).getDiscountedPrice());
managePriceProductsModelList.set(position, dataValue);
} else if (charSequence.length() == 0) {
ManagePriceProductsModel.DataValue dataValue = new ManagePriceProductsModel.DataValue();
dataValue.setTitle(managePriceProductsModelList.get(position).getTitle().trim());
dataValue.setId(managePriceProductsModelList.get(position).getId());
dataValue.setPrice(null);
dataValue.setDiscountedPrice(managePriceProductsModelList.get(position).getDiscountedPrice());
managePriceProductsModelList.set(position, dataValue);
}
}
#Override
public void afterTextChanged(Editable editable) {
try {
editText.removeTextChangedListener(this);
String value = editText.getText().toString();
if (!value.equals("")) {
if (value.startsWith(".")) {
editText.setText("0.");
}
if (value.startsWith("0") && !value.startsWith("0.")) {
editText.setText("");
}
String str = editText.getText().toString().replaceAll(",", "");
if (!value.equals(""))
editText.setText(getDecimalFormattedString(str));
editText.setSelection(editText.getText().toString().length());
}
editText.addTextChangedListener(this);
} catch (Exception ex) {
ex.printStackTrace();
editText.addTextChangedListener(this);
}
}
}
}
As the comments above it is not recommended to use edittext in recyclerview.
If you have to do this can you try to use
viewHolder.setIsRecyclable(false);
in your onBindViewHolder method
You can use this library to support this
Create a ViewState
new ViewState<>() {
private String savedValue; /* here will be saved a value for each item by createViewStateID() */
#Override
public void clear(#NonNull final ViewHolder<ViewFinder> holder) {
holder.getViewFinder().setText(R.id.text, "");
}
#Override
public void save(#NonNull final ViewHolder<ViewFinder> holder) {
savedValue = holder.getViewFinder().<EditText>find(R.id.text).getText().toString();
}
#Override
public void restore(#NonNull final ViewHolder<ViewFinder> holder) {
holder.getViewFinder().setText(R.id.text, savedValue);
}
};
Set that ViewState to your ViewRenderer
adapter.registerRenderer(new ViewRenderer<>(
R.layout.your_item_layout, //your layout
YourItemModel.class, //your model
(model, finder, payloads) -> finder.setText(R.id.text, model.getValue()), //your binding
getYourViewStateProvider() // here is your ViewState
));
More info you can find here
You can use the code below to keep hold of your dynamic values.
Paste this code inside your adapter. This allows to assign a unique id to your items. Just make sure the id assigned to all the items in the recyclerview must be unique.
override fun getItemViewType(position: Int) = position
override fun getItemId(position: Int) = position.toLong()
I want to separate automatically edit text like (9,99,999) like this. I searched for this on the web but I have not found a proper solution for this.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText editText = (EditText) findViewById(R.id.edittext);
editText.addTextChangedListener(new NumberTextWatcherForThousand(editText)); NumberTextWatcherForThousand.trimCommaOfString(editText.getText().toString());
}
}
NumberTextWatcherForThousand
public class NumberTextWatcherForThousand implements TextWatcher {
EditText editText;
public NumberTextWatcherForThousand(EditText editText) {
this.editText = editText;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
try
{
editText.removeTextChangedListener(this);
String value = editText.getText().toString();
if (value != null && !value.equals(""))
{
if(value.startsWith(".")){
editText.setText("0.");
}
if(value.startsWith("0") && !value.startsWith("0.")){
editText.setText("");
}
String str = editText.getText().toString().replaceAll(",", "");
if (!value.equals(""))
editText.setText(getDecimalFormattedString(str));
editText.setSelection(editText.getText().toString().length());
}
editText.addTextChangedListener(this);
return;
}
catch (Exception ex)
{
ex.printStackTrace();
editText.addTextChangedListener(this);
}
}
public static String getDecimalFormattedString(String value)
{
StringTokenizer lst = new StringTokenizer(value, ".");
String str1 = value;
String str2 = "";
if (lst.countTokens() > 1)
{
str1 = lst.nextToken();
str2 = lst.nextToken();
}
String str3 = "";
int i = 0;
int j = -1 + str1.length();
if (str1.charAt( -1 + str1.length()) == '.')
{
j--;
str3 = ".";
}
for (int k = j;; k--)
{
if (k < 0)
{
if (str2.length() > 0)
str3 = str3 + "." + str2;
return str3;
}
if (i == 3)
{
str3 = "," + str3;
i = 0;
}
str3 = str1.charAt(k) + str3;
i++;
}
}
public static String trimCommaOfString(String string) {
if(string.contains(",")){
return string.replace(",","");}
else {
return string;
}
}
}
This will format the text and add commas in thousands place inside your edit text.
#Override
public void afterTextChanged(Editable editable) {
try {
// The comma in the format specifier does the trick
editText.setText(String.format("%,d", Long.parseLong(editable.toString())));
} catch (NumberFormatException e) {
}
}
try this below code :-
import java.text.DecimalFormat;
import java.text.ParseException;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
public class NumberTextWatcher implements TextWatcher {
private DecimalFormat df;
private DecimalFormat dfnd;
private boolean hasFractionalPart;
private EditText et;
public NumberTextWatcher(EditText et)
{
df = new DecimalFormat("#,###.##");
df.setDecimalSeparatorAlwaysShown(true);
dfnd = new DecimalFormat("#,###");
this.et = et;
hasFractionalPart = false;
}
#SuppressWarnings("unused")
private static final String TAG = "NumberTextWatcher";
#Override
public void afterTextChanged(Editable s)
{
et.removeTextChangedListener(this);
try {
int inilen, endlen;
inilen = et.getText().length();
String v = s.toString().replace(String.valueOf(df.getDecimalFormatSymbols().getGroupingSeparator()), "");
Number n = df.parse(v);
int cp = et.getSelectionStart();
if (hasFractionalPart) {
et.setText(df.format(n));
} else {
et.setText(dfnd.format(n));
}
endlen = et.getText().length();
int sel = (cp + (endlen - inilen));
if (sel > 0 && sel <= et.getText().length()) {
et.setSelection(sel);
} else {
// place cursor at the end?
et.setSelection(et.getText().length() - 1);
}
} catch (NumberFormatException nfe) {
// do nothing?
} catch (ParseException e) {
// do nothing?
}
et.addTextChangedListener(this);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
if (s.toString().contains(String.valueOf(df.getDecimalFormatSymbols().getDecimalSeparator())))
{
hasFractionalPart = true;
} else {
hasFractionalPart = false;
}
}
}
and in your edittext
editText.addTextChangedListener(new NumberTextWatcher(editText));
In build.gradle add following lines
repositories{
maven { url "https://jitpack.io" }
}
dependencies {
compile 'com.github.BlacKCaT27:CurrencyEditText:v1.4.4'
}
Instead of EditText use following Code
<com.blackcat.currencyedittext.CurrencyEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
check this link https://github.com/BlacKCaT27/CurrencyEditText
I want to separate automatically edit text like (9,99,999) like this. i searched for this on web but i am not getting proper solution for this.
can you please help me.thank you stack overflow.
You can use DecimalFormat for this like below Code:
public String formatNumber(double d) {
DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Locale.US);
formatter.applyPattern("#,###");
return formatter.format(d);
}
You Can Pass Pattern as you want.
public static String formatCurrency(String number) {
try {
number = NumberFormat.getNumberInstance(Locale.US).format(Double.valueOf(number));
} catch (Exception e) {
}
return number;
}
This is what i did. Works perfectly
Try this.
public class NumberTextWatcherForThousand implements TextWatcher {
EditText editText;
public NumberTextWatcherForThousand(EditText editText) {
this.editText = editText;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
try
{
editText.removeTextChangedListener(this);
String value = editText.getText().toString();
if (value != null && !value.equals(""))
{
if(value.startsWith(".")){ //adds "0." when only "." is pressed on begining of writting
editText.setText("0.");
}
if(value.startsWith("0") && !value.startsWith("0.")){
editText.setText(""); //Prevents "0" while starting but not "0."
}
String str = editText.getText().toString().replaceAll(",", "");
if (!value.equals(""))
editText.setText(getDecimalFormat(str));
editText.setSelection(editText.getText().toString().length());
}
editText.addTextChangedListener(this);
return;
}
catch (Exception ex)
{
ex.printStackTrace();
editText.addTextChangedListener(this);
}
}
public static String getDecimalFormat(String value)
{
StringTokenizer lst = new StringTokenizer(value, ".");
String str1 = value;
String str2 = "";
if (lst.countTokens() > 1)
{
str1 = lst.nextToken();
str2 = lst.nextToken();
}
String str3 = "";
int i = 0;
int j = -1 + str1.length();
if (str1.charAt( -1 + str1.length()) == '.')
{
j--;
str3 = ".";
}
for (int k = j;; k--)
{
if (k < 0)
{
if (str2.length() > 0)
str3 = str3 + "." + str2;
return str3;
}
if (i == 3)
{
str3 = "," + str3;
i = 0;
}
str3 = str1.charAt(k) + str3;
i++;
}
}
//Trims all the comma of the string and returns
public static String trimCommaOfString(String string) {
if(string.contains(",")){
return string.replace(",","");}
else {
return string;
}
}
}
editText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
editText.removeTextChangedListener(this);
try {
StringBuilder originalString = new StringBuilder(editable.toString().replaceAll(",", ""));
int indx = 0;
for (int i = originalString.length(); i > 0; i--) {
if (indx % 3 == 0 && indx > 0)
originalString = originalString.insert(i, ",");
indx++;
}
editText.setText(originalString);
editText.setSelection(originalString.length());
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
}
editText.addTextChangedListener(this);
}
});
I have an EditText in which the user should input a number including decimals and i want a thousand separator automatically added onto the input number I tried a couple of other methods but some do not allow floating point numbers so i came up with this code which works well only that the string input is not being edited in realtime to one with possible thousand separators and the errors seem to stem from the s.replace();
am2 = new TextWatcher(){
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {}
public void afterTextChanged(Editable s) {
if (s.toString().equals("")) {
amount.setText("");
value = 0;
}else{
StringBuffer strBuff = new StringBuffer();
char c;
for (int i = 0; i < amount2.getText().toString().length() ; i++) {
c = amount2.getText().toString().charAt(i);
if (Character.isDigit(c)) {
strBuff.append(c);
}
}
value = Double.parseDouble(strBuff.toString());
reverse();
NumberFormat nf2 = NumberFormat.getInstance(Locale.ENGLISH);
((DecimalFormat)nf2).applyPattern("###,###.#######");
s.replace(0, s.length(), nf2.format(value));
}
}
};
This Class solves the problem, allows decimal input and adds the thousand separators.
public class NumberTextWatcher implements TextWatcher {
private DecimalFormat df;
private DecimalFormat dfnd;
private boolean hasFractionalPart;
private EditText et;
public NumberTextWatcher(EditText et)
{
df = new DecimalFormat("#,###.##");
df.setDecimalSeparatorAlwaysShown(true);
dfnd = new DecimalFormat("#,###");
this.et = et;
hasFractionalPart = false;
}
#SuppressWarnings("unused")
private static final String TAG = "NumberTextWatcher";
public void afterTextChanged(Editable s)
{
et.removeTextChangedListener(this);
try {
int inilen, endlen;
inilen = et.getText().length();
String v = s.toString().replace(String.valueOf(df.getDecimalFormatSymbols().getGroupingSeparator()), "");
Number n = df.parse(v);
int cp = et.getSelectionStart();
if (hasFractionalPart) {
et.setText(df.format(n));
} else {
et.setText(dfnd.format(n));
}
endlen = et.getText().length();
int sel = (cp + (endlen - inilen));
if (sel > 0 && sel <= et.getText().length()) {
et.setSelection(sel);
} else {
// place cursor at the end?
et.setSelection(et.getText().length() - 1);
}
} catch (NumberFormatException nfe) {
// do nothing?
} catch (ParseException e) {
// do nothing?
}
et.addTextChangedListener(this);
}
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().contains(String.valueOf(df.getDecimalFormatSymbols().getDecimalSeparator())))
{
hasFractionalPart = true;
} else {
hasFractionalPart = false;
}
}
}
Source: http://blog.roshka.com/2012/08/android-edittext-with-number-format.html
Unfortunately the code did not work as it is in the answer.
It has two problems:
It does not work if the phone locale configuration uses "," as a decimal separator.
It does not work if the number has trailing zeros in the decimal part. Example 1.01.
I went crazy to fix it.
Finally I came to this code that worked well on my cell phone:
NumberTextWatcher.java
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.DigitsKeyListener;
import android.util.Log;
import android.widget.EditText;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;
public class NumberTextWatcher
implements TextWatcher {
private static final String TAG = "NumberTextWatcher";
private final int numDecimals;
private String groupingSep;
private String decimalSep;
private boolean nonUsFormat;
private DecimalFormat df;
private DecimalFormat dfnd;
private boolean hasFractionalPart;
private EditText et;
private String value;
private String replicate(char ch, int n) {
return new String(new char[n]).replace("\0", "" + ch);
}
public NumberTextWatcher(EditText et, Locale locale, int numDecimals) {
et.setKeyListener(DigitsKeyListener.getInstance("0123456789.,"));
this.numDecimals = numDecimals;
DecimalFormatSymbols symbols = new DecimalFormatSymbols(locale);
char gs = symbols.getGroupingSeparator();
char ds = symbols.getDecimalSeparator();
groupingSep = String.valueOf(gs);
decimalSep = String.valueOf(ds);
String patternInt = "#,###";
dfnd = new DecimalFormat(patternInt, symbols);
String patternDec = patternInt + "." + replicate('#', numDecimals);
df = new DecimalFormat(patternDec, symbols);
df.setDecimalSeparatorAlwaysShown(true);
df.setRoundingMode(RoundingMode.DOWN);
this.et = et;
hasFractionalPart = false;
nonUsFormat = !decimalSep.equals(".");
value = null;
}
#Override
public void afterTextChanged(Editable s) {
Log.d(TAG, "afterTextChanged");
et.removeTextChangedListener(this);
try {
int inilen, endlen;
inilen = et.getText().length();
String v = value.replace(groupingSep, "");
Number n = df.parse(v);
int cp = et.getSelectionStart();
if (hasFractionalPart) {
int decPos = v.indexOf(decimalSep) + 1;
int decLen = v.length() - decPos;
if (decLen > numDecimals) {
v = v.substring(0, decPos + numDecimals);
}
int trz = countTrailingZeros(v);
StringBuilder fmt = new StringBuilder(df.format(n));
while (trz-- > 0) {
fmt.append("0");
}
et.setText(fmt.toString());
} else {
et.setText(dfnd.format(n));
}
endlen = et.getText().length();
int sel = (cp + (endlen - inilen));
if (sel > 0 && sel <= et.getText().length()) {
et.setSelection(sel);
} else {
// place cursor at the end?
et.setSelection(et.getText().length() - 1);
}
} catch (NumberFormatException | ParseException nfe) {
// do nothing?
}
et.addTextChangedListener(this);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
Log.d(TAG, "beforeTextChanged");
value = et.getText().toString();
}
private int countTrailingZeros(String str) {
int count = 0;
for (int i = str.length() - 1; i >= 0; i--) {
char ch = str.charAt(i);
if ('0' == ch) {
count++;
} else {
break;
}
}
return count;
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Log.d(TAG, "onTextChanged");
String newValue = s.toString();
String change = newValue.substring(start, start + count);
String prefix = value.substring(0, start);
String suffix = value.substring(start + before);
if (".".equals(change) && nonUsFormat) {
change = decimalSep;
}
value = prefix + change + suffix;
hasFractionalPart = value.contains(decimalSep);
Log.d(TAG, "VALUE: " + value);
}
}
and then to use it simply to do:
Locale locale = new Locale("es", "AR"); // For example Argentina
int numDecs = 2; // Let's use 2 decimals
TextWatcher tw = new NumberTextWatcher(myEditText, locale, numDecs);
myEditText.addTextChangedListener(tw);
You need to use DecimalFormat class with DecimalFormatSymbols class, check the out following method,
public static String formatAmount(int num)
{
DecimalFormat decimalFormat = new DecimalFormat();
DecimalFormatSymbols decimalFormateSymbol = new DecimalFormatSymbols();
decimalFormateSymbol.setGroupingSeparator(',');
decimalFormat.setDecimalFormatSymbols(decimalFormateSymbol);
return decimalFormat.format(num);
}
you can use kotlin extensions function like this...
fun EditText.onCommaChange(input: (String) -> Unit) {
this.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
if (!edit) {
edit = true
if (s.toString() != "₹") {
try {
val flNumber = getCommaLessNumber(s.toString()).toInt()
val fNumber = getFormattedAmount(flNumber)
setText(fNumber)
setSelection(text.length)
input(flNumber.toString())
} catch (e: NumberFormatException) {
Timber.e(e)
}
} else {
setText("")
input("")
}
edit = false
}
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
})}
fun getCommaLessNumber(commaNumber: String): String {
var number = commaNumber.replace("₹", "")
number = number.replace(",".toRegex(), "")
return number}
fun getFormattedAmount(amount: Int): String {
return "₹${String.format("%,d", amount)}"}
fun EditText.text() = this.text.toString()
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import java.text.DecimalFormat;
public class MyNumberWatcher_3Digit implements TextWatcher {
private EditText editText;
private int digit;
public MyNumberWatcher_3Digit(EditText editText) {
this.editText = editText;
}
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
editText.removeTextChangedListener( this );
String s = editText.getText().toString();
s = s.replace( ",", "" ).replace( "٬", "" );
s = replaceNonstandardDigits( s );
if (s.length() > 0) {
DecimalFormat sdd = new DecimalFormat( "#,###" );
Double doubleNumber = Double.parseDouble( s );
String format = sdd.format( doubleNumber );
editText.setText( format );
editText.setSelection( format.length() );
}
editText.addTextChangedListener( this );
}
static String replaceNonstandardDigits(String input) {
if (input == null || input.isEmpty()) {
return input;
}
StringBuilder builder = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt( i );
if (isNonstandardDigit( ch )) {
int numericValue = Character.getNumericValue( ch );
if (numericValue >= 0) {
builder.append( numericValue );
}
} else {
builder.append( ch );
}
}
return builder.toString();
}
private static boolean isNonstandardDigit(char ch) {
return Character.isDigit( ch ) && !(ch >= '0' && ch <= '9');
}
}
// oncreate activity
input_text_rate.addTextChangedListener(new MyNumberWatcher_3Digit(input_text_rate));
I used this way in Kotlin for a Dialog:
val et = dialog.findViewById(R.id.etNumber) as EditText
et.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable) {
et.removeTextChangedListener(this)
forChanged(et)
et.addTextChangedListener(this)
}
override fun beforeTextChanged(
s: CharSequence,
start: Int,
count: Int,
after: Int
) {
}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
}
})
then write a method like this:
private fun forChanged(alpha: EditText) {
val string = alpha.text.toString()
val dec = DecimalFormat("#,###")
if (!TextUtils.isEmpty(string)) {
val textWC = string.replace(",".toRegex(), "")
val number = textWC.toDouble()
alpha.setText(dec.format(number))
alpha.setSelection(dec.format(number).length)
}
}
I have tried solutions but with ending 0 i was having problem, sometimes user just wanted to enter 0.01 or 0.0001,
I don't know if any other have posted same answer or not but if this helps,
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.widget.EditText;
import java.text.DecimalFormat;
public class NumberTextWatcher implements TextWatcher {
private DecimalFormat dfnd;
private boolean hasFractionalPart;
private EditText inputView;
public static void bindView(EditText inputView) {
NumberTextWatcher temp = new NumberTextWatcher(inputView);
inputView.addTextChangedListener(temp);
}
public NumberTextWatcher(EditText inputView) {
dfnd = new DecimalFormat("#,###.######");
this.inputView = inputView;
hasFractionalPart = false;
}
#SuppressWarnings("unused")
private static final String TAG = "NumberTextWatcher";
public void afterTextChanged(Editable s) {
Log.d(TAG, "afterTextChanged() called with: s = [" + s + "]");
inputView.removeTextChangedListener(this);
try {
String text = inputView.getText().toString().replace(String.valueOf(dfnd.getDecimalFormatSymbols().getGroupingSeparator()), "");
if(text.charAt(text.length() - 1) == '.')
{
if(getCount(text,'.') >1)
{
text = text.substring(0,text.length()-1);
}
}
String afterDecimalPoint = "";
String beforeDecimalPoint = text;
if (hasFractionalPart || (text.charAt(text.length() - 1) == '0')) {
String[] data = text.split("\\.");
beforeDecimalPoint = data[0];
if (data.length != 2) {
afterDecimalPoint = ".";
} else {
afterDecimalPoint = "." + data[1];
if (data[1].length() >= dfnd.getMaximumFractionDigits()) {
afterDecimalPoint = "." + data[1].substring(0, dfnd.getMaximumFractionDigits());
}
}
}
beforeDecimalPoint = dfnd.format(Double.parseDouble(beforeDecimalPoint));
String finalText = beforeDecimalPoint;
if (hasFractionalPart) {
finalText = beforeDecimalPoint + afterDecimalPoint;
}
inputView.setText(finalText);
inputView.setSelection(finalText.length());
} catch (Exception nfe) {
// do nothing?
nfe.printStackTrace();
}
inputView.addTextChangedListener(this);
}
private int getCount(String someString, char someChar) {
int count = 0;
for (int i = 0; i < someString.length(); i++) {
if (someString.charAt(i) == someChar) {
count++;
}
}
return count;
}
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().contains(String.valueOf(dfnd.getDecimalFormatSymbols().getDecimalSeparator()))) {
hasFractionalPart = true;
} else {
hasFractionalPart = false;
}
}
}