/**
* 自定義EditTextView 限定數字格式和最大值
*/
public class FormatEditText extends androidx.appcompat.widget.AppCompatEditText{
private static final int UN_DEFINED = Integer.MAX_VALUE;
private static final int INTEGER = 0;
private static final int FLOAT = 1;
private static final int TEXT = 2;
private int dotNum = 2;//小數點數量
private int maxValue;
private int customInputType;
public FormatEditText(Context context){
super(context);
}
public FormatEditText(Context context, AttributeSet attrs){
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FormatEditText);
maxValue = typedArray.getInt(R.styleable.FormatEditText_value_max, UN_DEFINED);
customInputType = typedArray.getInt(R.styleable.FormatEditText_value_format, TEXT);
dotNum = typedArray.getInt(R.styleable.FormatEditText_value_dot, 2);
initEditText();
typedArray.recycle();
}
private void initEditText(){
if(customInputType == TEXT){
return;
}else if(customInputType == INTEGER){
setInputType(InputType.TYPE_CLASS_NUMBER);
Log.e("customInputType", "INTEGER");
setIntegerFilter();
}else if(customInputType == FLOAT){
setInputType(InputType.TYPE_NUMBER_FLAG_DECIMAL);
setFloatFilter();
Log.e("customInputType", "FLOAT");
}
}
/**
* 去掉整數前面的0
*/
private String cutInt(String text){
if(text.length() > 1 && text.startsWith("0")){
text = text.substring(1);
return cutInt(text);
}
return text;
}
private void setIntegerFilter(){
addTextChangedListener(new TextWatcher(){
@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){
String trim = s.toString().trim();
if(!TextUtils.isEmpty(trim) && trim.length() > 1 && trim.startsWith("0")){
String text = cutInt(trim);
setText(text);
setSelection(text.length());
}else if(maxValue != UN_DEFINED && !TextUtils.isEmpty(trim) && trim.length() > 0){
try{
int value = Integer.parseInt(trim);
if(value > maxValue){
App.showMessage(getContext().getString(R.string.max_value_notice) + maxValue);
String substring = trim.substring(0, trim.length() - 1);
setText(substring);
setSelection(substring.length());
}
}catch(Exception e){
e.printStackTrace();
}
}
}
});
}
private void setFloatFilter(){
setFilters(new InputFilter[]{new FloatFilter(dotNum, maxValue)});
addTextChangedListener(new TextWatcher(){
@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){
String trim = s.toString().trim();
if(!TextUtils.isEmpty(trim) && trim.length() > 1 && trim.startsWith("0") && !trim.startsWith("0.")){
String text = cutInt(trim);
setText(text);
setSelection(text.length());
}else if(!TextUtils.isEmpty(trim) && trim.length() > 0 && trim.startsWith(".")){
String newText = "0" + trim;
setText(newText);
setSelection(newText.length());
}
}
});
}
public class FloatFilter implements InputFilter{
Pattern mPattern;
float max;
/**
* @param digitsAfterZero 保留幾位小數
* @param max 最大值
*/
int length = 6; //小數點前面整數位數
public FloatFilter(int digitsAfterZero, float max){
String regex = String.format("[0-9]{0,%d}+(\\.[0-9]{0,%d})?", length, digitsAfterZero);
mPattern = Pattern.compile(regex);
this.max = max;
}
/**
* dest 輸入前的文字
* source 輸入的文字
*/
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend){
//直接輸入"."傳回"0."
// Log.e("dest", dest.toString() + " __");
if(".".equals(source.toString()) && "".equals(dest.toString())){
return "0.";
}
StringBuilder builder = new StringBuilder(dest);
builder.insert(dstart, source);
String resultTemp = builder.toString();
//判斷修改後的數字是否滿足小數格式,不滿足則傳回 "",不允許修改
Matcher matcher = mPattern.matcher(resultTemp);
if(!matcher.matches()){
return "";
}
if(max != UN_DEFINED && resultTemp.length() > 0){
try{
float value = Float.parseFloat(resultTemp);
if(value > max){
App.showMessage(getContext().getString(R.string.max_value_notice) + max);
return "";
}
}catch(Exception e){
return "";
}
}
return source;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="FormatEditText">
<!-- <attr name="value_min" format="integer" />-->
<attr name="value_max" format="integer" />
<attr name="value_dot" format="integer" />
<attr name="value_format">
<enum name="v_integer" value="0" />
<enum name="v_float" value="1" />
<enum name="v_text" value="2" />
</attr>
</declare-styleable>
</resources>