美文网首页程序员的职业规划Android开发知识小点
android 仿微信添加银行卡时输入支付密码

android 仿微信添加银行卡时输入支付密码

作者: yeyecan | 来源:发表于2019-05-08 14:19 被阅读1861次

    最近了解到了BottomSheetBehavior,感觉是个很有意思的布局,刚好项目中有实际场景可以应用,就拿它来实现了,下面是我们要实现的最终效果:

    gif.gif
    底部的键盘布局呢,就是采用的BottomSheetBehavior,我个人理解类似于抽屉的效果,可以从底部滑出划入,话不多说,开始吧。

    布局界面代码

    布局界面就是一个关闭按钮的图片,两个TextView和一个自定义的密码输入控件,下面贴上代码

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".activity.PasswordcheckActivity">
    
    
        <RelativeLayout
            android:background="@color/back"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <ImageView
                android:id="@+id/img_close"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:layout_marginTop="20dp"
                android:layout_marginLeft="20dp"
                android:src="@drawable/ic_close" />
    
            <TextView
                android:id="@+id/textView4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="@dimen/dp_120"
                android:textColor="@color/title_black"
                android:textSize="25sp"
                android:text="添加银行卡" />
    
            <TextView
                android:id="@+id/textView5"
                android:textColor="@color/title_black"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/textView4"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="@dimen/dp_20"
                android:text="请输入支付密码,以验证身份" />
    
            <com.xxx.xxx.PassEditView
                android:id="@+id/pass_edit"
                android:layout_width="256dp"
                android:layout_height="48dp"
                android:layout_below="@+id/textView5"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="60dp"
                android:padding="1dp" />
        </RelativeLayout>
        
        
        <LinearLayout
            android:background="@color/white"
            android:id="@+id/line_pass_bottom"
            app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_300">
            <LinearLayout
                android:id="@+id/Line_bom"
                android:gravity="center"
                android:layout_width="match_parent"
                android:layout_height="@dimen/dp_20">
            <ImageView
                android:layout_width="@dimen/dp_30"
                android:layout_height="@dimen/dp_20"
                android:src="@drawable/bottom"
                />
            </LinearLayout>
    
           <GridLayout
               android:columnCount="3"
               android:rowCount="4"
               android:layout_width="match_parent"
               android:layout_height="match_parent">
    
    
                <TextView
                    android:id="@+id/text_num_1"
                    android:layout_height="70dp"
                    android:layout_columnWeight="1"
                    android:gravity="center"
                    android:text="1"
                    android:textSize="25sp"
                    android:textColor="@color/black"
                    />
               <TextView
                   android:id="@+id/text_num_2"
                   android:layout_height="70dp"
                   android:layout_columnWeight="1"
                   android:gravity="center"
                   android:text="2"
                   android:textSize="25sp"
                   android:textColor="@color/black"
                   />
               <TextView
                   android:id="@+id/text_num_3"
                   android:layout_height="70dp"
                   android:layout_columnWeight="1"
                   android:gravity="center"
                   android:text="3"
                   android:textSize="25sp"
                   android:textColor="@color/black"
                   />
    
               <TextView
                   android:id="@+id/text_num_4"
                   android:layout_height="70dp"
                   android:layout_columnWeight="1"
                   android:gravity="center"
                   android:text="4"
                   android:textSize="25sp"
                   android:textColor="@color/black"
                   />
               <TextView
                   android:id="@+id/text_num_5"
                   android:layout_height="70dp"
                   android:layout_columnWeight="1"
                   android:gravity="center"
                   android:text="5"
                   android:textSize="25sp"
                   android:textColor="@color/black"
                   />
               <TextView
                   android:id="@+id/text_num_6"
                   android:layout_height="70dp"
                   android:layout_columnWeight="1"
                   android:gravity="center"
                   android:text="6"
                   android:textSize="25sp"
                   android:textColor="@color/black"
                   />
    
               <TextView
                   android:id="@+id/text_num_7"
                   android:layout_height="70dp"
                   android:layout_columnWeight="1"
                   android:gravity="center"
                   android:text="7"
                   android:textSize="25sp"
                   android:textColor="@color/black"
                   />
               <TextView
                   android:id="@+id/text_num_8"
                   android:layout_height="70dp"
                   android:layout_columnWeight="1"
                   android:gravity="center"
                   android:text="8"
                   android:textSize="25sp"
                   android:textColor="@color/black"
                   />
               <TextView
                   android:id="@+id/text_num_9"
                   android:layout_height="70dp"
                   android:layout_columnWeight="1"
                   android:gravity="center"
                   android:text="9"
                   android:textSize="25sp"
                   android:textColor="@color/black"
                   />
    
               <TextView
                   android:layout_height="70dp"
                   android:layout_columnWeight="1"
                   android:gravity="center"
                   android:text=""
                   android:textSize="25sp"
                   android:textColor="@color/black"
                   />
               <TextView
                   android:id="@+id/text_num_0"
                   android:layout_height="70dp"
                   android:layout_columnWeight="1"
                   android:gravity="center"
                   android:text="0"
                   android:textSize="25sp"
                   android:textColor="@color/black"
                   />
               <RelativeLayout
                   android:id="@+id/text_num_d"
                   android:layout_height="70dp"
                   android:layout_columnWeight="1"
                   >
                    <ImageView
                        android:layout_centerInParent="true"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:src="@drawable/ic_close"
                        />
               </RelativeLayout>
           </GridLayout>
        </LinearLayout>
    </android.support.design.widget.CoordinatorLayout>
    

    除了几个颜色资源和图片外,没有用到其他的资源文件,注意的是com.xxx.xxx.PassEditView这个自定义控件需要将代码复制到你项目下使用,替换成你的包名,而且BottomSheetBehavior布局的界面要加入以下一句:

     app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
    

    而且BottomSheetBehavior是可以设置初始高度等属性的,感兴趣的同学可以搜索百度BottomSheetBehavior
    下面是PassEditView这个密码输入框的代码:

    public class PassEditView extends View {
    
    
        private Paint mPaint;
        private InputFinishListener inputFinishListener;//输入完成监听
    
        private int inputNum=0;//当前输入的密码个数
        private int passwordNum=6;//密码个数
    
        private int boundWidth=2;//外层框线条粗细
        private int boundColor= R.color.view_blue;//外层框线条颜色
        private int boundRadius=0;//外框圆角半径
    
        private int deliverWidth=1;//分割线粗细
        private int deliverColor=Color.GRAY;//分割线条颜色
        private int deliverPadding=5;//分割线距离框的大小
    
        private int circleRadius =15;//密码圆点半径大小
        private int circleColor= Color.BLACK;//密码圆点颜色
    
        private StringBuilder currentPassword;//用户输入的密码
    
        public PassEditView(Context context) {
            super(context);
            init();
        }
    
        public PassEditView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
    
        @Override
            protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
    
        }
    
        private void init() {
            currentPassword=new StringBuilder();
            mPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        }
    
        private int dip2px(float dpValue) {
            final float scale = getContext().getResources().getDisplayMetrics().density;
            return (int) (dpValue * scale + 0.5f);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            int widthMode=MeasureSpec.getMode(widthMeasureSpec);
            int widthSize=MeasureSpec.getSize(widthMeasureSpec);
            int heightMode=MeasureSpec.getMode(heightMeasureSpec);
            int heightSize=MeasureSpec.getSize(heightMeasureSpec);
            int width,height;
            if (widthMode==MeasureSpec.AT_MOST){
                width=dip2px(36)*passwordNum;
            }else {
                width=widthSize;
            }
            if (heightMode==MeasureSpec.AT_MOST){
                height=dip2px(36);
            }else{
                height=heightSize;
            }
            setMeasuredDimension(width,height);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            int width = getWidth();
            int height = getHeight();
            float deliverSize=(width-getPaddingLeft()-getPaddingRight())/passwordNum;
            //1.画外框
            drawBound(canvas, width, height);
            //2.画分割线
            drawDeliver(canvas, height, deliverSize);
            //3.输入密码之后显示的图案
            drawCircle(canvas, height, deliverSize);
        }
    
        private void drawCircle(Canvas canvas, int height, float deliverSize) {
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setColor(circleColor);
            for (int i = 0; i < inputNum; i++) {
                canvas.drawCircle(deliverSize*i+getPaddingLeft()+deliverSize/2,(height-getPaddingTop()-getPaddingBottom())/2+getPaddingTop(), circleRadius,mPaint);
            }
        }
    
        private void drawDeliver(Canvas canvas, int height, float deliverSize) {
    
            mPaint.setStrokeWidth(deliverWidth);
            mPaint.setColor(deliverColor);
            Path path = new Path();
            for (int i = 1; i < passwordNum; i++) {
                path.reset();
                path.moveTo(deliverSize*i+getPaddingLeft(),0+deliverPadding+getPaddingTop());
                path.lineTo(deliverSize*i+getPaddingLeft(),height-deliverPadding-getPaddingBottom());
                canvas.drawPath(path,mPaint);
            }
        }
    
        private void drawBound(Canvas canvas, int width, int height) {
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(boundWidth);
            mPaint.setColor(getResources().getColor(boundColor));
            RectF rectF = new RectF(getPaddingLeft(),getPaddingTop(),width-getPaddingRight(),height-getPaddingBottom());
            canvas.drawRoundRect(rectF,boundRadius,boundRadius,mPaint);
        }
    
    
        public void inputPassword(Object pwd){
            if (inputNum<passwordNum) {
                currentPassword.append(pwd);
                inputNum++;
            }
            invalidate();
            if (inputNum==passwordNum){
                if (inputFinishListener!=null){
                    inputFinishListener.onFinish(getPassword());
                }
            }
        }
        //删除一个密码
        public void deletePassword(){
            if (currentPassword.length()>0) {
                currentPassword.deleteCharAt(currentPassword.length() - 1);
                inputNum--;
            }
            invalidate();
        }
        //清空输入的所有密码
        public void cleanInput(){
            inputNum=0;
            currentPassword.delete(0,currentPassword.length());
            invalidate();
        }
        //获取输入的所有密码
        public String getPassword(){
            return currentPassword.toString();
        }
    
        public void setInputFinishListener(InputFinishListener inputFinishListener) {
            this.inputFinishListener = inputFinishListener;
        }
    
        public interface InputFinishListener{
            void onFinish(String pwd);
        }
    }
    
    

    PassEditView这个自定义View并不是作者本人写的哦,网上有很多一样的轮子,就拿来用了,感谢作者的开源,其中包含有四个主要方法,输入密码-inputPassword,传入一个数字、删除一个密码-deletePassword()清空所有密码-cleanInput()、以及获取所有密码-getPassword(),值得注意的是,这个控件有输入完成的回调,实现这个回调就能直接获取到输入的密码。

    Java代码部分

    在java代码中我们要实现点击键盘数字,输入密码,点击输入框掉起数字键盘,点击返回键,收起键盘等等,总体来说功能并不难;这里代码中设置BottomSheetBehavior的初始状态:

    public class PasswordcheckActivity extends AppCompatActivity {
    
        BottomSheetBehavior bottomSheetBehavior;
        @BindView(R.id.pass_edit)
        PassEditView passEdit;
        @BindView(R.id.Line_bom)
        LinearLayout LineBom;
        @BindView(R.id.text_num_1)
        TextView textNum1;
        @BindView(R.id.text_num_2)
        TextView textNum2;
        @BindView(R.id.text_num_3)
        TextView textNum3;
        @BindView(R.id.text_num_4)
        TextView textNum4;
        @BindView(R.id.text_num_5)
        TextView textNum5;
        @BindView(R.id.text_num_6)
        TextView textNum6;
        @BindView(R.id.text_num_7)
        TextView textNum7;
        @BindView(R.id.text_num_8)
        TextView textNum8;
        @BindView(R.id.text_num_9)
        TextView textNum9;
        @BindView(R.id.text_num_0)
        TextView textNum0;
        @BindView(R.id.text_num_d)
        RelativeLayout textNumD;
        @BindView(R.id.img_close)
        ImageView imgClose;
        @BindView(R.id.line_pass_bottom)
        LinearLayout linePassBottom;
        boolean isshowPass = true;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_passwordcheck);
            ButterKnife.bind(this);
            init();
        }
    
        private void init() {
            bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.line_pass_bottom));
            bottomSheetBehavior.setSkipCollapsed(true);
            bottomSheetBehavior.setHideable(true);
            bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
            passEdit.setInputFinishListener(new PassEditView.InputFinishListener() {
                @Override
                public void onFinish(String pwd) {
                    Toast.makeText(PasswordcheckActivity.this, pwd, Toast.LENGTH_SHORT).show();
                }
            });
        }
    
        @OnClick({R.id.img_close,R.id.pass_edit, R.id.Line_bom, R.id.text_num_1, R.id.text_num_2, R.id.text_num_3, R.id.text_num_4, R.id.text_num_5, R.id.text_num_6, R.id.text_num_7, R.id.text_num_8, R.id.text_num_9, R.id.text_num_0, R.id.text_num_d})
        public void onViewClicked(View view) {
            switch (view.getId()) {
                case R.id.pass_edit:
                    isshowPass = true;
                    bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
                    break;
                case R.id.Line_bom:
                    isshowPass = false;
                    bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
                    break;
                case R.id.text_num_1:
                    passEdit.inputPassword(1);
                    break;
                case R.id.text_num_2:
                    passEdit.inputPassword(2);
                    break;
                case R.id.text_num_3:
                    passEdit.inputPassword(3);
                    break;
                case R.id.text_num_4:
                    passEdit.inputPassword(4);
                    break;
                case R.id.text_num_5:
                    passEdit.inputPassword(5);
                    break;
                case R.id.text_num_6:
                    passEdit.inputPassword(6);
                    break;
                case R.id.text_num_7:
                    passEdit.inputPassword(7);
                    break;
                case R.id.text_num_8:
                    passEdit.inputPassword(8);
                    break;
                case R.id.text_num_9:
                    passEdit.inputPassword(9);
                    break;
                case R.id.text_num_0:
                    passEdit.inputPassword(0);
                    break;
                case R.id.text_num_d:
                    passEdit.deletePassword();
                    break;
                case R.id.img_close:
                    finish();
                    break;
            }
        }
    
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                if(isshowPass){
                    isshowPass = false;
                    bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
                }else {
                    finish();
                }
                return false;
            }
            return super.onKeyDown(keyCode, event);
        }
    }
    
    

    以上呢,就完成了我们需要的效果,大致上与微信的输入密码页面差不多,关于BottomSheetBehavior的更多用法,大家有兴趣可以去搜索一下,在没了解之前做底部抽屉都是用弹窗的形式,BottomSheetBehavior很好的帮我们免去了写一个新页面的麻烦哦。

    相关文章

      网友评论

        本文标题:android 仿微信添加银行卡时输入支付密码

        本文链接:https://www.haomeiwen.com/subject/dqtcwqtx.html