I have to allow user to input only time in ##:## format in edit text on the fly, is there any way to achieve it? I have used below code but it doest not working.
I a
I found this library for time EditText.
The code is easy to use. I add some explanations from the code owner:
A custom EditText (actually derived from TextView) to input time in 24h format. Features:
- It always shows the currently set time, so it's never empty.
Both virtual and physical keyboards can be used.
The current digit is highlighted;
when a number on the keyboard is pressed, the digit is replaced.
Back key moves the cursor backward.
- Space key moves the cursor forward.
Here is the TimeEditText Class:
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;
}
};
}
}
You must add this lines to your view: