Android自定义View实现微信支付密码输入框

本文实例为大家分享了Android实现微信支付密码输入框的具体代码,供大家参考,具体内容如下

创新互联建站成立于2013年,是专业互联网技术服务公司,拥有项目成都做网站、成都网站制作网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元立山做网站,已为上家服务,为立山各地企业和个人服务,联系电话:18982081108

效果图

Android自定义View实现微信支付密码输入框

项目中使用到了支付密码功能,其实这类界面是比较常用的,涉及支付密码的输入的一般都会用到对的,所以单独地把这部分抽取出来,有需要的朋友可以拿去用哈!

效果就是支付,弹出密码框,输入密码,这个过程密码不可见,并且提供一个输入完毕的监听!

这个弹出层呢,其实就是一个DialogFragment,逻辑封装在其内部

一.弹出层进出动画 (anim文件)

push_bottom_in.xml

<?xml version="1.0" encoding="utf-8"?>


 

push_bottom_out.xml

<?xml version="1.0" encoding="utf-8"?>


 

二.drawable资源

selector_item_pressed.xml

<?xml version="1.0" encoding="utf-8"?>

 
 
 

键盘的点击效果

shape_dialog.xml

<?xml version="1.0" encoding="utf-8"?>

 
 

弹出框样式

三.mipmap资源

ic_arrow_down

Android自定义View实现微信支付密码输入框

ic_input_del

Android自定义View实现微信支付密码输入框

icon_del.png

Android自定义View实现微信支付密码输入框

四.layout布局

fragment_pay.xml

支付弹出层布局

<?xml version="1.0" encoding="utf-8"?>


 

 

 
 
 
 

 
 
 
 
 
 
 
 
 
 

 
 

自定义键盘布局

<?xml version="1.0" encoding="utf-8"?>


 

 

 

 

 

 

 

 
 

 

 

 

 
 

 

 

 

 
 

 

 

 


 

 

五.color资源

<?xml version="1.0" encoding="utf-8"?>

 #3F51B5
 #303F9F
 #FF4081

 #919191
 #EBEBEB

 #f0eff5
 #d5d1d1
 #FFFFFF
 #000000
 #212121

六.dimen资源

<?xml version="1.0" encoding="utf-8"?>


 
 40sp
 18sp
 15sp
 12sp
 10sp

 
 20dp
 15dp
 10dp
 10dp
 0.5dp
 10dp
 10dp

 
 50dp
 25dp
 2px

七.styles样式



 
 

 
 

 

 
 
 
 


 
 

 
 
 
 
 
 
 
 


 
 

八.输入键盘view

public class PassWordInputView extends LinearLayout implements View.OnClickListener {

 private InputReceiver inputReceiver;

 public PassWordInputView(Context context, @Nullable AttributeSet attrs) {
 super(context, attrs);
 LayoutInflater.from(context).inflate(R.layout.view_password_input, this);

 initView();
 }

 private void initView() {
 findViewById(R.id.btn_1).setOnClickListener(this);
 findViewById(R.id.btn_2).setOnClickListener(this);
 findViewById(R.id.btn_3).setOnClickListener(this);
 findViewById(R.id.btn_4).setOnClickListener(this);
 findViewById(R.id.btn_5).setOnClickListener(this);
 findViewById(R.id.btn_6).setOnClickListener(this);
 findViewById(R.id.btn_7).setOnClickListener(this);
 findViewById(R.id.btn_8).setOnClickListener(this);
 findViewById(R.id.btn_9).setOnClickListener(this);
 findViewById(R.id.btn_0).setOnClickListener(this);
 findViewById(R.id.btn_del).setOnClickListener(this);

 findViewById(R.id.layout_hide).setOnClickListener(new OnClickListener() {
 @Override
 public void onClick(View v) {
 setVisibility(GONE);
 }
 });
 }

 @Override
 public void onClick(View v) {
 String num = (String) v.getTag();
 this.inputReceiver.receive(num);
 }


 /**
 * 设置接收器
 *
 * @param receiver
 */
 public void setInputReceiver(InputReceiver receiver) {
 this.inputReceiver = receiver;
 }

 /**
 * 输入接收器
 */
 public interface InputReceiver {

 void receive(String num);
 }
}

九.密码框view

public class PayPassWordView extends View {

 private ArrayList result;//输入结果保存
 private int count;//密码位数
 private int size;//默认每一格的大小
 private Paint mBorderPaint;//边界画笔
 private Paint mDotPaint;//掩盖点的画笔
 private int mBorderColor;//边界颜色
 private int mDotColor;//掩盖点的颜色
 private RectF mRoundRect;//外面的圆角矩形
 private int mRoundRadius;//圆角矩形的圆角程度

 public PayPassWordView(Context context) {
 super(context);
 init(null);//初始化
 }

 private InputCallBack inputCallBack;//输入完成的回调
 private PassWordInputView inputMethodView; //输入键盘

 public interface InputCallBack {
 void onInputFinish(String result);
 }

 public PayPassWordView(Context context, AttributeSet attrs) {
 super(context, attrs);
 init(attrs);
 }

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

 /**
 * 初始化相关参数
 */
 void init(AttributeSet attrs) {
 final float dp = getResources().getDisplayMetrics().density;
 this.setFocusable(true);
 this.setFocusableInTouchMode(true);
 result = new ArrayList<>();
 if (attrs != null) {
 TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.PayPassWordView);
 mBorderColor = ta.getColor(R.styleable.PayPassWordView_border_color, Color.LTGRAY);
 mDotColor = ta.getColor(R.styleable.PayPassWordView_dot_color, Color.BLACK);
 count = ta.getInt(R.styleable.PayPassWordView_count, 6);
 ta.recycle();
 } else {
 mBorderColor = Color.LTGRAY;
 mDotColor = Color.GRAY;
 count = 6;//默认6位密码
 }
 size = (int) (dp * 30);//默认30dp一格
 //color
 mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 mBorderPaint.setStrokeWidth(3);
 mBorderPaint.setStyle(Paint.Style.STROKE);
 mBorderPaint.setColor(mBorderColor);

 mDotPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 mDotPaint.setStrokeWidth(3);
 mDotPaint.setStyle(Paint.Style.FILL);
 mDotPaint.setColor(mDotColor);
 mRoundRect = new RectF();
 mRoundRadius = (int) (5 * dp);
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 int w = measureWidth(widthMeasureSpec);
 int h = measureHeight(heightMeasureSpec);
 int wsize = MeasureSpec.getSize(widthMeasureSpec);
 int hsize = MeasureSpec.getSize(heightMeasureSpec);
 //宽度没指定,但高度指定
 if (w == -1) {
 if (h != -1) {
 w = h * count;//宽度=高*数量
 size = h;
 } else {//两个都不知道,默认宽高
 w = size * count;
 h = size;
 }
 } else {//宽度已知
 if (h == -1) {//高度不知道
 h = w / count;
 size = h;
 }
 }
 setMeasuredDimension(Math.min(w, wsize), Math.min(h, hsize));
 }

 private int measureWidth(int widthMeasureSpec) {
 //宽度
 int wmode = MeasureSpec.getMode(widthMeasureSpec);
 int wsize = MeasureSpec.getSize(widthMeasureSpec);
 if (wmode == MeasureSpec.AT_MOST) {//wrap_content
 return -1;
 }
 return wsize;
 }

 private int measureHeight(int heightMeasureSpec) {
 //高度
 int hmode = MeasureSpec.getMode(heightMeasureSpec);
 int hsize = MeasureSpec.getSize(heightMeasureSpec);
 if (hmode == MeasureSpec.AT_MOST) {//wrap_content
 return -1;
 }
 return hsize;
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
 if (event.getAction() == MotionEvent.ACTION_DOWN) {//点击控件弹出输入键盘
 requestFocus();
 inputMethodView.setVisibility(VISIBLE);
 return true;
 }
 return true;
 }

 @Override
 protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
 super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
 if (gainFocus) {
 inputMethodView.setVisibility(VISIBLE);
 } else {
 inputMethodView.setVisibility(GONE);
 }
 }

 @Override
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 final int width = getWidth() - 2;
 final int height = getHeight() - 2;
 //先画个圆角矩形
 mRoundRect.set(0, 0, width, height);
 canvas.drawRoundRect(mRoundRect, 0, 0, mBorderPaint);
 //画分割线
 for (int i = 1; i < count; i++) {
 final int x = i * size;
 canvas.drawLine(x, 0, x, height, mBorderPaint);
 }
 //画掩盖点,
 // 这是前面定义的变量 private ArrayList result;//输入结果保存
 int dotRadius = size / 8;//圆圈占格子的三分之一
 for (int i = 0; i < result.size(); i++) {
 final float x = (float) (size * (i + 0.5));
 final float y = size / 2;
 canvas.drawCircle(x, y, dotRadius, mDotPaint);
 }
 }

 @Override
 public boolean onCheckIsTextEditor() {
 return true;
 }

 @Override
 public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
 outAttrs.inputType = InputType.TYPE_CLASS_NUMBER;//输入类型为数字
 outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE;
 return new MyInputConnection(this, false);
 }

 public void setInputCallBack(InputCallBack inputCallBack) {
 this.inputCallBack = inputCallBack;
 }

 public void clearResult() {
 result.clear();
 invalidate();
 }


 private class MyInputConnection extends BaseInputConnection {
 public MyInputConnection(View targetView, boolean fullEditor) {
 super(targetView, fullEditor);
 }

 @Override
 public boolean commitText(CharSequence text, int newCursorPosition) {
 //这里是接受输入法的文本的,我们只处理数字,所以什么操作都不做
 return super.commitText(text, newCursorPosition);
 }

 @Override
 public boolean deleteSurroundingText(int beforeLength, int afterLength) {
 //软键盘的删除键 DEL 无法直接监听,自己发送del事件
 if (beforeLength == 1 && afterLength == 0) {
 return super.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
  && super.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
 }
 return super.deleteSurroundingText(beforeLength, afterLength);
 }
 }


 /**
 * 设置输入键盘view
 *
 * @param inputMethodView
 */
 public void setInputMethodView(PassWordInputView inputMethodView) {
 this.inputMethodView = inputMethodView;
 this.inputMethodView.setInputReceiver(new PassWordInputView.InputReceiver() {
 @Override
 public void receive(String num) {
 if (num.equals("-1")) {
  if (!result.isEmpty()) {
  result.remove(result.size() - 1);
  invalidate();
  }
 } else {
  if (result.size() < count) {
  result.add(num);
  invalidate();
  ensureFinishInput();
  }
 }


 }
 });
 }

 /**
 * 判断是否输入完成,输入完成后调用callback
 */
 void ensureFinishInput() {
 if (result.size() == count && inputCallBack != null) {//输入完成
 StringBuffer sb = new StringBuffer();
 for (String i : result) {
 sb.append(i);
 }
 inputCallBack.onInputFinish(sb.toString());
 }
 }

 /**
 * 获取输入文字
 *
 * @return
 */
 public String getInputText() {
 if (result.size() == count) {
 StringBuffer sb = new StringBuffer();
 for (String i : result) {
 sb.append(i);
 }
 return sb.toString();
 }
 return null;
 }
}

十.支付弹出层

public class PayFragment extends DialogFragment implements View.OnClickListener {

 public static final String EXTRA_CONTENT = "extra_content"; //提示框内容
 public static final String EXTRA_CONTENT2 = "extra_content2"; //提示框内容
 public static final String EXTRA_CONTENT3 = "extra_content3"; //提示框内容

 private PayPassWordView psw_input;
 private PayPassWordView.InputCallBack inputCallBack;

 @NonNull
 @Override
 public Dialog onCreateDialog(Bundle savedInstanceState) {
 // 使用不带Theme的构造器, 获得的dialog边框距离屏幕仍有几毫米的缝隙。
 Dialog dialog = new Dialog(getActivity(), R.style.BottomDialog);
 dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); // 设置Content前设定
 dialog.setContentView(R.layout.fragment_pay);
 dialog.setCanceledOnTouchOutside(true); //外部点击取消
 // 设置宽度为屏宽, 靠近屏幕底部。
 final Window window = dialog.getWindow();
 window.setWindowAnimations(R.style.AnimBottom);
 window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
 final WindowManager.LayoutParams lp = window.getAttributes();
 lp.width = WindowManager.LayoutParams.MATCH_PARENT; // 宽度持平
 lp.gravity = Gravity.TOP;
 window.setAttributes(lp);
 initView(dialog);
 return dialog;
 }

 private void initView(Dialog dialog) {
 Bundle bundle = getArguments();
 if (bundle != null) {
 TextView tv_content = (TextView) dialog.findViewById(R.id.tv_content);
 TextView tv_content2 = (TextView) dialog.findViewById(R.id.tv_content2);
 TextView tv_content3 = (TextView) dialog.findViewById(R.id.tv_content3);
 tv_content.setText(bundle.getString(EXTRA_CONTENT));
 tv_content2.setText(bundle.getString(EXTRA_CONTENT2));
 tv_content3.setText(bundle.getString(EXTRA_CONTENT3));
 }
 psw_input = (PayPassWordView) dialog.findViewById(R.id.payPwdView);
 PassWordInputView inputMethodView = (PassWordInputView) dialog.findViewById(R.id.inputMethodView);
 psw_input.setInputMethodView(inputMethodView);
 psw_input.setInputCallBack(inputCallBack);
 dialog.findViewById(R.id.iv_close).setOnClickListener(this);
 }

 @Override
 public void onClick(View v) {
 switch (v.getId()) {
 case R.id.iv_close:
 dismiss();
 break;
 }
 }

 /**
 * 设置输入回调
 *
 * @param inputCallBack
 */
 public void setPaySuccessCallBack(PayPassWordView.InputCallBack inputCallBack) {
 this.inputCallBack = inputCallBack;
 }

}

十一.逻辑代码中直接引用

public class MainActivity extends AppCompatActivity implements PayPassWordView.InputCallBack, View.OnClickListener {

 private PayFragment fragment;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 findViewById(R.id.btn_pay).setOnClickListener(this);
 }

 @Override
 public void onClick(View v) {
 switch (v.getId()) {
 case R.id.btn_pay:
 Bundle bundle = new Bundle();
 bundle.putString(PayFragment.EXTRA_CONTENT, "提现");
 bundle.putString(PayFragment.EXTRA_CONTENT2, "¥" + 1.00);
 bundle.putString(PayFragment.EXTRA_CONTENT3, "额外扣除0.1手续费");
 fragment = new PayFragment();//创建支付弹出框实例
 fragment.setArguments(bundle);//传递信息
 fragment.setPaySuccessCallBack(MainActivity.this);//设置回调
 fragment.show(getSupportFragmentManager(), "Pay");
 break;
 }
 }


 @Override
 public void onInputFinish(String result) {
 Toast.makeText(this, result, Toast.LENGTH_SHORT).show();
 fragment.dismiss();//窗口消失
 }
}

什么都没有,只有一个点击事件而已.

分享结束,这里面的代码可是有我造假的成分哦,不过,我就是喜欢将优秀的东西集成在一起,谢谢观看!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持创新互联。


名称栏目:Android自定义View实现微信支付密码输入框
标题URL:http://pwwzsj.com/article/gijicc.html