代码之家  ›  专栏  ›  技术社区  ›  Jayesh

android中格式为(XXX)XXX-XXXX ext.XXXXXX的屏蔽编辑文本?

  •  -2
  • Jayesh  · 技术社区  · 7 年前

    我怎样才能掩饰 EditText 在android中使用以下格式?

    (XXX) XXX-XXXX ext.XXXXXX i.e (654) 321-5846 ext.654321
    

    在自定义编辑文本类下面使用

    package com.test.PhoneNumberFormatter;
        import android.content.Context;
        import android.content.res.TypedArray;
        import android.os.Bundle;
        import android.os.Parcelable;
        import android.support.v7.widget.AppCompatEditText;
        import android.text.Editable;
        import android.text.SpannableStringBuilder;
        import android.text.TextWatcher;
        import android.text.style.ForegroundColorSpan;
        import android.util.AttributeSet;
        import android.util.Log;
        import android.view.KeyEvent;
        import android.view.View;
        import android.widget.TextView;
        import com.test.R;
        import static android.content.ContentValues.TAG;
        public class MaskedEditText extends AppCompatEditText implements TextWatcher {
        public static final String SPACE = " ";
        private String mask;
        private char charRepresentation;
        private boolean keepHint;
        private int[] rawToMask;
        private RawText rawText;
        private boolean editingBefore;
        private boolean editingOnChanged;
        private boolean editingAfter;
        private int[] maskToRaw;
        private int selection;
        private boolean initialized;
        private boolean ignore;
        protected int maxRawLength;
        private int lastValidMaskPosition;
        private boolean selectionChanged;
        private OnFocusChangeListener focusChangeListener;
        private String allowedChars;
        private String deniedChars;
    
    
        public MaskedEditText(Context context) {
            super(context);
            init();
        }
    
        public MaskedEditText(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
    
            TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.MaskedEditText);
            mask = attributes.getString(R.styleable.MaskedEditText_mask);
    
            allowedChars = attributes.getString(R.styleable.MaskedEditText_allowed_chars);
            deniedChars = attributes.getString(R.styleable.MaskedEditText_denied_chars);
    
            String representation = attributes.getString(R.styleable.MaskedEditText_char_representation);
    
            if (representation == null) {
                charRepresentation = '#';
            } else {
                charRepresentation = representation.charAt(0);
            }
    
            keepHint = attributes.getBoolean(R.styleable.MaskedEditText_keep_hint, false);
    
            cleanUp();
    
            // Ignoring enter key presses
            setOnEditorActionListener(new OnEditorActionListener() {
                @Override
                public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                    switch (actionId) {
    //              case EditorInfo.IME_ACTION_NEXT:
                        // fixing actionNext
    //                  return false;
                        default:
                            return true;
                    }
                }
            });
            attributes.recycle();
        }
    
        @Override
        public Parcelable onSaveInstanceState() {
            final Parcelable superParcellable = super.onSaveInstanceState();
            final Bundle state = new Bundle();
            state.putParcelable("super", superParcellable);
            state.putString("text", getRawText());
            state.putBoolean("keepHint", isKeepHint());
            return state;
        }
    
        @Override
        public void onRestoreInstanceState(Parcelable state) {
            Bundle bundle = (Bundle) state;
            keepHint = bundle.getBoolean("keepHint", false);
            super.onRestoreInstanceState(((Bundle) state).getParcelable("super"));
            final String text = bundle.getString("text");
    
            setText(text);
            Log.d(TAG, "onRestoreInstanceState: " + text);
        }
    
        @Override
        public void setText(CharSequence text, BufferType type) {
    //      if (text == null || text.equals("")) return;
            super.setText(text, type);
        }
    
        /**
         * @param listener - its onFocusChange() method will be called before performing MaskedEditText operations,
         *                 related to this event.
         */
        @Override
        public void setOnFocusChangeListener(OnFocusChangeListener listener) {
            focusChangeListener = listener;
        }
    
        private void cleanUp() {
            initialized = false;
    
            generatePositionArrays();
    
            rawText = new RawText();
            selection = rawToMask[0];
    
            editingBefore = true;
            editingOnChanged = true;
            editingAfter = true;
            if (hasHint() && rawText.length() == 0) {
                this.setText(makeMaskedTextWithHint());
            } else {
                this.setText(makeMaskedText());
            }
            editingBefore = false;
            editingOnChanged = false;
            editingAfter = false;
    
            maxRawLength = maskToRaw[previousValidPosition(mask.length() - 1)] + 1;
            lastValidMaskPosition = findLastValidMaskPosition();
            initialized = true;
    
            super.setOnFocusChangeListener(new OnFocusChangeListener() {
                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    if (focusChangeListener != null) {
                        focusChangeListener.onFocusChange(v, hasFocus);
                    }
    
                    if (hasFocus()) {
                        selectionChanged = false;
                        MaskedEditText.this.setSelection(lastValidPosition());
                    }
                }
            });
        }
    
        private int findLastValidMaskPosition() {
            for (int i = maskToRaw.length - 1; i >= 0; i--) {
                if (maskToRaw[i] != -1) return i;
            }
            throw new RuntimeException("Mask must contain at least one representation char");
        }
    
        private boolean hasHint() {
            return getHint() != null;
        }
    
        public MaskedEditText(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init();
        }
    
        public void setMask(String mask) {
            this.mask = mask;
            cleanUp();
        }
    
        public String getMask() {
            return this.mask;
        }
    
        public String getRawText() {
            return this.rawText.getText();
        }
    
        public void setCharRepresentation(char charRepresentation) {
            this.charRepresentation = charRepresentation;
            cleanUp();
        }
    
        public char getCharRepresentation() {
            return this.charRepresentation;
        }
    
        /**
         * Generates positions for values characters. For instance:
         * Input data: mask = "+7(###)###-##-##
         * After method execution:
         * rawToMask = [3, 4, 5, 6, 8, 9, 11, 12, 14, 15]
         * maskToRaw = [-1, -1, -1, 0, 1, 2, -1, 3, 4, 5, -1, 6, 7, -1, 8, 9]
         * charsInMask = "+7()- " (and space, yes)
         */
        private void generatePositionArrays() {
            int[] aux = new int[mask.length()];
            maskToRaw = new int[mask.length()];
            String charsInMaskAux = "";
    
            int charIndex = 0;
            for (int i = 0; i < mask.length(); i++) {
                char currentChar = mask.charAt(i);
                if (currentChar == charRepresentation) {
                    aux[charIndex] = i;
                    maskToRaw[i] = charIndex++;
                } else {
                    String charAsString = Character.toString(currentChar);
                    if (!charsInMaskAux.contains(charAsString)) {
                        charsInMaskAux = charsInMaskAux.concat(charAsString);
                    }
                    maskToRaw[i] = -1;
                }
            }
            if (charsInMaskAux.indexOf(' ') < 0) {
                charsInMaskAux = charsInMaskAux + SPACE;
            }
    
            char[] charsInMask = charsInMaskAux.toCharArray();
    
            rawToMask = new int[charIndex];
            for (int i = 0; i < charIndex; i++) {
                rawToMask[i] = aux[i];
            }
        }
    
        private void init() {
            addTextChangedListener(this);
        }
    
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                                      int after) {
            if (!editingBefore) {
                editingBefore = true;
                if (start > lastValidMaskPosition) {
                    ignore = true;
                }
                int rangeStart = start;
                if (after == 0) {
                    rangeStart = erasingStart(start);
                }
                Range range = calculateRange(rangeStart, start + count);
                if (range.getStart() != -1) {
                    rawText.subtractFromString(range);
                }
                if (count > 0) {
                    selection = previousValidPosition(start);
                }
            }
        }
    
        private int erasingStart(int start) {
            while (start > 0 && maskToRaw[start] == -1) {
                start--;
            }
            return start;
        }
    
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            if (!editingOnChanged && editingBefore) {
                editingOnChanged = true;
                if (ignore) {
                    return;
                }
                if (count > 0) {
                    int startingPosition = maskToRaw[nextValidPosition(start)];
                    String addedString = s.subSequence(start, start + count).toString();
                    count = rawText.addToString(clear(addedString), startingPosition, maxRawLength);
                    if (initialized) {
                        int currentPosition;
                        if (startingPosition + count < rawToMask.length)
                            currentPosition = rawToMask[startingPosition + count];
                        else
                            currentPosition = lastValidMaskPosition + 1;
                        selection = nextValidPosition(currentPosition);
                    }
                }
            }
        }
    
        @Override
        public void afterTextChanged(Editable s) {
            if (!editingAfter && editingBefore && editingOnChanged) {
                editingAfter = true;
                if (hasHint() && (keepHint || rawText.length() == 0)) {
                    setText(makeMaskedTextWithHint());
                } else {
                    setText(makeMaskedText());
                }
    
                selectionChanged = false;
                setSelection(selection);
    
                editingBefore = false;
                editingOnChanged = false;
                editingAfter = false;
                ignore = false;
            }
        }
    
        public boolean isKeepHint() {
            return keepHint;
        }
    
        public void setKeepHint(boolean keepHint) {
            this.keepHint = keepHint;
            setText(getRawText());
        }
    
        @Override
        protected void onSelectionChanged(int selStart, int selEnd) {
            // On Android 4+ this method is being called more than 1 time if there is a hint in the EditText, what moves the cursor to left
            // Using the boolean var selectionChanged to limit to one execution
    
            if (initialized) {
                if (!selectionChanged) {
                    selStart = fixSelection(selStart);
                    selEnd = fixSelection(selEnd);
    
                    // exactly in this order. If getText.length() == 0 then selStart will be -1
                    if (selStart > getText().length()) selStart = getText().length();
                    if (selStart < 0) selStart = 0;
    
                    // exactly in this order. If getText.length() == 0 then selEnd will be -1
                    if (selEnd > getText().length()) selEnd = getText().length();
                    if (selEnd < 0) selEnd = 0;
    
                    setSelection(selStart, selEnd);
                    selectionChanged = true;
                } else {
                    //check to see if the current selection is outside the already entered text
                    if (selStart > rawText.length() - 1) {
                        final int start = fixSelection(selStart);
                        final int end = fixSelection(selEnd);
                        if (start >= 0 && end < getText().length()) {
                            setSelection(start, end);
                        }
                    }
                }
            }
            super.onSelectionChanged(selStart, selEnd);
        }
    
        private int fixSelection(int selection) {
            if (selection > lastValidPosition()) {
                return lastValidPosition();
            } else {
                return nextValidPosition(selection);
            }
        }
    
        private int nextValidPosition(int currentPosition) {
            while (currentPosition < lastValidMaskPosition && maskToRaw[currentPosition] == -1) {
                currentPosition++;
            }
            if (currentPosition > lastValidMaskPosition) return lastValidMaskPosition + 1;
            return currentPosition;
        }
    
        private int previousValidPosition(int currentPosition) {
            while (currentPosition >= 0 && maskToRaw[currentPosition] == -1) {
                currentPosition--;
                if (currentPosition < 0) {
                    return nextValidPosition(0);
                }
            }
            return currentPosition;
        }
    
        private int lastValidPosition() {
            if (rawText.length() == maxRawLength) {
                return rawToMask[rawText.length() - 1] + 1;
            }
            return nextValidPosition(rawToMask[rawText.length()]);
        }
    
    
        private String makeMaskedText() {
            int maskedTextLength;
            if (rawText.length() < rawToMask.length) {
                maskedTextLength = rawToMask[rawText.length()];
            } else {
                maskedTextLength = mask.length();
            }
            char[] maskedText = new char[maskedTextLength]; //mask.replace(charRepresentation, ' ').toCharArray();
            for (int i = 0; i < maskedText.length; i++) {
                int rawIndex = maskToRaw[i];
                if (rawIndex == -1) {
                    maskedText[i] = mask.charAt(i);
                } else {
                    maskedText[i] = rawText.charAt(rawIndex);
                }
            }
            return new String(maskedText);
        }
    
        private CharSequence makeMaskedTextWithHint() {
            SpannableStringBuilder ssb = new SpannableStringBuilder();
            int mtrv;
            int maskFirstChunkEnd = rawToMask[0];
            for (int i = 0; i < mask.length(); i++) {
                mtrv = maskToRaw[i];
                if (mtrv != -1) {
                    if (mtrv < rawText.length()) {
                        ssb.append(rawText.charAt(mtrv));
                    } else {
                        ssb.append(getHint().charAt(maskToRaw[i]));
                    }
                } else {
                    ssb.append(mask.charAt(i));
                }
                if ((keepHint && rawText.length() < rawToMask.length && i >= rawToMask[rawText.length()])
                        || (!keepHint && i >= maskFirstChunkEnd)) {
                    ssb.setSpan(new ForegroundColorSpan(getCurrentHintTextColor()), i, i + 1, 0);
                }
            }
            return ssb;
        }
    
        private Range calculateRange(int start, int end) {
            Range range = new Range();
            for (int i = start; i <= end && i < mask.length(); i++) {
                if (maskToRaw[i] != -1) {
                    if (range.getStart() == -1) {
                        range.setStart(maskToRaw[i]);
                    }
                    range.setEnd(maskToRaw[i]);
                }
            }
            if (end == mask.length()) {
                range.setEnd(rawText.length());
            }
            if (range.getStart() == range.getEnd() && start < end) {
                int newStart = previousValidPosition(range.getStart() - 1);
                if (newStart < range.getStart()) {
                    range.setStart(newStart);
                }
            }
            return range;
        }
    
        private String clear(String string) {
            if (deniedChars != null) {
                for (char c : deniedChars.toCharArray()) {
                    string = string.replace(Character.toString(c), "");
                }
            }
    
            if (allowedChars != null) {
                StringBuilder builder = new StringBuilder(string.length());
    
                for (char c : string.toCharArray()) {
                    if (allowedChars.contains(String.valueOf(c))) {
                        builder.append(c);
                    }
                }
    
                string = builder.toString();
            }
    
            return string;
        }
        }
    

    <com.test.PhoneNumberFormatter.MaskedEditText
        android:id="@+id/phone_input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        android:hint="@string/phone_number"
        android:imeOptions="actionNext"
        android:inputType="textPhonetic"
        android:paddingBottom="@dimen/_3sdp"
        android:paddingTop="@dimen/_8sdp"
        android:textColorHint="@color/grey_color"
        android:textSize="@dimen/_12sdp"
        mask:allowed_chars="1234567890ext."
        mask:keep_hint="false"
        mask:mask="(###)###-#### ext.######" />
    

    谢谢

    3 回复  |  直到 7 年前
        1
  •  1
  •   Topsy    7 年前

    对于格式编辑文本,下面的内容可能对您有所帮助。

     **Step 1** : Add following line in your build.gradle file
    
      implementation 'com.github.pinball83:masked-edittext:1.0.4'
    
     **Step 2 :**  by xml :
    
     <com.github.pinball83.maskededittext.MaskedEditText
                android:id="@+id/masked_edit_text"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:inputType="number"
                app:mask="8 (***) *** **-**"
                app:notMaskedSymbol="*"
                app:maskIcon="@drawable/abc_ic_clear_mtrl_alpha"
                app:maskIconColor="@color/colorPrimary"
                />
    

     MaskedEditText maskedEditText = new MaskedEditText.Builder(context)
            .mask("8 (***) *** **-**")
            .notMaskedSymbol("*")
            .icon(R.drawable.ic_account_circle)
            .iconCallback(unmaskedText -> { //Icon click callback handler })
            .build();
    
    
    
     MaskedEditText editText = new MaskedEditText.Builder(context)
            .mask("8 (***) *** **-**")
            .notMaskedSymbol("*")
            .build();; //set mask to "8 (***) *** **-**" and not masked symbol to "*"
    

    文本设置和格式

        MaskedEditText editText = new MaskedEditText..Builder(context)
            .mask("8 (***) *** **-**")
            .notMaskedSymbol("*")
            .format("[1][2][3] [4][5][6]-[7][8]-[10][9]")//set format of returned data input into MaskedEditText
            .build();
    

    setMaskedText(“5551235567”);

    https://github.com/pinball83/Masked-Edittext

        2
  •  0
  •   Sz-Nika Janos    7 年前

    步骤1:创建编辑文本

    <EditText
        android:id="@+id/masked_edit_text"
        android:layout_width="yourSize"
        android:layout_height="yourSize"
        android:inputType="textPassword"/>
    

    步骤2:

     public class CustomTransformation  extends PasswordTransformationMethod {
      @Override
      public CharSequence getTransformation(CharSequence source, View view) {
        return new TransformedSequence(source);
    }
    
    private class TransformedSequence implements CharSequence {
    
        private CharSequence sequence;
    
        public TransformedSequence(CharSequence source) {
            sequence = source; // Store char sequence
        }
        public char charAt(int index) {
            return 'X'; //  Replace with what you want.
        }
        public int length() {
            return sequence.length(); // return the length
        }
        public CharSequence subSequence(int start, int end) {
            return sequence.subSequence(start, end); //return  sequence
        }
    }
    

    步骤3:应用转换

    EditText edittext = findViewById(R.id.masked_edit_text);
    edittext.setTransformationMethod(new CustomTransformation());
    
        3
  •  0
  •   Muhammad Ahsan    7 年前