android-otpview-pinview源码解析核心实现原理【免费下载链接】android-otpview-pinviewA custom view to enter otp of different sizes used usually in cases of authentication.项目地址: https://gitcode.com/gh_mirrors/an/android-otpview-pinviewandroid-otpview-pinview是一个用于输入不同长度OTP验证码的自定义视图广泛应用于身份验证场景。本文将深入解析其核心实现原理帮助开发者理解其工作机制和设计思想。一、核心类结构与继承关系OtpView作为整个库的核心组件继承自AppCompatEditText这使其具备了EditText的基本功能同时又能实现自定义的外观和行为。public class OtpView extends AppCompatEditText { // 类实现代码 }这种设计选择的优势在于继承EditText的文本处理能力保留系统EditText的辅助功能支持可通过重写方法实现自定义绘制和交互二、自定义属性与初始化流程OtpView通过自定义属性实现灵活配置在构造函数中完成初始化工作。1. 自定义属性定义在otpview/src/main/res/values/attrs.xml中定义了一系列可配置属性如OtpViewType视图类型矩形、线条或无OtpItemCountOTP位数OtpItemHeight/Width每个输入框的高度和宽度OtpItemSpacing输入框之间的间距OtpLineColor线条颜色OtpCursorColor光标颜色2. 属性解析与初始化在OtpView的构造函数中通过TypedArray解析XML中定义的属性值并进行初始化public OtpView(Context context, Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // 获取资源和主题 // 解析TypedArray属性 viewType typedArray.getInt(R.styleable.OtpView_OtpViewType, VIEW_TYPE_NONE); otpViewItemCount typedArray.getInt(R.styleable.OtpView_OtpItemCount, DEFAULT_COUNT); // 其他属性解析... // 初始化画笔、动画等 setupAnimator(); setMaxLength(otpViewItemCount); // 其他初始化工作... }三、视图测量与布局OtpView重写了onMeasure方法根据配置的属性计算视图的宽高Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode MeasureSpec.getMode(widthMeasureSpec); int heightMode MeasureSpec.getMode(heightMeasureSpec); int widthSize MeasureSpec.getSize(widthMeasureSpec); int heightSize MeasureSpec.getSize(heightMeasureSpec); // 计算宽度 if (widthMode MeasureSpec.EXACTLY) { width widthSize; } else { int boxesWidth (otpViewItemCount - 1) * otpViewItemSpacing otpViewItemCount * otpViewItemWidth; width boxesWidth ViewCompat.getPaddingEnd(this) ViewCompat.getPaddingStart(this); // 间距为0时的特殊处理... } // 计算高度 height heightMode MeasureSpec.EXACTLY ? heightSize : boxHeight getPaddingTop() getPaddingBottom(); setMeasuredDimension(width, height); }这段代码根据OTP位数、每个输入框的大小和间距计算出整个视图的宽度确保在不同模式下都能正确显示。四、自定义绘制流程OtpView的核心功能通过重写onDraw方法实现主要包括背景绘制、文本绘制和光标绘制。1. 绘制主流程Override protected void onDraw(Canvas canvas) { canvas.save(); updatePaints(); drawOtpView(canvas); canvas.restore(); } private void drawOtpView(Canvas canvas) { // 计算当前要填充的位置 int nextItemToFill rtlTextDirection ? otpViewItemCount - 1 : getText().length(); // 循环绘制每个OTP输入框 for (int i 0; i otpViewItemCount; i) { boolean itemSelected isFocused() nextItemToFill i; boolean itemFilled i nextItemToFill; // 更新绘制区域 updateItemRectF(i); updateCenterPoint(); // 绘制背景 drawItemBackground(canvas, itemState); // 绘制光标 if (itemSelected) { drawCursor(canvas); } // 绘制边框矩形或线条 if (viewType VIEW_TYPE_RECTANGLE) { drawOtpBox(canvas, i); } else if (viewType VIEW_TYPE_LINE) { drawOtpLine(canvas, i); } // 绘制文本或提示 if (rtlTextDirection) { // RTL方向文本绘制 } else { // LTR方向文本绘制 } } // 绘制选中状态的边框 if (isFocused() viewType VIEW_TYPE_RECTANGLE) { // 绘制选中状态边框 } }2. 绘制不同类型的输入框OtpView支持两种主要的视觉样式矩形框和下划线。矩形框样式private void drawOtpBox(Canvas canvas, int i) { if (getText() ! null hideLineWhenFilled i getText().length()) { return; } canvas.drawPath(path, paint); }下划线样式private void drawOtpLine(Canvas canvas, int i) { if (getText() ! null hideLineWhenFilled i getText().length()) { return; } // 设置画笔样式 paint.setStyle(Paint.Style.FILL); // 更新线条绘制区域 itemLineRect.set(/* 计算坐标 */); // 绘制线条 updateRoundRectPath(itemLineRect, otpViewItemRadius, otpViewItemRadius, drawLeft, drawRight); canvas.drawPath(path, paint); }五、文本处理与输入交互OtpView对文本输入和选择进行了特殊处理以适应OTP输入的需求。1. 文本变化监听Override protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { if (start ! text.length()) { moveSelectionToEnd(); } // OTP输入完成回调 if (text.length() otpViewItemCount onOtpCompletionListener ! null) { onOtpCompletionListener.onOtpCompleted(text.toString()); } // 光标闪烁 makeBlink(); // 动画处理 if (isAnimationEnable) { // 处理输入动画 } }2. 光标控制OtpView实现了自定义的光标闪烁效果private void makeBlink() { if (shouldBlink()) { if (blink null) { blink new Blink(); } removeCallbacks(blink); drawCursor false; postDelayed(blink, BLINK); } else { if (blink ! null) { removeCallbacks(blink); } } } private class Blink implements Runnable { private boolean cancelled; Override public void run() { if (cancelled) { return; } removeCallbacks(this); if (shouldBlink()) { invalidateCursor(!drawCursor); postDelayed(this, BLINK); } } // 取消和恢复方法... }六、扩展性设计OtpView提供了丰富的API允许开发者通过代码动态修改其属性// 设置OTP位数 public void setItemCount(int count) { otpViewItemCount count; setMaxLength(count); requestLayout(); } // 设置线条颜色 public void setLineColor(ColorInt int color) { lineColor ColorStateList.valueOf(color); updateColors(); } // 设置动画开关 public void setAnimationEnable(boolean enable) { isAnimationEnable enable; } // 设置完成监听 public void setOtpCompletionListener(OnOtpCompletionListener otpCompletionListener) { this.onOtpCompletionListener otpCompletionListener; }这些方法使OtpView能够适应不同的使用场景和需求变化。七、总结android-otpview-pinview通过继承AppCompatEditText并自定义绘制和交互逻辑实现了一个功能完善、高度可定制的OTP输入视图。其核心设计思想包括单一职责专注于OTP输入场景提供针对性的功能灵活配置通过自定义属性和API支持多样化的视觉样式良好交互优化输入体验包括光标控制、动画效果等扩展性设计提供丰富的API支持动态修改和扩展通过深入理解其源码实现开发者不仅可以更好地使用这个库还能学习到自定义View的设计模式和最佳实践为自己的项目开发提供参考。【免费下载链接】android-otpview-pinviewA custom view to enter otp of different sizes used usually in cases of authentication.项目地址: https://gitcode.com/gh_mirrors/an/android-otpview-pinview创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考