自定义V_04_InputPassword

一、效果


密码输入.png

二、描述
实现一个密码输入框,继承自Editext免去了位置的测量,将这个放入一个Dialog中,可以实现一个自定义的输入密码键盘
三、分析
1.首先要画好背景框
2.在画里面的竖线
1)每一次:从上一次的竖线宽度+(本次条目的宽度 )+ 本次边框的宽度
int startX = bgBorderSize + (i + 1) * itemWidth + i * bgBorderSize;


表格.png

3.画圆点
1)其实就是用的Canvas画View替换了系统的draw(),如果这里不注释 super.onDraw(canvas);在最开始的起点那里长按依然可以选中那些文字,当然这不是重点;

2)获取文字长度计算圆点个数:画的位置相当于一个 错位 的感觉,就是第一次是框的宽度的一半,下一个圆点距离就是上次位置加一个框的宽度
圆点.png

3)键盘就简单多了,继承自LinearLayout引入布局,主要是把子View设置监听事件,然后进行一个回调。

四、动手
1)man.xml




··
2)Main.java

    editextLayout = findViewById(R.id.editextLayout);
    inputKeyBord = findViewById(R.id.inputKeyBord);
    //屏蔽系统键盘
    editextLayout.setEnabled(false);

    inputKeyBord.setKeyBordBack(new InputKeybordLayout.keyBordBack() {
        @Override
        public void click(String str) {
            editextLayout.addTextNumber(str);
        }

        @Override
        public void delete() {
            editextLayout.deleteNumber();
        }
    });

3)MyEditextLayout.java

public class MyEditextLayout extends AppCompatEditText {
  //密码个数
  private int inputCount;
  //点的半径大小
  private int pointSizePi;
  //点的颜色
  private int pointColor = Color.GRAY;
  //分隔线颜色
  private int lineColor = Color.GRAY;
  //线条宽度
  private int lineWidth = 1;
  //背景边框颜色
  private int bgBorderColor = Color.GRAY;
  //背景边框大小
  private int bgBorderSize = 1;
  //背景边框圆角
  private int bgCircularBeadSize = 2;
  //设置最大输入个数
  private int MAXNUMBERS = 6;
  private Paint mPaint;
  private Paint mBGPaint;
  private Paint mPointPaint;
  public MyEditextLayout(Context context) {
      super(context);
  }
public MyEditextLayout(Context context, AttributeSet attrs) {
      super(context, attrs);
      init(context, attrs);
  }

  public MyEditextLayout(Context context, AttributeSet attrs, int defStyleAttr) {
      super(context, attrs, defStyleAttr);
      init(context, attrs);
  }

  private void init(Context context, AttributeSet attrs) {
      TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyEditextLayout);

      inputCount = array.getInteger(R.styleable.MyEditextLayout_inputCount, inputCount);
      pointSizePi = (int) array.getDimension(R.styleable.MyEditextLayout_pointSizePi, dip2px(pointSizePi));
      pointColor = array.getColor(R.styleable.MyEditextLayout_pointColor, pointColor);
      lineColor = array.getColor(R.styleable.MyEditextLayout_lineColor, lineColor);
      lineWidth = array.getInteger(R.styleable.MyEditextLayout_lineWidth, (int) dip2px(lineWidth));
      bgBorderColor = array.getColor(R.styleable.MyEditextLayout_bgBorderColor, bgBorderColor);
      bgBorderSize = (int) array.getDimension(R.styleable.MyEditextLayout_bgBorderSize, dip2px(bgBorderSize));
      bgCircularBeadSize = (int) array.getDimension(R.styleable.MyEditextLayout_bgCircularBeadSize, bgCircularBeadSize);

      array.recycle();

      mPaint = getMPaint();
      mPaint.setColor(bgBorderColor);


      mBGPaint = getMPaint();
      mBGPaint.setColor(bgBorderColor);
      mBGPaint.setStrokeWidth(bgBorderSize);

      mPointPaint = getMPaint();
      mPointPaint.setColor(pointColor);
      mPointPaint.setStyle(Paint.Style.FILL_AND_STROKE);

      setTextColor(0X00ffffff); //把用户输入的内容设置为透明
      setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_NORMAL);
      this.setBackgroundDrawable(null);
      setLongClickable(false);
      setTextIsSelectable(false);
      setCursorVisible(false);
  }@Override
  protected void onDraw(Canvas canvas) {//        super.onDraw(canvas);
      drawBorderBG(canvas);
      drawBorderSeparate(canvas);
      drawPWD(canvas);
  }

  public void addTextNumber(String str) {
      if (TextUtils.isEmpty(str) || MAXNUMBERS == str.length())
          return;
      setText(getText() + str);
  }

  public void deleteNumber() {
      if (TextUtils.isEmpty(getText()) || getText().length() <= 0)
          return;
      String str = getText().toString().trim();
      str = str.substring(0, str.length() - 1);
      setText(str);
  }


  /**
   * 绘制框中心的点
   */
  private void drawPWD(Canvas canvas) {
      //实心圆
      //输入的个数
      int pwdLength = getText().toString().length();
      for (int i = 0; i < pwdLength; i++) {
          //核心:竖线宽度 + 宽度的一半
          //      竖线宽度      + 项的宽度* i  +  i+竖线条数       + 项宽度一半
          int cx = bgBorderSize + itemWidth * i + i * bgBorderSize + itemWidth / 2;
          int cy = getHeight() / 2;
          canvas.drawCircle(cx, cy, pointSizePi, mPointPaint);
      }
  }

  /**
   * 中间的分隔
   *
   * @param canvas
   */
  private int itemWidth = 0;

  private void drawBorderSeparate(Canvas canvas) {
      //总的宽度 - (数量减-1 * 条竖线)
      int passwordWidth = getWidth() - (inputCount - 1) * lineWidth;
      itemWidth = passwordWidth / inputCount;
      mPaint.setStrokeWidth(bgBorderSize);
      //        itemWidth = (getWidth() - 2 * bgBorderSize - (inputCount - 1) * lineWidth) / inputCount;
      for (int i = 0; i < inputCount - 1; i++) {
          //x = 每一次:从上一次的竖线宽度+(本次条目的宽度 )+ 本次次边框的宽度
          int startX = bgBorderSize + (i + 1) * itemWidth + i * bgBorderSize;
          int startY = bgBorderSize;
          int endX = startX;
          int endY = getHeight() - bgBorderSize;
          canvas.drawLine(startX, startY, endX, endY, mPaint);
      }

  }

  /**
   * 确定背景
   *
   * @param canvas
   */
  private void drawBorderBG(Canvas canvas) {
      RectF mRect = new RectF(bgCircularBeadSize, bgCircularBeadSize, getWidth() - bgCircularBeadSize, getHeight() - bgCircularBeadSize);
      if (bgCircularBeadSize > 0) {
          canvas.drawRoundRect(mRect, bgCircularBeadSize, bgCircularBeadSize, mBGPaint);
      } else {
          canvas.drawRect(mRect, mBGPaint);
      }

  }

  private Paint getMPaint() {
      Paint mPaint = new Paint();
      //抗据齿
      mPaint.setAntiAlias(true);
      //防抖动
      mPaint.setDither(true);
      mPaint.setStyle(Paint.Style.STROKE);
      return mPaint;
  }

  private float dip2px(int dip) {
      return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, getResources().getDisplayMetrics());
  }

4)InputKeybordLayout.java

public class InputKeybordLayout extends LinearLayout implements View.OnClickListener {
    public interface keyBordBack{
        void click(String str);
        void delete();
    }
    private keyBordBack keyBordBack;

    public void setKeyBordBack(InputKeybordLayout.keyBordBack keyBordBack) {
        this.keyBordBack = keyBordBack;
    }

    public InputKeybordLayout(Context context) {
        //        super(context);
        this(context, null);
    }

    public InputKeybordLayout(Context context, @Nullable AttributeSet attrs) {
        //        super(context, attrs);
        this(context, attrs, 0);
    }

    public InputKeybordLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        //加载布局
        inflate(context, R.layout.layout_keybord, this);
        addKeyBordClickListener(this);
    }

    /**
     * 递归设置子View事件
     * @param view
     */
    private void addKeyBordClickListener(View view) {
        if (view instanceof ViewGroup){
            //遍历所有的子View设置事件
            for (int i=0;i<((ViewGroup) view).getChildCount();i++){
                View childV = ((ViewGroup) view).getChildAt(i);
                addKeyBordClickListener(childV);
            }
        }else {
            view.setOnClickListener(this);
        }
    }

    @Override
    public void onClick(View v) {
        if (v instanceof TextView){
            //强转获取键盘的数字
            String tx = ((TextView) v).getText().toString();
            if (keyBordBack==null)return;
            if ("删除".equals(tx)){
                keyBordBack.delete();
            }else {
                keyBordBack.click(tx);
            }
        }
    }
}

五、结论
在画框那里有点复杂,主要是算位置那里一定画图参考,明白计算的过程,只有动手才能明白内在的流程。

你可能感兴趣的:(自定义V_04_InputPassword)