edtext 从右边开始输入 安卓_android文本输入框 输入完成自动跳到下一个输入框...

定义文本框 输入完一个自动跳到下一个且获取焦点,当删除一个自动跳到前一个输入框获取焦点

老规矩来一波效果图:

新建NumberCodeView 继承FrameLayout

public class NumberCodeView extends FrameLayout {

private static final int[] STATE_NORMAL = {-android.R.attr.state_selected};

private static final int[] STATE_SELECTED = {android.R.attr.state_selected};

private static final int DEFAULT_TEXT_COLOR = 0xFFffffff;

private static final int DEFAULT_TEXT_SIZE = 30;  //dp

private static final int DEFAULT_FRAME_SIZE = 50;

private static final int DEFAULT_FRAME_PADDING = 14;

private static final int DEFAULT_CODE_LENGTH = 4;

/**

* 输入View

*/

private EditText mEditText;

private int mLastIndex = 0;

private int mCurIndex = 0;

private int mCodeLength = 0;

private Paint mCodeTextPaint;

private Rect mTextRect;

private String mCodeText = "";

private int mFrameSize = -1;

private int mFramePadding = -1;

private int mCodeTextColor = -1;

private int mCodeTextSize = -1;

private int mNormalId = R.mipmap.verificate_code_normal;

private int mSelectId = R.mipmap.verificate_code_selected;

private boolean mShowSystemKeyboard = true;

private @DrawableRes

int mFrameDrawableId = -1;

private SparseArrayCompat mInputDrawable = new SparseArrayCompat<>();

private InputMethodManager mInputMethodManager;

private OnNumberInputListener mOnNumberInputListener;

private TextWatcher mTextWatcher = new TextWatcher() {

@Override

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

}

@Override

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

boolean isBack = mCodeText.length() > s.length();

mLastIndex = mCurIndex;

if (!TextUtils.isEmpty(s)) {

mCodeText = s.toString();

mCurIndex = isBack ? mCodeText.length() - 1 : mCodeText.length();

mCurIndex = mCurIndex == mCodeLength ? mCurIndex - 1 : mCurIndex;

} else {

mCurIndex = 0;

mCodeText = "";

}

setDrawableState(mLastIndex, STATE_NORMAL);

if (mCodeText.length() == mCodeLength) {

if (mOnNumberInputListener != null) {

mOnNumberInputListener.onInputFinish();

}

} else {

setDrawableState(mCurIndex, STATE_SELECTED);

if (mOnNumberInputListener != null) {

mOnNumberInputListener.onInputIng();

}

}

invalidate();

}

@Override

public void afterTextChanged(Editable s) {

}

};

public NumberCodeView(Context context) {

this(context, null);

}

public NumberCodeView(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public NumberCodeView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

PixelUtil pixelUtil = new PixelUtil(context);

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NumberCodeView);

int size = typedArray.getIndexCount();

if (size > 0) {

for (int i = 0; i < size; i++) {

int attr = typedArray.getIndex(i);

switch (attr) {

case R.styleable.NumberCodeView_codeTextColor:

mCodeTextColor = typedArray.getColor(attr, -1);

break;

case R.styleable.NumberCodeView_codeTextSize:

mCodeTextSize = typedArray.getDimensionPixelSize(attr, -1);

break;

case R.styleable.NumberCodeView_frameSize:

mFrameSize = typedArray.getDimensionPixelSize(attr, -1);

break;

case R.styleable.NumberCodeView_framePadding:

mFramePadding = typedArray.getDimensionPixelOffset(attr, -1);

break;

case R.styleable.NumberCodeView_codeLength:

mCodeLength = typedArray.getInt(attr, -1);

break;

case R.styleable.NumberCodeView_frameDrawableId:

mFrameDrawableId = typedArray.getResourceId(attr, -1);

break;

case R.styleable.NumberCodeView_normal:

mNormalId = typedArray.getResourceId(attr, R.mipmap.verificate_code_normal);

break;

case R.styleable.NumberCodeView_select:

mSelectId = typedArray.getResourceId(attr, R.mipmap.verificate_code_selected);

break;

}

}

}

typedArray.recycle();

if (mCodeTextColor == -1) {

mCodeTextColor = DEFAULT_TEXT_COLOR;

}

if (mCodeTextSize == -1) {

mCodeTextSize = pixelUtil.dp2px(DEFAULT_TEXT_SIZE);

}

if (mFrameSize == -1) {

mFrameSize = pixelUtil.dp2px(DEFAULT_FRAME_SIZE);

}

if (mFramePadding == -1) {

mFramePadding = pixelUtil.dp2px(DEFAULT_FRAME_PADDING);

}

if (mCodeLength <= 0) {

mCodeLength = DEFAULT_CODE_LENGTH;

}

mTextRect = new Rect();

mInputMethodManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);

initEditText();

initTextPaint();

initStateListDrawable();

setWillNotDraw(false);

}

private void initEditText() {

mEditText = new EditText(getContext());

mEditText.addTextChangedListener(mTextWatcher);

mEditText.setCursorVisible(false);

ViewCompat.setBackground(mEditText, new ColorDrawable(Color.TRANSPARENT));

mEditText.setTextColor(Color.TRANSPARENT);

mEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(mCodeLength)});

mEditText.setFocusable(true);

mEditText.requestFocus();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

mEditText.setShowSoftInputOnFocus(true);

}

mEditText.setInputType(TYPE_CLASS_NUMBER);

mEditText.setSingleLine();

addView(mEditText, new LayoutParams(MATCH_PARENT, MATCH_PARENT));

}

/**

* 是否显示键盘

*

* @param showSystemKeyboard true为显示,false为不显示

*/

public void setShowKeyboard(boolean showSystemKeyboard) {

if (mShowSystemKeyboard == showSystemKeyboard) return;

mShowSystemKeyboard = showSystemKeyboard;

if (mShowSystemKeyboard) {

mEditText.setInputType(TYPE_CLASS_NUMBER);

} else {

mEditText.setInputType(TYPE_NULL);

}

}

public EditText getInputView() {

return mEditText;

}

public void setText(CharSequence text) {

if (mEditText != null) {

mEditText.setText(text);

}

}

private void initTextPaint() {

mCodeTextPaint = new TextPaint();

mCodeTextPaint.setColor(mCodeTextColor);

mCodeTextPaint.setAntiAlias(true);

mCodeTextPaint.setTextSize(mCodeTextSize);

mCodeTextPaint.setFakeBoldText(true);

mCodeTextPaint.setTextAlign(Paint.Align.CENTER);

}

private Drawable getFrameDrawable() {

if (mFrameDrawableId == -1) {

StateListDrawable drawable = new StateListDrawable();

drawable.addState(STATE_NORMAL, ContextCompat.getDrawable(getContext(), mNormalId));

drawable.addState(STATE_SELECTED, ContextCompat.getDrawable(getContext(), mSelectId));

return drawable;

} else {

return ContextCompat.getDrawable(getContext(), mFrameDrawableId);

}

}

private void initStateListDrawable() {

for (int i = 0; i < mCodeLength; i++) {

mInputDrawable.put(i, getFrameDrawable());

}

mCurIndex = mLastIndex = 0;

setDrawableState(mCurIndex, STATE_SELECTED);

}

//    private static boolean isAttrPxType(TypedArray typeArray, int index) {

//        return typeArray.peekValue(index).type == TypedValue.COMPLEX_UNIT_PX;

//    }

public void setOnNumberInputListener(OnNumberInputListener listener) {

this.mOnNumberInputListener = listener;

}

/**

* 设置drawable state

*/

private void setDrawableState(int index, int[] state) {

if (index < 0 || index > mInputDrawable.size() - 1) return;

mInputDrawable.get(index).setState(state);

}

@Override

protected void onVisibilityChanged(@NonNull View changedView, int visibility) {

super.onVisibilityChanged(changedView, visibility);

if (getVisibility() != VISIBLE) {

mInputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);

}

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int width = MeasureSpec.getSize(widthMeasureSpec);

int height = MeasureSpec.getSize(heightMeasureSpec);

int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);

int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);

if (heightSpecMode == MeasureSpec.AT_MOST) {

height = mFrameSize;

}

if (widthSpecMode != MeasureSpec.EXACTLY) {

width = (mCodeLength * mFrameSize) + (mFramePadding * (mCodeLength - 1));

}

int childWidthSpec = getChildMeasureSpec(widthMeasureSpec, 0, width);

int childHeightSpec = getChildMeasureSpec(heightMeasureSpec, 0, height);

mEditText.measure(childWidthSpec, childHeightSpec);

setMeasuredDimension(width, height);

}

public String getInputCode() {

return mCodeText;

}

private String indexOfCode(int index) {

if (TextUtils.isEmpty(mCodeText)) {

return "";

}

if (index < 0 || index > mCodeText.length() - 1) {

return "";

}

return String.valueOf(mCodeText.charAt(index));

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

int left = 0;

int right = mFrameSize;

int size = mInputDrawable.size();

for (int i = 0; i < size; i++) {

Drawable drawable = mInputDrawable.get(i);

drawable.setBounds(left, 0, right, getMeasuredHeight());

drawable.draw(canvas);

//绘制文本

drawCodeText(canvas, drawable.getBounds(), indexOfCode(i));

left = right + mFramePadding;

right = left + mFrameSize;

}

}

private void drawCodeText(Canvas canvas, Rect bound, String text) {

if (!TextUtils.isEmpty(text)) {

mCodeTextPaint.getTextBounds(text, 0, text.length(), mTextRect);

canvas.drawText(text, bound.centerX(), bound.height() / 2 + mTextRect.height() / 2, mCodeTextPaint);

}

}

public interface OnNumberInputListener {

void onInputFinish();

void onInputIng();

}

}

public interface OnNumberInputListener {

void onInputFinish();

void onInputIng();

}

该接口有两个方法用来监听输入完成、正在输入

像素转换工具类:PixelUtil

/**

* 像素转换工具类

*/

public class PixelUtil {

/**

* The context.

*/

private Context context;

public PixelUtil(Context context) {

this.context = context;

}

public static boolean isPxVal(TypedValue val) {

if (val != null && val.type == TypedValue.TYPE_DIMENSION &&

getComplexUnit(val.data) == TypedValue.COMPLEX_UNIT_PX) {

return true;

}

return false;

}

private static int getComplexUnit(int data) {

return TypedValue.COMPLEX_UNIT_MASK & (data >> TypedValue.COMPLEX_UNIT_SHIFT);

}

/**

* dpת px.

*

* @param value the value

* @return the int

*/

public int dp2px(float value) {

final float density = context.getResources().getDisplayMetrics().density;

return (int) (value * density + 0.5f);

}

/**

* pxתdp.

*

* @param value the value

* @return the int

*/

public int px2dp(float value) {

final float scale = context.getResources().getDisplayMetrics().densityDpi;

return (int) ((value * 160) / scale + 0.5f);

}

/**

* spתpx.

*

* @param value the value

* @return the int

*/

public int sp2px(float value) {

Resources r;

if (context == null) {

r = Resources.getSystem();

} else {

r = context.getResources();

}

float spvalue = value * r.getDisplayMetrics().scaledDensity;

return (int) (spvalue + 0.5f);

}

/**

* pxתsp.

*

* @param value the value

* @return the int

*/

public int px2sp(float value) {

final float scale = context.getResources().getDisplayMetrics().scaledDensity;

return (int) (value / scale + 0.5f);

}

public int width() {

return context.getResources().getDisplayMetrics().widthPixels;

}

public int height() {

return context.getResources().getDisplayMetrics().heightPixels;

}

}

attrs.xml

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值