密码控件passwordView及其分析

    xiaoxiao2021-03-25  97

    1.做app,尤其是金融类的app,往往都会涉及到支付密码这块,并且支付密码几乎都是6个数字,1个数字占一个区域,6个数字占满整个区域,并且每个数字占得大小是相等的,类似于以下的样子

    2. 那么怎么样才能做出这样一个控件呢,可以看到每个数字是等大小的,并且是会显示在中间的

    3.我们在考虑的时候肯定是输入东西,第一控件就是EditText,因为这个控件是支持输入的。但是我们要求的刚好6个数字,并且是一个个数字都在框的中间的,距离是等距的,这时候就会发现EditText不是很适合这个。

    4.最好的等距方法就是一个LInearLayout里面放6个EditText,每个EditText设置weight="1",这样至少6个框就出来了,而且设置gravity="center",字也能在中间了,但是,每个EditText是能输入很多字 的,那么设置每个Editext只能输入一个字呢,基本满足要求了,但是这个不会说你第一个Editext输入了数字就能自动跳到第二个输入框的。所以这里得解决这个问题,我们可以设置一个框来获取输入值,后面都是前面这个框设置TextWatch监听来获取输入值,然后用代码给后面的框里设置好数字就ok了,看起来就像数字是一个输进去的,而且一个个的展示出来了

    5. 还有一个,一般这个控件出来后,会自动弹出软键盘,并且,看不到游标,弹出软键盘,只要设置获取焦点,并且给这个自定义的view设置点击事件,来控制软键盘的显示和隐藏,游标的话

    <item name="android:cursorVisible">false</item>

    就不会显示了

             6.其实这时候会发现后面5个控件,不一定得是Editext,也可以是TextView,效果一样

    7.基本设计思路是这样的。这边在github上有个别人的较好的,这里是地址https://github.com/Jungerr/GridPasswordView,可以下载看看

    8.针对上面这个开源项目进行分析:

    项目运行之后大致如上,可以设置输入密码位数,还有可见不可见等等

    <declare-styleable name="gridPasswordView"> <attr name="gpvTextColor" format="color|reference" /> <attr name="gpvTextSize" format="dimension" /> <attr name="gpvLineColor" format="color" /> <attr name="gpvGridColor" format="color" /> <attr name="gpvLineWidth" format="dimension" /> <attr name="gpvPasswordLength" format="integer" /> <attr name="gpvPasswordTransformation" format="string" /> <attr name="gpvPasswordType" format="enum"> <enum name="numberPassword" value="0" /> <enum name="textPassword" value="1" /> <enum name="textVisiblePassword" value="2" /> <enum name="textWebPassword" value="3" /> </attr> </declare-styleable>

    这个自定义控件提供了以上可以在xml字直接定义的属性,有输入位数,输入类型,其实gpvLIneColor,就是看到的黑色框,gpvGridColor是中间白色的部分,运用这两种颜色就能做出一个框了。

    最关键的代码就在这个类中 

    public class GridPasswordView extends LinearLayout implements PasswordView {

    可以看到是继承一个LInearLayout,他的思路也是在这个控件里放了一个Editext,5个Textview来达到显示效果,但是这个做了扩展,在属性里可以设置位数,代码里自动判断要出现几个框

    int index = 1; while (index < mPasswordLength) { View dividerView = inflater.inflate(R.layout.divider, null); LayoutParams dividerParams = new LayoutParams(mLineWidth, LayoutParams.MATCH_PARENT); dividerView.setBackgroundDrawable(mLineDrawable); addView(dividerView, dividerParams); TextView textView = (TextView) inflater.inflate(R.layout.textview, null); setCustomAttr(textView); LayoutParams textViewParams = new LayoutParams(0, LayoutParams.MATCH_PARENT, 1f); addView(textView, textViewParams); mViewArr[index] = textView; index++; }

    并且把TextView 全部放到mViewArr[]中,给后面再每个view上放数字给予方便,一个个取出来放进去就可以了。

    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.gridPasswordView, defStyleAttr, 0); mTextColor = ta.getColorStateList(R.styleable.gridPasswordView_gpvTextColor); if (mTextColor == null) mTextColor = ColorStateList.valueOf(getResources().getColor(android.R.color.primary_text_light)); int textSize = ta.getDimensionPixelSize(R.styleable.gridPasswordView_gpvTextSize, -1); if (textSize != -1) { this.mTextSize = Util.px2sp(context, textSize); } mLineWidth = (int) ta.getDimension(R.styleable.gridPasswordView_gpvLineWidth, Util.dp2px(getContext(), 1)); mLineColor = ta.getColor(R.styleable.gridPasswordView_gpvLineColor, DEFAULT_LINECOLOR); mGridColor = ta.getColor(R.styleable.gridPasswordView_gpvGridColor, DEFAULT_GRIDCOLOR); mLineDrawable = ta.getDrawable(R.styleable.gridPasswordView_gpvLineColor); if (mLineDrawable == null) mLineDrawable = new ColorDrawable(mLineColor); mOuterLineDrawable = generateBackgroundDrawable(); mPasswordLength = ta.getInt(R.styleable.gridPasswordView_gpvPasswordLength, DEFAULT_PASSWORDLENGTH); mPasswordTransformation = ta.getString(R.styleable.gridPasswordView_gpvPasswordTransformation); if (TextUtils.isEmpty(mPasswordTransformation)) mPasswordTransformation = DEFAULT_TRANSFORMATION; mPasswordType = ta.getInt(R.styleable.gridPasswordView_gpvPasswordType, 0); ta.recycle(); mPasswordArr = new String[mPasswordLength]; mViewArr = new TextView[mPasswordLength];

    以上这段是获取属性的代码,mPasswordArr 是放置输入数字的,全部存起来,最后取出来放到各个TextView上,

    另外就是监听了

    public interface OnPasswordChangedListener { /** * Invoked when the password changed. * @param psw new text */ void onTextChanged(String psw); /** * Invoked when the password is at the maximum length. * @param psw complete text */ void onInputFinish(String psw); }

    这个监听是来判断密码输入的,也是给外界传出数据的出口

    private ImeDelBugFixedEditText.OnDelKeyEventListener onDelKeyEventListener = new ImeDelBugFixedEditText.OnDelKeyEventListener() { @Override public void onDeleteClick() { for (int i = mPasswordArr.length - 1; i >= 0; i--) { if (mPasswordArr[i] != null) { mPasswordArr[i] = null; mViewArr[i].setText(null); notifyTextChanged(); break; } else { mViewArr[i].setText(null); } } } }; 这个监听是用来删除输入的密码的,删除一个mPasswordArr【】li 就变成空,设置null,表现形式就是少输了一个密码

    转载请注明原文地址: https://ju.6miu.com/read-37116.html

    最新回复(0)