如何使用单个EditText实现此布局

时间:2016-02-14 10:12:30

标签: android android-layout android-edittext

如何使用单个EditText实现此类编辑文本。 enter image description here

我在我的应用中验证otp时使用此编辑文字。

我可以使用6个编辑文本来执行此操作,例如 my_layout.xml 是否可以使用单个编辑文本来做这件事。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:wheel="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="To complete the installation,\nplease enter the 6-digit\nverification code."
            android:id="@+id/textView4"
            android:textColor="@color/black"
            android:gravity="center" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center">
        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxLength="1"
            android:gravity="center" />
        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxLength="1"
            android:gravity="center" />
        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxLength="1"
            android:gravity="center" />
        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxLength="1"
            android:layout_marginLeft="15dp"
            android:gravity="center" />
        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxLength="1"
            android:gravity="center" />
        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxLength="1"
            android:gravity="center" />
    </LinearLayout>

</LinearLayout>

2 个答案:

答案 0 :(得分:2)

你必须实现TextWacher并一次删除它们,你的EditText看起来像这样

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/editText"
    android:singleLine="true"
    android:text="______"
    android:inputType = "textNoSuggestions"
    android:letterSpacing="0.4" -->Its the spacing of letter
    android:textSize="29sp" />

这是实施

EditText editText;
String text;
boolean delete = false;

    text = editText.getText().toString();

    editText.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            text = editText.getText().toString();
            if (count > after)
                delete = true;

        }

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

            StringBuilder sb = new StringBuilder(s.toString());
            int replacePosition = editText.getSelectionEnd();

            if (s.length() != 6) { //where 6 is the character underline per text
                if (!delete) {
                    if (replacePosition < s.length())
                        sb.deleteCharAt(replacePosition);
                } else {
                    sb.insert(replacePosition, '_');
                }

                if (replacePosition < s.length() || delete) {
                        editText.setText(sb.toString());
                        editText.setSelection(replacePosition);
                } else {
                        editText.setText(text);
                        editText.setSelection(replacePosition - 1);
                }
            }
        }
        delete = false;
    }
    @Override
    public void afterTextChanged(Editable s) {
    }
});

答案 1 :(得分:-1)

我认为为时已晚,但是一旦你有时间,你应该试试这个。我希望这能满足你的要求。

pincode_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<LinearLayout android:id="@+id/pin_layout"
    android:layout_width="match_parent"
    android:layout_height="56dp"
    android:orientation="horizontal"
    android:gravity="center_horizontal"
    android:layout_gravity="center_horizontal">

    <EditText android:id="@+id/pin_first_edittext"
        android:layout_width="40dp"
        android:gravity="center"
        android:layout_height="match_parent"
        android:background="@drawable/otp_drawable"
        style="@style/otp_edittext_style" />

    <EditText android:id="@+id/pin_second_edittext"
        android:layout_width="40dp"
        android:layout_marginLeft="11dp"
        android:background="@drawable/otp_drawable"
        android:layout_height="match_parent"
        style="@style/otp_edittext_style" />

    <EditText android:id="@+id/pin_third_edittext"
        android:layout_width="40dp"
        android:layout_marginLeft="11dp"
        android:background="@drawable/otp_drawable"
        android:layout_height="match_parent"
        style="@style/otp_edittext_style" />

    <EditText android:id="@+id/pin_forth_edittext"
        android:layout_width="40dp"
        android:layout_marginLeft="11dp"
        android:background="@drawable/otp_drawable"
        android:layout_height="match_parent"
        style="@style/otp_edittext_style" />
    <EditText android:id="@+id/pin_fifth_edittext"
        android:layout_width="40dp"
        android:layout_marginLeft="11dp"
        android:background="@drawable/otp_drawable"
        android:layout_height="match_parent"
        style="@style/otp_edittext_style" />
    <EditText android:id="@+id/pin_sixth_edittext"
        android:layout_width="40dp"
        android:layout_marginLeft="11dp"
        android:background="@drawable/otp_drawable"
        android:layout_height="match_parent"
        style="@style/otp_edittext_style" />

</LinearLayout>

<EditText android:id="@+id/pin_hidden_edittext"
    android:layout_width="1dp"
    android:layout_height="1dp"
    android:gravity="center_horizontal"
    android:layout_gravity="center_horizontal"
    android:background="@null"
    android:cursorVisible="false"
    android:maxLength="6"
    android:textColor="#00000000"
    android:contentDescription="@string/pin_content_desc" />

PinCodeLayout.java

 import android.app.Service;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.support.annotation.Nullable;
 import android.text.Editable;
 import android.text.TextWatcher;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.EditText;
 import android.widget.LinearLayout;

 import com.elanic.R;
 import com.elanic.utils.StringUtils;

/**
  * Created by sandeep on 8/19/2017.
*/

public class PinCodeLayout extends LinearLayout implements 
View.OnFocusChangeListener, View.OnKeyListener, TextWatcher {
private EditText mPinFirstDigitEditText;
private EditText mPinSecondDigitEditText;
private EditText mPinThirdDigitEditText;
private EditText mPinForthDigitEditText;
private EditText mPinFifthDigitEditText;
private EditText mPinSixthDigitEditText;
private EditText mPinHiddenEditText;
private boolean isManuallyEntering = true;
private String pinCodeText;
private PinCodeCallBack pinCodeCallback;


public PinCodeLayout(Context context) {
    super(context);
    init(context);
}

public PinCodeLayout(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

 public PinCodeLayout(Context context, @Nullable AttributeSet attrs, int 
    defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context);
 }

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int 
  after) {

}

@Override
public void onFocusChange(View v, boolean hasFocus) {
    final int id = v.getId();
    switch (id) {
        case R.id.pin_first_edittext:
            if (hasFocus) {
                setFocus(mPinHiddenEditText);
                showSoftKeyboard(mPinHiddenEditText);
            }
            break;

        case R.id.pin_second_edittext:
            if (hasFocus) {
                setFocus(mPinHiddenEditText);
                showSoftKeyboard(mPinHiddenEditText);
            }
            break;

        case R.id.pin_third_edittext:
            if (hasFocus) {
                setFocus(mPinHiddenEditText);
                showSoftKeyboard(mPinHiddenEditText);
            }
            break;

        case R.id.pin_forth_edittext:
            if (hasFocus) {
                setFocus(mPinHiddenEditText);
                showSoftKeyboard(mPinHiddenEditText);
            }
            break;
        case R.id.pin_fifth_edittext:
            if (hasFocus) {
                setFocus(mPinHiddenEditText);
                showSoftKeyboard(mPinHiddenEditText);
            }
            break;
        case R.id.pin_sixth_edittext:
            if (hasFocus) {
                setFocus(mPinHiddenEditText);
                showSoftKeyboard(mPinHiddenEditText);
            }
            break;
        default:
            break;
    }
 }

@Override
 public boolean onKey(View v, int keyCode, KeyEvent event) {
    if (event.getAction() == KeyEvent.ACTION_DOWN) {
        final int id = v.getId();
        switch (id) {
            case R.id.pin_hidden_edittext:
                if (keyCode == KeyEvent.KEYCODE_DEL) {
                    if (mPinHiddenEditText.getText().length() == 6)
                        mPinSixthDigitEditText.setText("");
                    else if (mPinHiddenEditText.getText().length() == 5)
                        mPinFifthDigitEditText.setText("");
                    else if (mPinHiddenEditText.getText().length() == 4)
                        mPinForthDigitEditText.setText("");
                    else if (mPinHiddenEditText.getText().length() == 3)
                        mPinThirdDigitEditText.setText("");
                    else if (mPinHiddenEditText.getText().length() == 2)
                        mPinSecondDigitEditText.setText("");
                    else if (mPinHiddenEditText.getText().length() == 1)
                        mPinFirstDigitEditText.setText("");

                    if (mPinHiddenEditText.length() > 0) {

             mPinHiddenEditText.setText(mPinHiddenEditText.getText()
              .subSequence(0, mPinHiddenEditText.length() - 1));
                        mPinHiddenEditText.post(new Runnable() {
                            @Override
                            public void run() {
                          mPinHiddenEditText.setSelection(mPinHiddenEditText.
                             getText().toString().length());
                            }
                        });
                    }
                    return true;
                }
            case R.id.pin_first_edittext:
            case R.id.pin_second_edittext:
            case R.id.pin_third_edittext:
            case R.id.pin_forth_edittext:
            case R.id.pin_fifth_edittext:
            case R.id.pin_sixth_edittext:
                if (keyCode == KeyEvent.KEYCODE_0 || keyCode == 
                    KeyEvent.KEYCODE_1 ||
                        keyCode == KeyEvent.KEYCODE_2 || keyCode == 
                    KeyEvent.KEYCODE_3 ||
                        keyCode == KeyEvent.KEYCODE_4 || keyCode == 
                    KeyEvent.KEYCODE_5 ||
                        keyCode == KeyEvent.KEYCODE_6 || keyCode == 
                    KeyEvent.KEYCODE_7 ||
                        keyCode == KeyEvent.KEYCODE_8 || keyCode == 
                    KeyEvent.KEYCODE_9) {
                    isManuallyEntering = true;
                }
                break;

            default:
                return false;
        }
    }

    return false;
}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
    setDefaultPinBackground(mPinFirstDigitEditText);
    setDefaultPinBackground(mPinSecondDigitEditText);
    setDefaultPinBackground(mPinThirdDigitEditText);
    setDefaultPinBackground(mPinForthDigitEditText);
    setDefaultPinBackground(mPinFifthDigitEditText);
    setDefaultPinBackground(mPinSixthDigitEditText);


    if (s.length() == 0) {
        setFocusedPinBackground(mPinFirstDigitEditText);
        mPinFirstDigitEditText.setText("");
        pinCodeText = "";
    } else if (s.length() == 1) {
        setFocusedPinBackground(mPinSecondDigitEditText);
        mPinFirstDigitEditText.setText(s.charAt(0) + "");
        mPinSecondDigitEditText.setText("");
        mPinThirdDigitEditText.setText("");
        mPinForthDigitEditText.setText("");
        mPinFifthDigitEditText.setText("");
        mPinSixthDigitEditText.setText("");
    } else if (s.length() == 2) {
        setFocusedPinBackground(mPinThirdDigitEditText);
        mPinSecondDigitEditText.setText(s.charAt(1) + "");
        mPinThirdDigitEditText.setText("");
        mPinForthDigitEditText.setText("");
        mPinFifthDigitEditText.setText("");
        mPinSixthDigitEditText.setText("");

    } else if (s.length() == 3) {
        setFocusedPinBackground(mPinForthDigitEditText);
        mPinThirdDigitEditText.setText(s.charAt(2) + "");
        mPinForthDigitEditText.setText("");
        mPinFifthDigitEditText.setText("");
        mPinSixthDigitEditText.setText("");

    } else if (s.length() == 4) {
        setFocusedPinBackground(mPinFifthDigitEditText);
        mPinForthDigitEditText.setText(s.charAt(3) + "");
        mPinFifthDigitEditText.setText("");
        mPinSixthDigitEditText.setText("");

    } else if (s.length() == 5) {
        setFocusedPinBackground(mPinSixthDigitEditText);
        mPinFifthDigitEditText.setText(s.charAt(4) + "");
        mPinSixthDigitEditText.setText("");

    } else if (s.length() == 6) {
        mPinSixthDigitEditText.setText(s.charAt(5) + "");
        setDefaultPinBackground(mPinSixthDigitEditText);
        pinCodeText = s.toString();
        hideSoftKeyboard(mPinSixthDigitEditText);
        if (isManuallyEntering) {
            pinCodeCallback.onPinCodeEntered();
        }
    }
}

@Override
public void afterTextChanged(Editable s) {

}


private void init(Context context) {
    LayoutInflater inflater = (LayoutInflater) 
    context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    inflater.inflate(R.layout.pincode_layout, this);
    init();
    setPINListeners();
}

/**
 * Initialize EditText fields.
 */
private void init() {
    mPinFirstDigitEditText = (EditText) 
 findViewById(R.id.pin_first_edittext);
    mPinSecondDigitEditText = (EditText) 
 findViewById(R.id.pin_second_edittext);
    mPinThirdDigitEditText = (EditText) 
 findViewById(R.id.pin_third_edittext);
    mPinForthDigitEditText = (EditText) 
 findViewById(R.id.pin_forth_edittext);
    mPinFifthDigitEditText = (EditText) 
 findViewById(R.id.pin_fifth_edittext);
    mPinSixthDigitEditText = (EditText) 
 findViewById(R.id.pin_sixth_edittext);
    mPinHiddenEditText = (EditText) findViewById(R.id.pin_hidden_edittext);
    isManuallyEntering = true;
}

private void setPINListeners() {
    mPinHiddenEditText.addTextChangedListener(this);

    mPinFirstDigitEditText.setOnFocusChangeListener(this);
    mPinSecondDigitEditText.setOnFocusChangeListener(this);
    mPinThirdDigitEditText.setOnFocusChangeListener(this);
    mPinForthDigitEditText.setOnFocusChangeListener(this);
    mPinFifthDigitEditText.setOnFocusChangeListener(this);
    mPinSixthDigitEditText.setOnFocusChangeListener(this);

    mPinFirstDigitEditText.setOnKeyListener(this);
    mPinSecondDigitEditText.setOnKeyListener(this);
    mPinThirdDigitEditText.setOnKeyListener(this);
    mPinForthDigitEditText.setOnKeyListener(this);
    mPinFifthDigitEditText.setOnKeyListener(this);
    mPinSixthDigitEditText.setOnKeyListener(this);
    mPinHiddenEditText.setOnKeyListener(this);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int proposedHeight = MeasureSpec.getSize(heightMeasureSpec);
    final int actualHeight = getHeight();

    Log.d("TAG", "proposed: " + proposedHeight + ", actual: " + 
    actualHeight);

    if (actualHeight >= proposedHeight) {
        // Keyboard is shown
        if (mPinHiddenEditText.length() == 0)
            setFocusedPinBackground(mPinFirstDigitEditText);
        else
            setDefaultPinBackground(mPinFirstDigitEditText);
    }

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

/**
 * Sets default PIN background.
 *
 * @param editText edit text to change
 */
private void setDefaultPinBackground(EditText editText) {
    setViewBackground(editText, 
  getResources().getDrawable(R.drawable.otp_drawable));
}

/**
 * Sets focus on a specific EditText field.
 *
 * @param editText EditText to set focus on
 */
public static void setFocus(EditText editText) {
    if (editText == null)
        return;

    editText.setFocusable(true);
    editText.setFocusableInTouchMode(true);
    editText.requestFocus();
}

/**
 * Sets focused PIN field background.
 *
 * @param editText edit text to change
 */
private void setFocusedPinBackground(EditText editText) {
    setViewBackground(editText, 
    getResources().getDrawable(R.drawable.otp_drawable));
}

/**
 * Sets background of the view.
 * This method varies in implementation depending on Android SDK version.
 *
 * @param view       View to which set background
 * @param background Background to set to view
 */
@SuppressWarnings("deprecation")
public void setViewBackground(View view, Drawable background) {
    if (view == null || background == null)
        return;

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        view.setBackground(background);
    } else {
        view.setBackgroundDrawable(background);
    }
}

/**
 * Shows soft keyboard.
 *
 * @param editText EditText which has focus
 */
public void showSoftKeyboard(EditText editText) {
    if (editText == null)
        return;

    InputMethodManager imm = (InputMethodManager) 
    getContext().getSystemService(Service.INPUT_METHOD_SERVICE);
    editText.setRawInputType(Configuration.KEYBOARD_12KEY);
    imm.showSoftInput(editText, 0);
    if (pinCodeCallback != null) {
        //  pinCodeCallback.hideProgressBar(false);
    }
}

/**
 * Hides soft keyboard.
 *
 * @param editText EditText which has focus
 */
public void hideSoftKeyboard(EditText editText) {
    if (editText == null)
        return;

    InputMethodManager imm = (InputMethodManager) 
    getContext().getSystemService(Service.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
    if (pinCodeCallback != null) {
        // pinCodeCallback.hideProgressBar(true);
    }
}

public void setData(CharSequence data) {

    if (!StringUtils.isNullOrEmpty(data)) {
        isManuallyEntering = false;
        mPinFirstDigitEditText.setText(String.valueOf(data.charAt(0)));
        mPinHiddenEditText.setText(String.valueOf(data.charAt(0)));
        mPinSecondDigitEditText.setText(String.valueOf(data.charAt(1)));
        mPinHiddenEditText.append(String.valueOf(data.charAt(1)));
        mPinThirdDigitEditText.setText(String.valueOf(data.charAt(2)));
        mPinHiddenEditText.append(String.valueOf(data.charAt(2)));
        mPinForthDigitEditText.setText(String.valueOf(data.charAt(3)));
        mPinHiddenEditText.append(String.valueOf(data.charAt(3)));
        mPinFifthDigitEditText.setText(String.valueOf(data.charAt(4)));
        mPinHiddenEditText.append(String.valueOf(data.charAt(4)));
        mPinSixthDigitEditText.setText(String.valueOf(data.charAt(5)));
        mPinHiddenEditText.append(String.valueOf(data.charAt(5)));

        hideSoftKeyboard(mPinSixthDigitEditText);
        if (pinCodeCallback != null) {
            pinCodeCallback.onPinCodeEntered();
        }
    } else {
        isManuallyEntering = true;
        mPinSixthDigitEditText.setText("");
        mPinFifthDigitEditText.setText("");
        mPinForthDigitEditText.setText("");
        mPinThirdDigitEditText.setText("");
        mPinSecondDigitEditText.setText("");
        mPinFirstDigitEditText.setText("");
        mPinHiddenEditText.setText("");
        setFocus(mPinFirstDigitEditText);
        showSoftKeyboard(mPinFirstDigitEditText);

    }

}

public String getPinCodeText() {
    return pinCodeText;
}

public void setCallBack(PinCodeCallBack pinCodeCallBack) {
    this.pinCodeCallback = pinCodeCallBack;
}

public interface PinCodeCallBack {

    void onPinCodeEntered();

    /**
     * true --> show && false--> hide
     **/
    void hideProgressBar(boolean show);
}
}

otp_drawable.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
android:thickness="0dp">
<corners android:radius="1dp" />
<solid android:color="@color/otpBackgroundColor" />

edittext style

 <style name="otp_edittext_style">
    <item name="android:gravity">center</item>
    <item name="android:cursorVisible">false</item>
    <item name="android:maxLength">1</item>
    <item name="android:minEms">2</item>
    <item name="android:inputType">numberDecimal</item>
    <item name="android:focusable">true</item>
    <item name="android:textSize">18sp</item>
    <item name="android:fontFamily">sans-serif</item>
    <item name="android:textColor">@color/post_description_color</item>
    <item name="android:focusableInTouchMode">true</item>
</style>