我必须允许用户只在##中输入时间:##格式即时编辑文本,有没有办法实现它?我使用下面的代码,但它不起作用。
我能输入超过24的数字,如45623:5689。
edit.setInputType(InputType.TYPE_DATETIME_VARIATION_TIME)
即使android:text="time"
也无效。
我怎样才能实现这个目标。任何人都可以建议我怎么做这件事。
我想允许用户输入最多2个位置,最多23个值,然后输入compulasary:然后用户最多允许59个值。
例如
23:59 correct
24:05 incorrect
02:56 correct
02:79 incorrect
我也使用了这个自定义过滤器,但它不起作用
我从SO中的其他地方获得了此代码。
代码:
InputFilter timeFilter = new InputFilter() {
public CharSequence filter(CharSequence source, int start, int end, Spanned dest,
int dstart, int dend) {
if (source.length() == 0) {
return null;// deleting, keep original editing
}
String result = "";
result += dest.toString().substring(0, dstart);
result += source.toString().substring(start, end);
result += dest.toString().substring(dend, dest.length());
if (result.length() > 5) {
return "";// do not allow this edit
}
boolean allowEdit = true;
char c;
if (result.length() > 0) {
c = result.charAt(0);
allowEdit &= (c >= '0' && c <= '2');
}
if (result.length() > 1) {
c = result.charAt(1);
allowEdit &= (c >= '0' && c <= '9');
}
if (result.length() > 2) {
c = result.charAt(2);
allowEdit &= (c == ':');
}
if (result.length() > 3) {
c = result.charAt(3);
allowEdit &= (c >= '0' && c <= '5');
}
if (result.length() > 4) {
c = result.charAt(4);
allowEdit &= (c >= '0' && c <= '9');
}
return allowEdit ? null : "";
}
};
编辑问题:main.xml文件代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="10dp" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:gravity="center"
android:orientation="horizontal" >
<TextView
android:id="@+id/txtRecipientName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="20dp"
android:text="@string/recipient_name" />
<EditText
android:id="@+id/edTxtRecipient"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ems="10"
android:paddingLeft="20dp" >
<requestFocus />
</EditText>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:gravity="center"
android:orientation="horizontal" >
<TextView
android:id="@+id/txtParcelDeliverTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="20dp"
android:text="@string/delivered_time" />
<EditText
android:id="@+id/edTxtParcelDeliverTime"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ems="10"
android:paddingLeft="20dp" >
</EditText>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:gravity="center"
android:orientation="horizontal" >
<Button
android:id="@+id/btnRecipient_OK"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="@android:string/ok" />
</LinearLayout>
</LinearLayout>
此代码正在运行,但如果我插入第一个字母并插入正确的值,那么它不起作用,因为source
包含其先前的字符值。
答案 0 :(得分:1)
尝试将字符转换为整数,然后测试它们是否大于24和60。
int a = ((int) result.charAt(0)) - 48;
int b = ((int) result.charAt(1)) - 48;
int c = ((int) result.charAt(3)) - 48;
if(a < 0 || b < 0 || c < 0) {
Not right.
}
if((a > 2 || (a == 2 && b > 3)) || c > 59) {
Neither is this.
}
减去48因为数字0在ascii表中是第48位。 测试必须是ascii。
答案 1 :(得分:1)
而不是char为什么不使用字符串,因为char也可以用于比较,因为它可以返回数字
char c ='a';
if(c>10)
//do something
//OR
int x = c;
那么为什么不使用String而不是char
或你可以做的是,使用子字符串或类似的东西获取前两个字符并使用Integer.parse()方法解析它,如果它成功解析然后它是一个有效数字,否则它不是这样你可以验证它并且类似地为接下来的两个字符做
修改强> 的
如果你想这样实现 23:59正确 24:05不对 02:56对 02:79不正确
然后这是从我这边起作用的代码
public class MainActivity extends Activity {
InputFilter timeFilter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
timeFilter = new InputFilter() {
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest,
int dstart, int dend) {
if (source.length() == 0) {
return null;// deleting, keep original editing
}
String result = "";
result += dest.toString().substring(0, dstart);
result += source.toString().substring(start, end);
result += dest.toString().substring(dend, dest.length());
if (result.length() > 5) {
return "";// do not allow this edit
}
boolean allowEdit = true;
char c;
if (result.length() > 0) {
c = result.charAt(0);
allowEdit &= (c >= '0' && c <= '2');
}
if (result.length() > 1) {
c = result.charAt(1);
if(result.charAt(0) == '0' || result.charAt(0) == '1')
allowEdit &= (c >= '0' && c <= '9');
else
allowEdit &= (c >= '0' && c <= '3');
}
if (result.length() > 2) {
c = result.charAt(2);
allowEdit &= (c == ':');
}
if (result.length() > 3) {
c = result.charAt(3);
allowEdit &= (c >= '0' && c <= '5');
}
if (result.length() > 4) {
c = result.charAt(4);
allowEdit &= (c >= '0' && c <= '9');
}
return allowEdit ? null : "";
}
};
EditText txt1 = (EditText) findViewById(R.id.edTxtParcelDeliverTime);
txt1.setFilters(new InputFilter[]{timeFilter});
}
}
我刚把你的XML放在我的主电源布局中 并且XML没有变化 现在尝试一下并告诉?
编辑2 现在,我已经使用doneOnce布尔值为firs char check添加了一个验证 这现在有效,请告诉我你现在的代码是否有任何其他问题
public class MainActivity extends Activity {
EditText edt1;
InputFilter timeFilter;
private String LOG_TAG = "MainActivity";
private boolean doneOnce = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
timeFilter = new InputFilter() {
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest,
int dstart, int dend) {
if(source.length() > 1 && doneOnce == false){
source = source.subSequence(source.length()-1, source.length());
if(source.charAt(0) >= '0' && source.charAt(0) <= '2'){
doneOnce = true;
return source;
}else{
return "";
}
}
if (source.length() == 0) {
return null;// deleting, keep original editing
}
String result = "";
result += dest.toString().substring(0, dstart);
result += source.toString().substring(start, end);
result += dest.toString().substring(dend, dest.length());
if (result.length() > 5) {
return "";// do not allow this edit
}
boolean allowEdit = true;
char c;
if (result.length() > 0) {
c = result.charAt(0);
allowEdit &= (c >= '0' && c <= '2');
}
if (result.length() > 1) {
c = result.charAt(1);
if(result.charAt(0) == '0' || result.charAt(0) == '1')
allowEdit &= (c >= '0' && c <= '9');
else
allowEdit &= (c >= '0' && c <= '3');
}
if (result.length() > 2) {
c = result.charAt(2);
allowEdit &= (c == ':');
}
if (result.length() > 3) {
c = result.charAt(3);
allowEdit &= (c >= '0' && c <= '5');
}
if (result.length() > 4) {
c = result.charAt(4);
allowEdit &= (c >= '0' && c <= '9');
}
return allowEdit ? null : "";
}
};
edt1 = (EditText) findViewById(R.id.edTxtParcelDeliverTime);
edt1.setFilters(new InputFilter[] { timeFilter });
}
}
答案 2 :(得分:0)
试试这个,我只是编辑了你提供的代码....
InputFilter[] timeFilter = new InputFilter[1];
timeFilter[0] = new InputFilter() {
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
if (source.length() == 0) {
return null;// deleting, keep original editing
}
String result = "";
result += dest.toString().substring(0, dstart);
result += source.toString().substring(start, end);
result += dest.toString().substring(dend, dest.length());
if (result.length() > 5) {
return "";// do not allow this edit
}
boolean allowEdit = true;
char c;
if (result.length() > 0) {
c = result.charAt(0);
allowEdit &= (c >= '0' && c <= '2' && !(Character.isLetter(c)));
}
if (result.length() > 1) {
c = result.charAt(1);
allowEdit &= (c >= '0' && c <= '9' && !(Character.isLetter(c)));
}
if (result.length() > 2) {
c = result.charAt(2);
allowEdit &= (c == ':'&&!(Character.isLetter(c)));
}
if (result.length() > 3) {
c = result.charAt(3);
allowEdit &= (c >= '0' && c <= '5' && !(Character.isLetter(c)));
}
if (result.length() > 4) {
c = result.charAt(4);
allowEdit &= (c >= '0' && c <= '9'&& !(Character.isLetter(c)));
}
return allowEdit ? null : "";
}
};
这对我来说绝对没问题。仅接受hh:mm
格式的时间(不接受其他字符)
答案 3 :(得分:0)
我找到了this library的时间EditText
。
代码易于使用。我从代码所有者那里添加了一些解释:
要输入的自定义EditText(实际上是从TextView派生的) 时间为24小时格式。 特点:
- 它始终显示当前设置的时间,因此它永远不会为空。
可以使用虚拟和物理键盘。
当前数字突出显示;
按下键盘上的数字时,数字会被替换。
后退键向后移动光标。
- 空格键移动光标 前进。
以下是TimeEditText
类:
public class TimeEditText extends TextView {
private static final int POSITION_NONE = -1;
private int[] digits = new int[4];
private int currentPosition = POSITION_NONE;
private int mImeOptions;
public TimeEditText(Context context) {
this(context, null, 0);
}
public TimeEditText(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TimeEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setFocusableInTouchMode(true);
if (attrs != null && !isInEditMode()) {
mImeOptions = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "imeOptions", 0);
}
updateText();
}
/**
* @return the current hour (from 0 to 23)
*/
public int getHour() {
return digits[0]*10+digits[1];
}
/**
* @return the current minute
*/
public int getMinutes() {
return digits[2]*10+digits[3];
}
/**
* Set the current hour
* @param hour hour (from 0 to 23)
*/
public void setHour(int hour) {
hour = hour % 24;
digits[0] = hour/10;
digits[1] = hour%10;
updateText();
}
/**
* Set the current minute
* @param min minutes (from 0 to 59)
*/
public void setMinutes(int min) {
min = min % 60;
digits[2] = min/10;
digits[3] = min%10;
updateText();
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
// hide cursor if not focused
currentPosition = focused ? 0 : POSITION_NONE;
updateText();
super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
private void updateText() {
int bold = currentPosition > 1 ? currentPosition+1 : currentPosition;
int color = getTextColors().getDefaultColor();
Spannable text = new SpannableString(String.format("%02d:%02d", getHour(), getMinutes()));
if (bold >= 0) {
text.setSpan(new ForegroundColorSpan(color & 0xFFFFFF | 0xA0000000), 0, 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
text.setSpan(new StyleSpan(Typeface.BOLD), bold, bold+1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
text.setSpan(new ForegroundColorSpan(Color.BLACK), bold, bold+1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
text.setSpan(new BackgroundColorSpan(0x40808080), bold, bold+1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
setText(text);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
requestFocusFromTouch();
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(this,0);
if (currentPosition == POSITION_NONE) {
currentPosition = 0;
updateText();
}
}
return true;
}
private boolean onKeyEvent(int keyCode, KeyEvent event) {
if (event != null && event.getAction() != KeyEvent.ACTION_DOWN)
return false;
if (keyCode == KeyEvent.KEYCODE_DEL) {
// moves cursor backward
currentPosition = currentPosition >= 0 ? (currentPosition+3)%4 : 3;
updateText();
return true;
}
if (keyCode == KeyEvent.KEYCODE_SPACE) {
// moves cursor forward
currentPosition = (currentPosition+1)%4;
updateText();
return true;
}
if (keyCode == KeyEvent.KEYCODE_ENTER) {
View v = focusSearch(FOCUS_DOWN);
boolean next = v!=null;
if (next) {
next = v.requestFocus(FOCUS_DOWN);
}
if (!next) {
hideKeyboard();
currentPosition = POSITION_NONE;
updateText();
}
return true;
}
char c = (char) event.getUnicodeChar();
if (c >= '0' && c <= '9') {
currentPosition = currentPosition == POSITION_NONE ? 0 : currentPosition;
int n = c - '0';
boolean valid = false;
switch (currentPosition) {
case 0: // first hour digit must be 0-2
valid = n <= 2;
break;
case 1: // second hour digit must be 0-3 if first digit is 2
valid = digits[0] < 2 || n <= 3;
break;
case 2: // first minute digit must be 0-6
valid = n < 6;
break;
case 3: // second minuti digit always valid (0-9)
valid = true;
break;
}
if (valid) {
if (currentPosition == 0 && n == 2 && digits[1] > 3) { // clip to 23 hours max
digits[1] = 3;
}
digits[currentPosition] = n;
currentPosition = currentPosition < 3 ? currentPosition+1 : POSITION_NONE; // if it is the last digit, hide cursor
updateText();
}
return true;
}
return false;
}
private void hideKeyboard() {
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindowToken(), 0);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// events from physical keyboard
return onKeyEvent(keyCode, event);
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
// manage events from the virtual keyboard
outAttrs.actionLabel = null;
outAttrs.label = "time";
outAttrs.inputType = InputType.TYPE_CLASS_NUMBER;
outAttrs.imeOptions = mImeOptions | EditorInfo.IME_FLAG_NO_EXTRACT_UI;
if ((outAttrs.imeOptions & EditorInfo.IME_MASK_ACTION) == EditorInfo.IME_ACTION_UNSPECIFIED) {
if (focusSearch(FOCUS_DOWN) != null) {
outAttrs.imeOptions |= EditorInfo.IME_ACTION_NEXT;
} else {
outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE;
}
}
return new BaseInputConnection(this, false) {
@Override
public boolean performEditorAction(int actionCode) {
if (actionCode == EditorInfo.IME_ACTION_DONE) {
hideKeyboard();
currentPosition = POSITION_NONE;
updateText();
} else if (actionCode == EditorInfo.IME_ACTION_NEXT){
View v = focusSearch(FOCUS_DOWN);
if (v!=null) {
v.requestFocus(FOCUS_DOWN);
}
}
return true;
}
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
onKeyEvent(KeyEvent.KEYCODE_DEL, null);
return true;
}
@Override
public boolean sendKeyEvent(KeyEvent event) {
onKeyEvent(event.getKeyCode(), event);
return true;
}
};
}
}
您必须将此行添加到视图中:
<YourPackageName.TimeEditText
android:id="@+id/satOpenEditText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:ems="10"
android:inputType="time"
android:textSize="16sp" />
答案 4 :(得分:0)
//这会在运行时处理日期和时间的输入,并且所有//无效的atttempt都会自动消耗 //这是你可以实现的正则表达式的替代方法
//using the input regulation for the time data
timeField.addTextChangedListener(new TextWatcher() {
String beforeTXT;
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
Log.i("before TEXT TEXXT", " this : "+s+" and "+start+" and "+count+"and "+after);
beforeTXT= ""+s;
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
int input ;
//first determine whether user is at hrs side or min side
if (s.toString().equals("")){
return;
}
if(s.toString().length()>2 && start<=2){ //means the user is at hour side
input = Integer.parseInt(s.toString().substring(0,1)) % 10;
}
else if(s.toString().length()>2 && start>=3) {//means that user is at min side
input = Integer.parseInt("0"+s.toString().substring(3))%10;
}
else if(s.toString().indexOf(":")==1){ // if we have for eg 1: or 0: then we take first character for parsing
input = Integer.parseInt(s.toString().charAt(0)+"");
}
else{ //else it is default where the user is at first position
input = Integer.parseInt(s.toString()) % 10;
}
//Special case where 00: is autommatically converted to 12: in 12hr time format
if(s.toString().contains("00:")){
Log.i("INsisde )))","i am called ");
timeField.setText("12:");
return;
}
//Now we manipulate the input and its formattin and cursor movement
if(input<=1 && start ==0){ //thiis is for first input value to check .... time shouldnt exceed 12 hr
//do nothing
}
else if (input>1 && start==0){ //if at hour >1 is press then automaticc set the time as 02: or 05: etc
timeField.setText("0"+s+":");
}
else if(input>2 && start==1 && !s.toString().startsWith("0")){ //whe dont have greater than 12 hrs so second postionn shouldn't exceed value 2
timeField.setText(beforeTXT);
}
else if(start==1 && !beforeTXT.contains(":")){ //if valid input 10 or 11 or 12 is given then convert it to 10: 11: or 12:
timeField.setText(s.toString()+":");
if(s.toString().length()==1 && s.toString().startsWith("0")){
timeField.setText("");
}
if(s.toString().startsWith("1")&& s.toString().length()==1){ //on back space convert 1: to 01:
timeField.setText("0"+timeField.getText().toString());
}
}
else if(start == 3 && input >5 ){ //min fig shouldn't exceed 59 so ...if at first digit of min input >5 then do nothing or codpy the earlier text
timeField.setText(beforeTXT);
}
else if (start>4 && s.toString().length()>5){ // the total string lenght shouldn't excced 5
timeField.setText(beforeTXT);
}
else if(start<2 && beforeTXT.length()>2){
timeField.setText(beforeTXT);
}
}
@Override
public void afterTextChanged(Editable s) {
Log.i("after TEXT TEXXT", " this : "+s);
timeField.setSelection(timeField.getText().toString().length());
}
});