Android支付宝输入密码界面
2017-04-24 23:29
302 查看
项目地址https://github.com/GitHubToLiao/CustomPassWordEditText.git
先说明一下,这里的功能是我按照HongChengDarren的博客写的,他的博客地址是http://blog.csdn.net/z240336124/article/details/53739790,但是这里的代码是我看完他讲解的视频自己写的。同时我会在这里说下我自己在实现该功能时踩的坑,同时也对这个功能做一下总结
首先先上一下效果图
这里我分析一下他的实现思路
- 这里我们可以吧他整体分为三个部分
第一部分是上面的密码显示框我们可以自定义EditText然后把背景和输入的密码绘制出来
第二部分就是我们自定义的键盘当然这里也可以使用系统自带的键盘,如果使用我们自定义的键盘就要将第一部分和第二部分通过接口回调关联起来
第三部分就是将第一部分和第二部分加载到Dialog中然后给Dialog设置全屏和底部显示同时也可以加入显示和退出的动画
1.第一部分的代码
上面代码中已经写了注释但是要注意的是我这里在继承EditText的时候只重写了他的两个构造方法不知道你们发现了吗,为什么要重写两个构造方法原因是如果你们重写三个构造方法那么系统键盘我们就不能使用但是如果写两个构造方法就可有调用系统自带的键盘
在贴出自定义属性的代码文件路径res/values/attres.xml
2.接着是我们自定键盘的方法这里我的做法是继承自LinearLayout然后通过inflate()方法将我们已经写好的键盘布局引入这个非常简单
这里面主要功能不是布局而是怎么样把第一部分与第二部分关联起来,我这里的做法是将点击的按钮的数字通过接口回调回传给我们自定义的EditText也就是第一部分
好了下面就是自定义键盘的代码
然后是键盘的布局代码
最后就是将上面我们已经关联好的EditText和键盘整合到Dialog中这里没什么好说的直接上代码
布局代码
R.layout.pw_layout
Dialog的显示动画
R.style.dial_style
dian_open.xml的代码
dial_exit.xml的代码
这里在整合Dialog的过程中我自己有踩过一个坑分享一下这里创建Dialog的时候一定是Dialog而不能创建AlertDialog如果创建AlertDialog那么我们水平方向全屏显示就会不起作用·
项目地址https://github.com/GitHubToLiao/CustomPassWordEditText.git
先说明一下,这里的功能是我按照HongChengDarren的博客写的,他的博客地址是http://blog.csdn.net/z240336124/article/details/53739790,但是这里的代码是我看完他讲解的视频自己写的。同时我会在这里说下我自己在实现该功能时踩的坑,同时也对这个功能做一下总结
首先先上一下效果图
这里我分析一下他的实现思路
- 这里我们可以吧他整体分为三个部分
第一部分是上面的密码显示框我们可以自定义EditText然后把背景和输入的密码绘制出来
第二部分就是我们自定义的键盘当然这里也可以使用系统自带的键盘,如果使用我们自定义的键盘就要将第一部分和第二部分通过接口回调关联起来
第三部分就是将第一部分和第二部分加载到Dialog中然后给Dialog设置全屏和底部显示同时也可以加入显示和退出的动画
1.第一部分的代码
public class PassWordEditText extends EditText { private PWCommitListener mListener; // 画笔 private Paint mPaint; // 一个密码所占的宽度 private int mPasswordItemWidth; // 密码的个数默认为6位数 private int mPasswordNumber = 6; // 背景边框颜色 private int mBgColor = Color.parseColor("#d1d2d6"); // 背景边框大小 private int mBgSize = 1; // 背景边框圆角大小 private int mBgCorner = 0; // 分割线的颜色 private int mDivisionLineColor = mBgColor; // 分割线的大小 private int mDivisionLineSize = 1; // 密码圆点的颜色 private int mPasswordColor = mDivisionLineColor; // 密码圆点的半径大小 private int mPasswordRadius = 4; public PassWordEditText(Context context) { this(context, null); } public PassWordEditText(Context context, AttributeSet attrs) { super(context, attrs); //初始化画笔 initPaint(); //初始化自定义属性数据 initAttributeSet(context, attrs); setMaxEms(mPasswordNumber); setInputType(EditorInfo.TYPE_TEXT_VARIATION_PASSWORD); // 不显示光标 setCursorVisible(false); setEnabled(false); } /** * 初始化画笔 */ private void initPaint() { mPaint = new Paint(); //设置坑锯齿 mPaint.setAntiAlias(true); } /** * 初始化自 13cc9 定义属性 */ private void initAttributeSet(Context context, AttributeSet attrs) { TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PassWordEditText); // 获取大小 mDivisionLineSize = (int) array.getDimension(R.styleable.PassWordEditText_divisionLinesSize, dip2px(mDivisionLineSize)); mPasswordRadius = (int) array.getDimension(R.styleable.PassWordEditText_passwordRadius, dip2px(mPasswordRadius)); mBgSize = (int) array.getDimension(R.styleable.PassWordEditText_bgSize, dip2px(mBgSize)); mBgCorner = (int) array.getDimension(R.styleable.PassWordEditText_bgCorner, 0); // 获取颜色 mBgColor = array.getColor(R.styleable.PassWordEditText_bgColor, mBgColor); mDivisionLineColor = array.getColor(R.styleable.PassWordEditText_divisionLineColor, mDivisionLineColor); mPasswordColor = array.getColor(R.styleable.PassWordEditText_passwordColor, mDivisionLineColor); mPasswordNumber = array.getInt(R.styleable.PassWordEditText_passwordNumber, mPasswordNumber); //回收 array.recycle(); } /** * dip 转 px */ private int dip2px(int dip) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, getResources().getDisplayMetrics()); } @Override protected void onDraw(Canvas canvas) { int passwordWidth = getWidth() - (mPasswordNumber - 1) * mDivisionLineSize; mPasswordItemWidth = passwordWidth / mPasswordNumber; //绘制背景 drawBG(canvas); //绘制分割线 drawDivisionLion(canvas); //绘制密码 drawPassWord(canvas); } //添加密码将自定义键盘和密码框联系起来 public void addPW(String pw){ if(!TextUtils.isEmpty(pw)){ pw = getText().toString().trim()+pw; if(pw.length() >=mPasswordNumber){ //密码输入完成回调 if(pw.length() ==mPasswordNumber){ setText(pw); } mListener.commit_PW(pw); return; } setText(pw); } } //删除最后一个密码 public void removePW(){ String pw = getText().toString().trim(); if(TextUtils.isEmpty(pw)){ return; } pw = pw.substring(0,pw.length()-1); setText(pw); } //绘制密码 private void drawPassWord(Canvas canvas) { //获取当前文本长度的原因是因为让用户输一个我们动态的展示一个密码 int passwordLength = getText().length(); //设置画笔颜色 mPaint.setColor(mPasswordColor); //设密码为实心 mPaint.setStyle(Paint.Style.FILL); for (int i = 0; i < passwordLength; i++) { int cx = i * mDivisionLineSize + i * mPasswordItemWidth + mPasswordItemWidth / 2 + mBgSize; canvas.drawCircle(cx, getHeight() / 2, mPasswordRadius, mPaint); } } //绘制分割线 private void drawDivisionLion(Canvas canvas) { //设置画笔颜色 mPaint.setColor(mDivisionLineColor); //设置画笔大小 mPaint.setStrokeWidth(mDivisionLineSize); for (int i = 0; i < mPasswordNumber - 1; i++) { int startX = mPasswordItemWidth * (i + 1) + mDivisionLineSize * (i + 1); canvas.drawLine(startX, mBgSize, startX, getHeight() - mBgSize, mPaint); } } //绘制背景 private void drawBG(Canvas canvas) { //设置背景颜色 mPaint.setColor(mBgColor); //设置画笔为空心 mPaint.setStyle(Paint.Style.STROKE); //设置空心线宽 mPaint.setStrokeWidth(mBgSize); RectF rectF = new RectF(mBgSize, mBgSize, getWidth() - mBgSize, getHeight()); //进行绘制绘制过程中判断是否是圆角 if (mBgCorner != 0) { //绘制圆角 rectf 圆角弧度 圆角弧度 画笔 canvas.drawRoundRect(rectF, mBgCorner, mBgCorner, mPaint); } else { canvas.drawRect(rectF, mPaint); } } public void setOnPWCommitListener(PWCommitListener listener){ this.mListener =listener; } //密码完成回调 public interface PWCommitListener{ void commit_PW(String pw); } }
上面代码中已经写了注释但是要注意的是我这里在继承EditText的时候只重写了他的两个构造方法不知道你们发现了吗,为什么要重写两个构造方法原因是如果你们重写三个构造方法那么系统键盘我们就不能使用但是如果写两个构造方法就可有调用系统自带的键盘
在贴出自定义属性的代码文件路径res/values/attres.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="PassWordEditText"> <!--密码个数--> <attr name="passwordNumber" format="integer"/> <!--密码半径--> <attr name="passwordRadius" format="dimension"/> <!--密码颜色--> <attr name="passwordColor" format="color"/> <!--分割线大小--> <attr name="divisionLinesSize" format="dimension"/> <!--分割线颜色--> <attr name="divisionLineColor" format="color"/> <!--背景边框大小--> <attr name="bgSize" format="dimension"/> <!--背景边框颜色--> <attr name="bgColor" format="color"/> <!--背景边框弧度--> <attr name="bgCorner" format="dimension"/> </declare-styleable> </resources>
2.接着是我们自定键盘的方法这里我的做法是继承自LinearLayout然后通过inflate()方法将我们已经写好的键盘布局引入这个非常简单
这里面主要功能不是布局而是怎么样把第一部分与第二部分关联起来,我这里的做法是将点击的按钮的数字通过接口回调回传给我们自定义的EditText也就是第一部分
好了下面就是自定义键盘的代码
public class CustomerKeyboard extends LinearLayout implements View.OnClickListener { private CustomerKeyboardClickListener mListener; public CustomerKeyboard(Context context) { this(context, null); } public CustomerKeyboard(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CustomerKeyboard(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); inflate(context,R.layout.kayboard,this); setOnChildClick(this); } public void setOnChildClick(ViewGroup parant) { //获取所有的子条目的个数 int childCount = parant.getChildCount(); //对所有子条目进行遍历 for(int i =0;i<childCount;i++){ View view =parant.getChildAt(i); if(view instanceof ViewGroup){ //通过递归继续向下判断知道子条目不是VIewGroup setOnChildClick((ViewGroup) parant.getChildAt(i)); //退出本次循环 continue; } //如果不是ViewGroup就给当前组件设置点击事件 view.setOnClickListener(this); } } @Override public void onClick(View v) { //判断当前点击的按钮的类型我们的键盘只有TextView和ImageVIew //如果当前View的类型是TextVIew那么他就是输入的密码 if(v instanceof TextView){ String pw =((TextView)v).getText().toString().trim(); //这里判空一个是因为代码的健壮性另外一个是因为我们TextView是空的如果不判断是会出问题的 if(!TextUtils.isEmpty(pw)){ if(mListener !=null) { mListener.click(pw); } } //如果当前View的类型是ImageVIew那么点击的就是删除键 }else if(v instanceof ImageView){ if(mListener !=null) { mListener.remove(); } } } /** * * @param listener CustomerKeyboardClickListener对象 * 点击回调监听 */ public void setOnCustomerKeyboardClickListener(CustomerKeyboardClickListener listener){ this.mListener =listener; } /** * 回调接口用来判断键盘的点击 * 如果点击数字调用click方法并将改密码返回回调出去 * 如果点击删除键则回调remove方法 */ public interface CustomerKeyboardClickListener{ void click(String pw); void remove(); } }
然后是键盘的布局代码
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#d1d5db" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginTop="1dp" > <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/number_bg" android:layout_marginRight="1dp" android:gravity="center" android:padding="15dp" android:textColor="#000" android:textStyle="bold" android:text="1" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/number_bg" android:gravity="center" android:textColor="#000" android:textStyle="bold" android:padding="15dp" android:layout_marginRight="1dp" android:text="2" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:textStyle="bold" android:padding="15dp" android:textColor="#000" android:background="@drawable/number_bg" android:text="3" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:layout_marginTop="1dp" android:orientation="horizontal"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:textStyle="bold" android:padding="15dp" android:background="@drawable/number_bg" android:textColor="#000" android:layout_marginRight="1dp" android:text="4" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:padding="15dp" android:background="@drawable/number_bg" android:textStyle="bold" android:textColor="#000" android:layout_marginRight="1dp" android:text="5" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:padding="15dp" android:background="@drawable/number_bg" android:textColor="#000" android:textStyle="bold" android:gravity="center" android:text="6" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:layout_marginTop="1dp" android:orientation="horizontal"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:padding="15dp" android:background="@drawable/number_bg" android:layout_marginRight="1dp" android:layout_weight="1" android:gravity="center" android:textColor="#000" android:textStyle="bold" android:text="7" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:padding="15dp" android:background="@drawable/number_bg" android:layout_marginRight="1dp" android:gravity="center" android:textColor="#000" android:textStyle="bold" android:text="8" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:padding="15dp" android:background="@drawable/number_bg" android:gravity="center" android:textColor="#000" android:textStyle="bold" android:text="9" android:id="@+id/textView" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:layout_marginTop="1dp" android:layout_marginBottom="1dp" android:orientation="horizontal"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:padding="15dp" android:layout_marginRight="1dp" android:text="" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:padding="15dp" android:background="@drawable/number_bg" android:layout_marginRight="1dp" android:textColor="#000" android:textStyle="bold" android:text="0" android:id="@+id/textView2" /> <ImageView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:src="@drawable/delete_end"/> </LinearLayout> </LinearLayout>
最后就是将上面我们已经关联好的EditText和键盘整合到Dialog中这里没什么好说的直接上代码
LayoutInflater inflater = LayoutInflater.from(this); LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.pw_layout, null); Dialog dialog = new Dialog(this); dialog.setContentView(layout); //设置点击空白地区Dialog不退出 dialog.setCanceledOnTouchOutside(false); Window window = dialog.getWindow(); //设置Dialog出现于退出的动画 window.setWindowAnimations(R.style.dial_style); //设置底部显示 window.setGravity(Gravity.BOTTOM); //设置水平方向全屏显示 int width =WindowManager.LayoutParams.MATCH_PARENT; int height =WindowManager.LayoutParams.WRAP_CONTENT; WindowManager.LayoutParams lp = window.getAttributes(); // 获取对话框当前的参数值 lp.width = ViewGroup.LayoutParams.MATCH_PARENT; lp.height = ViewGroup.LayoutParams.WRAP_CONTENT; window.setAttributes(lp); dialog.show();
布局代码
R.layout.pw_layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:background="#fff" android:orientation="vertical"> <com.example.as.passwordedittext.PassWordEditText android:id="@+id/pw_EditText" android:layout_width="match_parent" android:layout_height="46dp" android:layout_margin="20dp" android:background="@null" app:bgColor="#a5a5a5" app:bgCorner="3dp" app:divisionLineColor="#a5a5a5" app:bgSize="1dp" app:passwordColor="#000" app:passwordRadius="5dp" app:divisionLinesSize="1dp" app:passwordNumber="6" /> <com.example.as.passwordedittext.CustomerKeyboard android:id="@+id/keyboard_View" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="60dp" /> </LinearLayout>
Dialog的显示动画
R.style.dial_style
<style name="dial_style" parent="android:Animation"> <item name="android:windowEnterAnimation">@anim/dian_open</item> <item name="android:windowExitAnimation">@anim/dial_exit</item> </style>
dian_open.xml的代码
<?xml version="1.0" encoding="utf-8"?> <!-- 上下滑入式 --> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="200" android:fromYDelta="100%p" android:toYDelta="0" /> </set>
dial_exit.xml的代码
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="600" android:toYDelta="100%p" /> </set>
这里在整合Dialog的过程中我自己有踩过一个坑分享一下这里创建Dialog的时候一定是Dialog而不能创建AlertDialog如果创建AlertDialog那么我们水平方向全屏显示就会不起作用·
项目地址https://github.com/GitHubToLiao/CustomPassWordEditText.git
相关文章推荐
- Android实现支付宝6位密码输入界面
- Android 支付宝支付密码输入界面
- Android仿支付宝支付密码输入框
- Android 带密码输入界面的Dialog实现机制
- Android 仿支付宝支付密码输入框
- 仿支付宝密码输入界面+随机键盘
- android:仿支付宝/微信的密码输入框效果
- android中6个EditText输入验证码(仿支付宝支付输入密码框)
- Android自定义控件开发系列——仿支付宝六位支付密码输入
- Android自定义View仿支付宝输入六位密码功能
- Ubuntu 12.04 64bit 配置完android 5.0编译环境后出现“could not write bytes: Broken pipe.”而无法进入输入帐号密码的登陆界面
- [Android开发] 从后台恢复前台界面需要输入密码的demo|监听Home短按长按锁屏
- 仿微信/支付宝的密码输入框效果 android
- 安卓实现支付宝6位密码输入界面
- 安卓/Android 模仿支付宝/微信 支付密码输入框的自定义View
- Android 仿微信/支付宝的密码输入框效果(一)
- 仿微信/支付宝的密码输入框效果 android
- [Android UI开发] 仿微信/支付宝的密码输入框效果:GridPasswordView
- Android 平板中 自定义键盘(popuwindow) 居于屏幕左下方 仿微信的密码输入界面
- Android自定义类似支付宝密码输入的控件