来自:http://blog.csdn.net/ywl5320/article/details/52003691
现在很多应用都会集成支付功能,不管是直接调用支付SDK还是自己平台的虚拟货币,支付密码都是很重要的。一般的应用会直接使用Edittext作为密码输入框,这个看着就有点low了,高大上一点的就会自定义一个支付界面,然后输入效果也会有相应的设计,比如我们看到的支付宝和微信支付就是这样的。因为常用所以我也就简单的写了一个类似的支付密码输入控件,望以后不再纠结于此事,哈哈哈,先来张效果图:
控件就是这样的,具体和怎样的支付界面或对话框搭配,就可以灵活使用了。
编程写代码的快慢和Bug的多少都取决于编程思路和思想,所谓编程的思路想法才是最重要的,即:算法是灵魂。所以我们先说说实现思想是怎么回事,当思想懂了,写代码就可以有一千种方式了。
一、实现思想如下:
分析效果图我们可以发现要能输入类容还要得到内容的值,所以首先得有Edittext。第一种尝试:密码个数是多少个,就写多少个Edittext,然后监听每个的值,最后组合到一起就是输入的密码。这个方式可以简单的实现顺序输入效果,但是就没有那么灵活了,会考虑当前输入框前后输入框的值是否有,是否需要跳转指针等等麻烦的事,而且代码也比较多,所以这种方式就pass掉了;第二种尝试:就是一个Edittext,然后在它上面覆盖密码个数的TextView,随时监听Edittext的内容变化实时反馈到TextView中,就可以达到这种效果了,而且只有一个Edittext,长按退格键可以删除完内容,还可以直接清空类容都很方便。这里有个技巧就是,输入框Edittext的大小应该和TextView组合起来的整体大小一致,点击效果才能更完美,然后Edittext的字体大小应该尽量小(0或者1),才能保证每次获取焦点时都是在内容最末尾处。这样就可以实现这种支付密码效果了。
二、封装过程
思路大家已经知道了,根据思路来如果每次用xml布局的话,那还是很麻烦的,要写那么多Textview和布局,这是我们不能忍受的,贴别是应用中多个地方都用到了支付功能,那就GG了。所以我把这些操作都封装到了一个控件里面,然后暴露出相应的方法来设置属性(这里不是很全,可根据自己的需求添加相应的属性方法来达到自己的效果),使用时就当做一个简单的控件使用就行(本人不是很喜欢自定义属性,感觉有点拖泥带水的,所以都是用方法来实现的)。
(1)因为有控件重叠效果,所以首先集成RelativeLayout来达到这个效果。
-
-
-
- public class PayPwdEditText extends RelativeLayout{
-
- private EditText editText;
- private Context context;
-
- private LinearLayout linearLayout;
- private TextView[] textViews;
-
- private int pwdlength = 6;
-
- private OnTextFinishListener onTextFinishListener;
-
-
- public PayPwdEditText(Context context) {
- this(context, null);
- }
-
- public PayPwdEditText(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public PayPwdEditText(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- this.context = context;
- }
- }
(2)分析要用到的属性,有密码框的背景布局、密码长度、每个密码直接的分割线宽度和颜色、密码字体颜色和大小(还可以密码设置显示的字符效果,这里没有添加,使用的默认效果)
(3)初始化Edittext
-
-
-
-
- private void initEdit(int bgcolor)
- {
- editText = new EditText(context);
- editText.setBackgroundResource(bgcolor);
- editText.setCursorVisible(false);
- editText.setTextSize(0);
- editText.setInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD | InputType.TYPE_CLASS_NUMBER);
- editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(pwdlength)});
- editText.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- Editable etext = editText.getText();
- Selection.setSelection(etext, etext.length());
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
-
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- initDatas(s);
- if(s.length() == pwdlength)
- {
- if(onTextFinishListener != null)
- {
- onTextFinishListener.onFinish(s.toString().trim());
- }
- }
- }
- });
- LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
- lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
- addView(editText, lp);
-
- }
这里可以对输入框的类型进行定制,只能输入数字还是数字字母混合等,然后监听每次输入的类容,并添加回调接口,方便使用时得到数据。
(4)初始化TextView显示框
-
-
-
-
-
-
-
-
- public void initShowInput(int bgcolor, int pwdlength, float slpilinewidth, int splilinecolor, int pwdcolor, int pwdsize)
- {
-
- linearLayout = new LinearLayout(context);
- linearLayout.setBackgroundResource(bgcolor);
- LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
- linearLayout.setLayoutParams(layoutParams);
- linearLayout.setOrientation(LinearLayout.HORIZONTAL);
- addView(linearLayout);
-
-
- textViews = new TextView[pwdlength];
- LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LayoutParams.MATCH_PARENT);
- params.weight = 1;
- params.gravity = Gravity.CENTER;
-
- LinearLayout.LayoutParams params2 = new LinearLayout.LayoutParams(dip2px(context, slpilinewidth),LayoutParams.MATCH_PARENT);
- for(int i = 0; i < textViews.length; i++)
- {
- final int index = i;
- TextView textView = new TextView(context);
- textView.setGravity(Gravity.CENTER);
- textViews[i] = textView;
- textViews[i].setTextSize(pwdsize);
- textViews[i].setTextColor(context.getResources().getColor(pwdcolor));
- textViews[i].setInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD | InputType.TYPE_CLASS_NUMBER);
- linearLayout.addView(textView, params);
-
-
- if(i < textViews.length - 1)
- {
- View view = new View(context);
- view.setBackgroundColor(context.getResources().getColor(splilinecolor));
- linearLayout.addView(view, params2);
- }
- }
- }
这个也是初始化TextView的显示效果,然后根据密码长度动态添加到布局中,并保存每个TextView的引用,方便以后对它门进行操作。
(5)然后是根据Edittext的输入内容设置Textview的值
-
-
-
-
- public void initDatas(Editable s)
- {
- if(s.length() > 0)
- {
- int length = s.length();
- for(int i = 0; i < pwdlength; i++)
- {
- if(i < length)
- {
- for(int j = 0; j < length; j++)
- {
- char ch = s.charAt(j);
- textViews[j].setText(String.valueOf(ch));
- }
- }
- else
- {
- textViews[i].setText("");
- }
- }
- }
- else
- {
- for(int i = 0; i < pwdlength; i++)
- {
- textViews[i].setText("");
- }
- }
- }
这个方法添加到Edittext的TextWatcher监听中即可,就能动态显示密码效果了。
核心思路和实现就是这样的,然后提供一个初始化入口:
-
-
-
-
-
-
-
-
- public void initStyle(int bgdrawable, int pwdlength, float splilinewidth, int splilinecolor, int pwdcolor, int pwdsize)
- {
- this.pwdlength = pwdlength;
- initEdit(bgdrawable);
- initShowInput(bgdrawable, pwdlength, splilinewidth, splilinecolor, pwdcolor, pwdsize);
- }
其他属性方法如下:
-
-
-
-
- public void setShowPwd(boolean showPwd) {
- int length = textViews.length;
- for(int i = 0; i < length; i++) {
- if (showPwd) {
- textViews[i].setTransformationMethod(PasswordTransformationMethod.getInstance());
- } else {
- textViews[i].setTransformationMethod(HideReturnsTransformationMethod.getInstance());
- }
- }
- }
-
-
-
-
-
- public void setInputType(int type)
- {
- int length = textViews.length;
- for(int i = 0; i < length; i++) {
- textViews[i].setInputType(type);
- }
- }
-
-
-
-
- public void clearText()
- {
- editText.setText("");
- for(int i = 0; i < pwdlength; i++)
- {
- textViews[i].setText("");
- }
- }
-
- public void setOnTextFinishListener(OnTextFinishListener onTextFinishListener) {
- this.onTextFinishListener = onTextFinishListener;
- }
-
-
-
- public String getPwdText()
- {
- if(editText != null)
- return editText.getText().toString().trim();
- return "";
- }
-
- public static int dip2px(Context context, float dipValue) {
- final float scale = context.getResources().getDisplayMetrics().density;
- return (int) (dipValue * scale + 0.5f);
- }
-
- public interface OnTextFinishListener
- {
- void onFinish(String str);
- }
这样就全部写完了,还是不多是吧,哈哈哈。
项目源码免费下载地址:
1、CSDN:PayPwdEditText
2、Github:PayPwdEditText
欢迎下载和start