Android仿IOS解锁密码界面-自定义view系列

  • 功能简介
  • 主要实现步骤-具体内容看github项目里的代码
  • xml相关属性设置
  • Android Studio 代码
  • Android技术生活交流

功能简介

仿ios解锁密码界面,按钮文字等全部用canvas自绘制出来,避免了创建多个button和textview组合起来实现密码解锁界面,一个view搞定所有,代码简洁清晰更易于维护。同时按压还带震动效果



主要实现步骤-具体内容看github项目里的代码

1.定义按钮的bean类ButtonData这里储存了按钮的相关信息,颜色,大小,rect位置,是否为当前选中,数字number,等。
2.定义好我们需要哪些按钮,将其储存在一个二维数组里mNumberArray片,这样我们方遍历数组中的所有value然后计算大小位置mButtonMap
3.大小位置的计算,先将所有的button视为一个整体按钮layout,计算出整体按钮layout处于canvas的位置,再挨个计算每个button的位置。计算完后将其数字作为key,创建ButtonData对象作为value将其储存在mButtonMap。.储存在mButtonMap里我们就可以对数据进行操作了,比如返回哪个按钮被当前选中。
5. 确定哪个按钮被当前选中,在onTouchEvent我们可以获取到手指按压时的位置,接着从mButtonMap数据中遍历所有ButtonData对象里的位置getRect。rect有个方法是可以检测是否包含某个x,y的位置。包含了就表示,当前button被选中。
6.确定了哪个按钮button被选中后,接下来就通过其ButtonData对象进行一些列操作就行了,如果是数字,则将其代表的数字number添加至mPassword_input进行展示,如果是删除 或 返回,则执行其他操作
7.通过接口 OnPasswordListener 我们可以获取返回事件,和密码输入后的结果


xml相关属性设置

属性名 介绍
mPassword_correct 设置正确的密码
setOnPasswordListener 设置监听事件,返回 和 密码正确结果

Android Studio 代码


/*** Author:游丰泽 Franco* Describe:仿Ios数码解锁屏* Time: 0001/01/01* CSDN:https://blog.csdn.net/ruiruiddd/article/details/117356567*/
public class IosUnlockPasswordView extends FrameLayout {private Context mContext;//TAGprivate String TAG = IosUnlockPasswordView.class.getName();//两个功能,返回 和 删除private static final String FUNCTION_BACK = "返回",FUNCTION_DELETE = "删除";//画笔private Paint mPaint;//view-背景颜色private int mView_backgroundColor = Color.WHITE;//canvas可绘制的高度private int mCanvasHeight = 0;//canvas可绘制的宽private int mCanvasWidth = 0;//按钮-二维数组private int[][] mNumberArray = new int[][]{{1,2,3},{4,5,6},{7,8,9},{10,0,11}};//按钮-将int和按钮数据以哈希map的形式储存对应起来private HashMap<Integer,ButtonData> mButtonMap = new HashMap<>();//按钮-颜色-未选中private int mButton_color_normal = Color.LTGRAY;//按钮-颜色-选中private int mButton_Color_selected = Color.DKGRAY;//按钮-文字-颜色-未选中private int mButton_Color_text_normal = Color.WHITE;//按钮-文字-颜色private int mButton_Color_text_selected = Color.LTGRAY;//按钮-文字-大小private int mButton_Size_text = 40;//按钮-长宽private int mButton_width_height = 0;//按钮-之间的间距private int mButton_margin = 80;//按钮-布局-大小private int mButton_layout_height_Width = 0;//按钮-布局-上方margin,使其处于view中间private int mButton_layout_margin_top = 0;//密码-记录输入后的密码private String mPassword_input = "";//密码-位置rectprivate Rect mPassword_rect = new Rect();//密码-文字大小private int mPassword_text_size = 10;//密码-文字颜色private int mPassword_text_color = Color.BLACK;//密码-正确密码设置,默认123456private int mPassword_correct = 123456;//按压震动private final int SHAKE_TIME = 50;//接口事件private OnPasswordListener mOnPasswordListener;public IosUnlockPasswordView(Context context) {super(context);initial(context);}public IosUnlockPasswordView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);initial(context);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mButton_margin = getMeasuredWidth() <= getMeasuredHeight() ? getMeasuredWidth() /20 : getMeasuredHeight() /20;mButton_Size_text = getMeasuredWidth() <= getMeasuredHeight() ? getMeasuredWidth() /10 : getMeasuredHeight() /10;mPassword_text_size = getMeasuredWidth() <= getMeasuredHeight() ? getMeasuredWidth() /20 : getMeasuredHeight() /20;//设置长宽占满全屏
//        setMeasuredDimension(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);}private void initial(Context context){mContext=context;setWillNotDraw(false);mPaint=new Paint();mPaint.setAntiAlias(true);setBackgroundColor(mView_backgroundColor);}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()){case MotionEvent.ACTION_DOWN:doSelectedInt(event.getX(),event.getY());break;case MotionEvent.ACTION_UP:doCalculatePasswordInput();doClearAll();break;}doRefreshUI();return true;}/*** 计算展示的输入密码*/private void doCalculatePasswordInput(){if(null != getButtonSelected()) {if(!getButtonSelected().isFunction){if(mPassword_input.length() < String.valueOf(mPassword_correct).length()) {mPassword_input = mPassword_input + getButtonSelected().getNumber();}if(mPassword_input.length() >= String.valueOf(mPassword_correct).length()) {boolean isCorrect = mPassword_input.equals(String.valueOf(mPassword_correct));if(null != mOnPasswordListener){mOnPasswordListener.onListenerPasswordResult(mPassword_input,isCorrect);}}}else {switch (getButtonSelected().getNumber()){case FUNCTION_BACK:if(null != mOnPasswordListener){mOnPasswordListener.onListenerBack(true);}break;case FUNCTION_DELETE:if(mPassword_input.length()>=1) {mPassword_input = mPassword_input.substring(0, mPassword_input.length() - 1);}break;default:break;}}}}/*** 计算按压时,选中的数字*/private void doSelectedInt(float x, float y){if(null != mButtonMap){for(int i=0;i<=mButtonMap.size();i++){if(null != mButtonMap.get(i)) {if (mButtonMap.get(i).getRectF().contains(x, y)) {mButtonMap.get(i).setSelected(true);Vibrate(mContext, SHAKE_TIME);Log.d(TAG, "onTouchEvent:选中 " + getButtonSelected().getNumber());}else {mButtonMap.get(i).setSelected(false);}}}}}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);onDraw_initialValues(canvas); //初始化一些数据onDraw_doDrawButtons(canvas); //画按钮布局onDraw_doDrawPassword(canvas); //画展示输入过的密码}/*** 初始化一些数据* @param canvas*/private void onDraw_initialValues(Canvas canvas){mCanvasHeight = canvas.getHeight(); //画板高mCanvasWidth = canvas.getWidth();   //画板宽mButton_layout_height_Width = mCanvasWidth <= mCanvasHeight ? mCanvasWidth: mCanvasHeight;  //按钮布局的大小//每个按钮的长宽 = (布局总长宽 - 4个按钮间距 ) / 3个按钮数量mButton_width_height = (mButton_layout_height_Width - (mNumberArray[0].length*2) * mButton_margin ) / (mNumberArray[0].length) ;//计算按钮布局上方margin,使其处于view中间mButton_layout_margin_top = (mCanvasHeight - mButton_layout_height_Width)/2;}/*** 画按钮基本轮廓* @param canvas*/private void onDraw_doDrawButtons(Canvas canvas){for(int i = 0; i< mNumberArray.length; i++){for(int j = 0; j< mNumberArray[i].length; j++){if(!mButtonMap.containsKey(mNumberArray[i][j])){RectF rectF = new RectF();rectF.left = mButton_margin * (j+2) + mButton_width_height * j;rectF.right = rectF.left + mButton_width_height ;rectF.top = mButton_layout_margin_top+mButton_margin * (i+2) + mButton_width_height * i;rectF.bottom = rectF.top + mButton_width_height ;mButtonMap.put(mNumberArray[i][j], new ButtonData(String.valueOf(mNumberArray[i][j]),rectF,mButton_color_normal,mButton_Color_selected,mButton_Color_text_normal,mButton_Color_text_selected,mButton_Size_text,false));}ButtonData buttonData = getButton(mNumberArray[i][j]);if(null != buttonData) {mPaint.setStyle(Paint.Style.FILL);mPaint.setColor(buttonData.getColorBackground());canvas.drawArc(buttonData.getRectF(), 0f, 360f, true, mPaint);onDraw_doDrawButtonText(canvas,buttonData); //画按钮文字}}}}/*** 画按钮中的文字*/private void onDraw_doDrawButtonText(Canvas canvas,ButtonData buttonData){mPaint.setTextSize(buttonData.getTextSize());mPaint.setFakeBoldText(true);mPaint.getTextBounds(buttonData.getNumber(),0,buttonData.getNumber().length(),buttonData.getRectText());mPaint.setColor(buttonData.getTextColor());canvas.drawText(buttonData.getNumber(),buttonData.getNumberStartX(),buttonData.getNumberStartY(),mPaint);}/*** 画输入过的密码*/private void onDraw_doDrawPassword(Canvas canvas){mPaint.setTextSize(mPassword_text_size);mPaint.setFakeBoldText(true);mPaint.setColor(mPassword_text_color);mPaint.getTextBounds(mPassword_input,0,mPassword_input.length(),mPassword_rect);canvas.drawText(mPassword_input,(canvas.getWidth())/2 - (mPassword_rect.left+mPassword_rect.right)/2,mButton_layout_margin_top/2 - (mPassword_rect.top+mPassword_rect.bottom)/2,mPaint);}/*** 根据手机的分辨率从 px(像素) 的单位 转成为 dp*/private int px2dp(Context context, float pxValue) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (pxValue / scale + 0.5f);}/*** 将px值转换为sp值,保证文字大小不变* @param pxValue* @return*/public static int px2sp(Context context, float pxValue) {final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;return (int) (pxValue / fontScale + 0.5f);}/*** 刷新UI*/private void doRefreshUI(){invalidate();}/*** 清除记录-当手指离开所选按钮或从屏幕抬起*/private void doClearAll(){if(null != mButtonMap) {for (int i = 0; i <= mButtonMap.size(); i++) {if(null != mButtonMap.get(i)) {mButtonMap.get(i).setSelected(false);}}}}/*** 获取当前选中的按钮数据*/private ButtonData getButtonSelected(){if(null != mButtonMap) {for (int i = 0; i<=mButtonMap.size(); i++) {if(null != mButtonMap.get(i)) {if (mButtonMap.get(i).isSelected()) {return mButtonMap.get(i);}}}}return null;}/*** 根据key获取按钮数据*/private ButtonData getButton(int number){if(null != mButtonMap) {return mButtonMap.get(number);}return null;}//得到正确密码public int getPassword_correct() {return mPassword_correct;}//设置正确密码public void setPassword_correct(int Password_correct) {this.mPassword_correct = Password_correct;}/*** 按钮表单信息-记录rectF位置-当前数字*/private class ButtonData {private String number = "";   //按钮数字private String character = "";   //按钮所代表的英文字母private RectF rectF = null;  //按钮的位置 rectFprivate int colorNormal = -1;private int colorSelected = -1;private int colorTextNormal = -1;private int colorTextSelected = -1;private boolean isSelected = false;private Rect rectText = null; //文字矩形位置private int textSize = 20; //文字大小private boolean isFunction = false;public ButtonData(String number, RectF rectF, int colorNormal, int colorSelected,int colorTextNormal,int colorTextSelected, int textSize,boolean isSelected){this.number = number;this.rectF = rectF;this.colorNormal = colorNormal;this.colorSelected = colorSelected;this.isSelected = isSelected;this.colorTextNormal = colorTextNormal;this.colorTextSelected = colorTextSelected;this.textSize= textSize;this.isFunction = false;rectText = new Rect();doSetNotNumber(number);}private void doSetNotNumber(String number){if(number.equals("10")|| number.equals("11")){if(number.equals("11")){this.number = FUNCTION_DELETE;}if(number.equals("10")){this.number = FUNCTION_BACK;}this.isFunction = true;this.textSize= this.textSize / 2;this.colorTextNormal = Color.DKGRAY;this.colorTextSelected = Color.BLACK;this.colorNormal = Color.TRANSPARENT;this.colorSelected = Color.TRANSPARENT;}}public float getNumberStartX() {if(null != rectF && null != rectText) {return (rectF.left+rectF.right)/2 - (rectText.left+rectText.right)/2;}else {return -1f;}}public float getNumberStartY() {if(null != rectF && null != rectText) {return (rectF.top+rectF.bottom)/2 - (rectText.top+rectText.bottom)/2;}else {return -1f;}}public String getNumber() {return number;}public void setNumber(String number) {this.number = number;}public String getCharacter() {return character;}public void setCharacter(String character) {this.character = character;}public RectF getRectF() {return rectF;}public void setRectF(RectF rectF) {this.rectF = rectF;}public int getColorBackground() {return isSelected? colorSelected :colorNormal;}public int getTextColor() {return isSelected? colorTextSelected :colorTextNormal;}public int getTextSize(){return textSize;}public boolean isSelected() {return isSelected;}public boolean isFunction() {return isFunction;}public void setSelected(boolean selected) {isSelected = selected;}public Rect getRectText() {return rectText;}}/*** 震动* @param context* @param milliseconds*/private void Vibrate(final Context context, long milliseconds) {Vibrator vib = (Vibrator) context.getSystemService(Service.VIBRATOR_SERVICE);vib.vibrate(milliseconds);}/*** 接口,操作返回,或者输入密码结束后的结果*/public interface OnPasswordListener{void onListenerBack(boolean isBack);void onListenerPasswordResult(String passwordInput, boolean isCorrect);}/*** 添加接口*/public void setOnPasswordListener(OnPasswordListener onEventListener){if(null == mOnPasswordListener){mOnPasswordListener = onEventListener;}}
}

Android技术生活交流

微信


Android仿IOS解锁密码界面-自定义view系列(6)相关推荐

  1. android 密码解锁程序,android 仿ios数字密码解锁界面的实例

    如下所示: 每个Android开发人员都知道,现在android的解锁最常用的就是九宫格解锁,ios的解锁常用的是数字密码解锁.而我们在开发工程中,很多时候,都需要android和ios进行结合.有的 ...

  2. android仿支付提现功能,Android应用开发Android 仿微信支付密码界面

    本文将带你了解Android应用开发Android 仿微信支付密码界面,希望本文对大家学Android有所帮助. 使用 Bundle bundle = new Bundle(); bundle.put ...

  3. Android 仿芝麻信用进度条,自定义View仿支付宝芝麻信用分仪表盘效果

    image 前言 灵感来自几天前看到一位作者的仿芝麻信用自定义View的文章很不错,所以我换了一种方式来进行实现,写了旧版和新版芝麻信用分仪表盘的效果. 截图 这是我做的效果,还是有点差距的,嘿嘿. ...

  4. android仿微信雷达 头像效果 自定义view

    ScreeningRadarView public class ScreeningRadarView extends View {// 定义画笔Paint paint;float radiusDiff ...

  5. Android仿IOS滑动关机-自定义view系列(6)

    Android仿IOS滑动关机-自定义view系列 功能简介 GIf演示 主要实现步骤-具体内容看github项目里的代码 Android技术生活交流 更多其他页面-自定义View-实用功能合集:点击 ...

  6. Android安卓仿IOS音量调节-自定义view系列(4)

    Android安卓仿IOS音量调节-自定义view系列 功能简介 主要实现步骤 xml相关属性设置 java代码 Android技术生活交流 更多其他页面-自定义View-实用功能合集:点击查看 Gi ...

  7. Android仿IOS吸边弹簧阻尼移动组件SpringMovingView-自定义view系列(3)

    () Android仿ios吸边弹簧阻尼效果的移动组件SpringMovingView 功能简介 Android技术生活交流 Gif演示 实现步骤 java代码 Android技术生活交流 更多其他页 ...

  8. android 仿ios动画效果代码,Android仿IOS上拉下拉弹性效果的实例代码

    用过iphone的朋友相信都体验过页面上拉下拉有一个弹性的效果,使用起来用户体验很好:Android并没有给我们封装这样一个效果,我们来看下在Android里如何实现这个效果.先看效果,感觉有些时候还 ...

  9. Android仿微信气泡聊天界面设计

    Android仿微信气泡聊天界面设计 微信的气泡聊天是仿iPhone自带短信而设计出来的,不过感觉还不错可以尝试一下仿着微信的气泡聊天做一个Demo,给大家分享一下!效果图如下: 气泡聊天最终要的是素 ...

最新文章

  1. 判断有向图g中顶点i到顶点j是否有路径_[源码和文档分享]基于Dijkstra算法的最短路径问题求解...
  2. 【干货】前端自学之路(持续更新)
  3. echarts统计x轴区间的数值
  4. 在lean trace mode下运行function
  5. python回归预测例子_案例实战 | 逻辑回归实现客户流失预测(附Python代码与源数据)...
  6. libpcre.so.1 cannot be found
  7. 彼得林奇:赚钱密码(1990年一次演讲)
  8. 小编带着小白看springboot源码3
  9. VC中调用 Excel 的总结
  10. zbrush史上最全笔刷下载43G(1200个)
  11. 华为asph是什么型号_华为triple camera这是什么型号
  12. linux shell题库,shell习题-30
  13. 九. MySQL InnoDB 底层结构
  14. Git版本控制器(涵盖GitHub\Gitee码云\GitLab),全网最详细教程
  15. HTTPS中间人攻击实验
  16. 流线动态图python_流的解释|流的意思|汉典“流”字的基本解释
  17. 如何学习编程?怎样学好编程?
  18. Google Chrome 成为互联网的看门人
  19. Web前端开发技术:Vue开发基础(1)
  20. maven明明本地仓库有依赖包,还会远程下载的问题

热门文章

  1. android 蓝牙搜索、配对连接通信总结
  2. FlashFXP,flashfxp怎么上传文件
  3. 破解“封闭式基金折价之谜”(ZT)
  4. 从细节最初判断一家公司
  5. JavaEE:网络原理之TCP/IP
  6. 东南大学计算机考研信息汇总
  7. Matlab 类函数基本运用
  8. 可以去看阿哲演唱会咯~
  9. Android 编译之source和lunch
  10. 手动刷入Android 4.4.1 KOT49E OTA更新包