9

我必须允许用户在即时编辑文本中以##:## 格式输入时间,有什么方法可以实现吗?我使用了下面的代码,但它不起作用。

我可以输入超过 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包含其先前的字符值。

4

5 回答 5

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。

于 2012-10-29T12:02:47.537 回答
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 布尔值对第一个字符检查的验证现在可以使用,告诉我你现在是否有任何其他问题

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 });

}
}
于 2012-10-29T12:34:58.127 回答
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(不接受其他字符)

于 2014-03-22T21:02:57.770 回答
0

//这是在运行时处理日期和时间的输入,并且所有 //无效的尝试都会自动消耗
//这是您可以实现的正则表达式的替代方案

//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());

        }
    });
于 2018-04-16T11:15:14.013 回答
0

我找到了这个图书馆时间EditText。该代码易于使用。我添加了代码所有者的一些解释:

一个自定义的 EditText(实际上是从 TextView 派生的)以 24 小时格式输入时间。特点:
- 它总是显示当前设置的时间,所以它永远不会为空。

  • 可以使用虚拟键盘和物理键盘。

  • 当前数字突出显示;

  • 当键盘上的数字被按下时,数字被替换。

  • Back 键向后移动光标。

  • 空格键向前移动光标。

这是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" />
于 2018-01-08T10:26:12.817 回答