how to avoid editing specific character in a edit text

Viewed 317

I have a string like this 08:12:01,868 -> hour:minute:second,millisecond

now I need to edit this, I must give an option to edit first two character skip one for : then allow edit next two character again skip : and so on.

Currently I'm achieving this with lot of logic behind. I have four edit text and I'm splitting the string, then loading values in 4 edit texts and retrieving it. After joining all the edited sub strings I'm saving the value in DB.

Is there any other better way to achieve this.

I mean I'll load the string in only one edit text, Then I should be able to lock specific characters like lockFromEditChar(":",",") and remaining values can be edited with default value zero if they clear all the character.

Is it possible ? or any other best alternatives ?

2 Answers

The technique is called Masking. Create this class MaskWatcher like this

import android.text.Editable;
import android.text.TextWatcher;

public class MaskWatcher implements TextWatcher {
    private boolean isRunning = false;
    private boolean isDeleting = false;
    private final String mask;

    public MaskWatcher(String mask) {
        this.mask = mask;
    }

    @Override
    public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
        isDeleting = count > after;
    }

    @Override
    public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
    }

    @Override
    public void afterTextChanged(Editable editable) {
        if (isRunning || isDeleting) {
            return;
        }
        isRunning = true;

        int editableLength = editable.length();
        if (editableLength < mask.length()) {
            if (mask.charAt(editableLength) != '#') {
                editable.append(mask.charAt(editableLength));
            } else if (mask.charAt(editableLength-1) != '#') {
                editable.insert(editableLength-1, mask, editableLength-1, editableLength);
            }
        }

        isRunning = false;
    }
}

and than use your edittext like this

editText.addTextChangedListener(MaskWatcher("##:##:##,###"));

If you have the cursor blocked in the last position and longClick disabled(copy paste):

Note that this example works only for strings, no spans

Create a TextWatcher and auto add : and , when you detect a new character added and the new size is 2,4(for ':'),6(for ',').

Also detect when you delete a character and the current size is 2,4,6, you have to delete the character before ';' or ',' as well.

class Watcher(private val textView:TextView) : TextWatcher {

    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
         val text = s?.toString()?:""
         val isDelete = textView.length > text.size
         if(isDelete) {
              //you can change this to an if to check for 2,4,6 and use take(size-1)
              newString = when(text.size) {
                  2->text.take(1)
                  4->text.take(3)
                  6->text.take(5)
              }
              if(newString!=null) {
                  textView.text = newString
              }
         } else {
              newString = when(text.size) {
                  2,4 -> text + ":"
                  6 -> text + ","
              }
              if(newString!=null) {
                  textView.text = newString
              }
         }
    }

}
Related