研究支付宝密码输入控件及源码实现

目标效果图

实现思路

  1. 要想实现输入,就少不了EditText
  2. 看整体布局应该是一个横向的LinearLayout
  3. 每个格子看进来应该是多个子View
  4. 那么我们是不是有思路了?没错!一个LinearLayout包含了多个EditText,首先这个思路是对的;其次,有必要每个子View都是EditText吗?我们在监听文本变化时,只需要对一个EditText添加TextWatcher,因此,只需要一个EditText,其它的可以是TextView就可以了(PS:EditText是继承自TextView的)

一、初步实现外观框架

自定义View,通过继承LinearLayout的方式

  1. 先看布局inputview.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"><EditText
        android:cursorVisible="false"android:gravity="center"android:id="@+id/indexView"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/bg_rec"android:text="a"/>
</LinearLayout>

需要注意的是要把光标设置成不可见,因为我们的目标效果中不应该有光标
2. 填充布局,关键代码是在init方法中填充几个TextView,并设置背景和LayoutParams

public class GridPasswordView extends LinearLayout {private EditText mIndexView;private LinearLayout mContainer;public GridPasswordView(Context context) {this(context, null);}public GridPasswordView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public GridPasswordView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {setOrientation(HORIZONTAL);setBackgroundColor(Color.GRAY);mContainer = (LinearLayout) View.inflate(getContext(), R.layout.inputview, null);mIndexView = (EditText) mContainer.findViewById(R.id.indexView);for (int i = 0; i < 5; i++) {TextView child = new TextView(getContext());child.setText(i + "");child.setLayoutParams(new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1));child.setGravity(Gravity.CENTER);child.setBackground(getResources().getDrawable(R.drawable.bg_rec));mContainer.addView(child);}mContainer.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));addView(mContainer);}
}

可以看到,我们又另外在mContainer中添加了5个TextView,并设置了内容
3. 矩形框背景使用的是shape

<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><stroke android:color="@color/colorAccent"android:width="1dp"/>
</shape>
  1. 在demo中使用
<feifu.com.testview.gridpswview.GridPasswordViewandroid:background="#f00"android:id="@+id/grid"android:layout_width="match_parent"android:layout_height="30dp"/>

效果图如下:

我们把EditText放在第一位也是有原因的,后面会讲。
到这里就实现了一个空的架子。

二、实现输入和删除逻辑

输入和删除的逻辑就要接收软键盘的输入和输出了,因此我们需要监听EditText的文本变化,如果有输入,就依次输入,如果按了删除,就依次删除。
1. 对EditText添加监听

    /*** 监听indexview的内容变化*/private TextWatcher mIndextViewWatcher = new TextWatcher() {@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {oldText = s.toString();}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {Log.e(TAG, "count=" + count + ",start=" + start + ",before=" + before + ",s=" + s);//输入内容if (count == 1) {//文本到达最大长度,不再接受输入,要保证edittext不变if (currentIndex >= maxLength) {mIndexView.removeTextChangedListener(this);mIndexView.setText(s.charAt(0) + "");mIndexView.setSelection(mIndexView.getText().length());//设置光标到最后,保证输入文本顺序mIndexView.addTextChangedListener(this);//设置文本后再次添加监听return;}if (currentIndex == 0) {currentIndex++;} else {TextView child = (TextView) mContainer.getChildAt(currentIndex++);child.setText(s.charAt(s.length() - 1) + "");//需要及时移除监听器,否则会形成死循环mIndexView.removeTextChangedListener(this);mIndexView.setText(s.charAt(0) + "");mIndexView.setSelection(mIndexView.getText().length());//设置光标到最后,保证输入文本顺序mIndexView.addTextChangedListener(this);//设置文本后再次添加监听}} else if (count == 0) {Log.e(TAG, "currentIndex=" + currentIndex);if (currentIndex <= 0) {return;}//删除内容if (currentIndex == 1) {currentIndex --;}else {TextView child = (TextView) mContainer.getChildAt(currentIndex - 1);currentIndex --;child.setText("");mIndexView.removeTextChangedListener(this);mIndexView.setText(oldText);mIndexView.addTextChangedListener(this);//设置文本后再次添加监听mIndexView.setSelection(mIndexView.getText().length());//设置光标位置到最后,否则无法删除}}}@Overridepublic void afterTextChanged(Editable s) {}};

主要的逻辑就在onTextChanged方法中,首先来说一个几个参数的意思:
* s 表示编辑后的文本内容
* start表示当前的光标位置
* before表示改变前的内容数量
* count表示改变的数量,1表示输入一个字符,0表示删除一个字符
2. 在onTextChanged方法中
* 首先判断是输入还是删除,根据count来判断,1表示输入一个字符,0表示删除一个字符
* 使用currentIndex表示当前文本个数
* 因为每次操作的其实都是EditText的内容,所以要及时的把EditText的内容给设置回原来的内容,要注意的一点是,在TextWatcher中设置EditText内容时,要先移除监听器再改变内容,改变完后再把监听器设置回来,否则会形成死循环

到这里,基本的输入和输出就搞定了。

添加自定义属性

接下来就是要添加一些自定义的属性了,这样更方便我们来定义自己需要的样式。

自定义属性的方式

  1. 在res/values/文件夹下新建文件attrs.xml或者attrs_xxx.xml
  2. 在attrs.xml中定义自己需要的属性
<declare-styleable name="GridPswView"><attr name="passwordTransformation" format="string"/><attr name="length" format="integer"/><attr name="borderColor" format="color"/><attr name="borderWidth" format="dimension"/><attr name="backgroundColor" format="color"/><attr name="textColor" format="color"/><attr name="textSize" format="dimension"/></declare-styleable>

如果需要定义属性的值域可以如下

<attr name="percent_circle_gravity"><flag name="left" value="0" /><flag name="top" value="1" /><flag name="center" value="2" /><flag name="right" value="3" /><flag name="bottom" value="4" />
</attr>
  1. 在我们的自定义view中获取属性的值,并且设置到我们的view中
    构造方法中会有两个参数,context和attrs,我们就是要用这两个参数来获取属性值
private void initAttr(Context context, AttributeSet attrs) {TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.GridPswView);if (typedArray != null) {mBorderColor = typedArray.getColor(R.styleable.GridPswView_borderColor, Color.BLUE);mTextColor = typedArray.getColor(R.styleable.GridPswView_textColor, Color.GRAY);mBackgroundColor = typedArray.getColor(R.styleable.GridPswView_backgroundColor, Color.LTGRAY);mPswTransformation = typedArray.getString(R.styleable.GridPswView_passwordTransformation);mMaxLength = typedArray.getInt(R.styleable.GridPswView_length, 6);mBroderWidth = typedArray.getDimension(R.styleable.GridPswView_borderWidth, 3);mTextSize = typedArray.getDimension(R.styleable.GridPswView_textSize, 16);}}

获取到值以后直接在view中设置属性就可以了,这里不再详述。
4. 在xml中设置属性的值
唯一需要注意的是要引入命名空间,在AndroidStudio中会自行引入,不必多言。
设置属性目前有以下几个选项,后序还会添加其它的:
* 背景颜色
* 字体颜色
* 边框颜色
* 字体大小
* 隐藏字符
* 长度

<feifu.com.testview.gridpswview.GridPswView
     android:background="#f00"android:layout_gravity="center_vertical"android:id="@+id/grid"ddDog:textColor="#0f0"ddDog:backgroundColor="#f00"ddDog:length="9"ddDog:textSize="30sp"android:layout_width="match_parent"android:layout_height="wrap_content"/>

好了现在运行一下吧,看看效果

设置的颜色不是很好,看着较Low,读者可以自行设置自行设置。

遗留问题

待续。。。

github源码:
https://github.com/dd-Dog/grid-psw-view

自定义view,仿微信、支付宝密码输入控件的源码实现相关推荐

  1. php支付密码控件,Android高仿微信支付密码输入控件实例代码

    这篇文章主要为大家详细介绍了Android高仿微信支付密码输入控件的具体实现代码,供大家参考,具体内容如下 像微信支付密码控件,在app中是一个多么司空见惯的功能.最近,项目需要这个功能,于是乎就实现 ...

  2. 自定义View之自定义支付宝密码输入控件

    效果如图上边(录像文件被压缩有些失真) 1.可以设置密码位数 2.每个格子能输入一位的数字 3.背景框.分割线.圆点颜色可以设置 4.位数输入满后可直接进行提示或后续操作 首先设置下需要的属性attr ...

  3. Android 仿微信语音录音小控件

    Android 仿微信语音录音小控件 前段时间一直在做IM聊天这方面的撸码工作,涉及到了很多小控件,有时间我会慢慢给大家分享一下我的小成果,希望大家一起学习,一起进步,今天来和大家来说一下Androi ...

  4. java 头像 微信群_仿微信群头像九宫格控件 LQRNineGridImageView

    软件介绍 仿微信群头像九宫格控件 一.简介: 参照Android 仿微信群聊头像文章学习开发的一个仿微信群头像九宫格控件,感谢博主Loften_93663469. 效果如下: 二.使用: 1.在自己项 ...

  5. Android 平板中 自定义键盘(popuwindow) 居于屏幕左下方 仿微信的密码输入界面

    之前博客中,介绍过使用谷歌提供的键盘的一些api,可以很好地自定义键盘,参考我之前的博客链接:android 自定义键盘 ,这个有一个局限性,只能占满屏幕,无法做到只能占一部分的需求键盘,如下图我平板 ...

  6. android旋转不重绘,Android自定义view仿微信刷新旋转小风车

    本文实例为大家分享了Android仿微信刷新旋转小风车 具体代码,供大家参考,具体内容如下 不太会录像,没办法,智能截图了 不多说了,直接上代码 package com.shipneg.demoysp ...

  7. Android 自定义View 仿微信好友,字母排序

    一 :具体说下思路(注意:一下代码如果没有显示则访问     https://www.jianshu.com/p/2da89b56871f   ) 1 :整体用到的控件,list view(recyc ...

  8. Android 自定义View 三板斧之二——组合现有控件

    通常情况下,Android实现自定义控件无非三种方式. Ⅰ.继承现有控件,对其控件的功能进行拓展. Ⅱ.将现有控件进行组合,实现功能更加强大控件. Ⅲ.重写View实现全新的控件 上文说过了如何继承现 ...

  9. Android自定义View实战:简约风歌词控件

    作者:jsyjst 前言 最近重构了之前的音乐播放器,添加了许多功能,比如歌词,下载功能等.这篇文章就让我们聊聊歌词控件的实现,先上效果图,如果感觉海星,就继续瞧下去! 看到这里,估计你对这个控件还有 ...

最新文章

  1. [转]一次.NET Web应用程序安装包的制作经历:Sql数据库安装的3种方式 配置IIS及Web.Config文件...
  2. matlab的开方算法_正确的「记事本」打开方式:能渲染3D图像,还能玩贪吃蛇
  3. win8.1 php mysql,win8.1(64位) apache2.4.3+php5.6.3+mysql5.6安装
  4. 简单易懂的 pwnable.kr 第一题[fd]Writeupt
  5. FaceBook机器学习开源DL模块
  6. c++ 动态分配数组_C/C++编程笔记:「C语言指针」民间解读版本
  7. IT互联网公司的笔试的输入输出- c++ python
  8. using 关键字有两个主要用途
  9. WF4 Bata 2
  10. spss典型相关分析_R语言实战 多元统计分析Day10— —典型相关分析
  11. centos7 php多版本切换_CentOS7服务搭建----搭建私有云盘01
  12. IOCP中多次投递WSASend
  13. idea 快捷键大全(全网最详细)
  14. 构建自己的Aleax查询服务
  15. 如何通过校园招聘,进入互联网大厂?
  16. 傻傻分不清?云存储、云计算与分布式存储、分布式计算是一回事吗?
  17. 【Linux】GCC程序开发工具(下)
  18. 设计模式 - 行为型设计模式 - 观察者模式(Java)
  19. 华硕A456UR7500初次非完美黑苹果安装教程
  20. Raphael Js矢量库API简介:

热门文章

  1. STM32单片机程序dll实现
  2. GIS制图的基础三点
  3. freetype的简单使用之 生成一个字体bmp
  4. ISO26262解析(四)——FMEDA
  5. Graph Convolutional Neural Network - Spatial Convolution 图卷积神经网络 — 空域卷积详解
  6. Typescript泛型与implements子句
  7. 【Java设计模式】组合模式
  8. H.264向H.265的转变及其相关技术
  9. 极限和连续+偏导+方向导数+可微+梯度+链式法则+hessian矩阵
  10. 几张图片生成3D模型?距离真正的AI建模还有多远?