美文网首页UI功能专区Android开发经验谈
Android-来填写一个验证码吧!(一)

Android-来填写一个验证码吧!(一)

作者: Sakura_echo | 来源:发表于2018-01-26 18:44 被阅读1226次
    android
    熟悉web开发中童鞋们都知道为了防止恶意破解、恶意提交等行为,所以我们在提交表单数据时,都会使用随机验证码功能。在Android应用中我们同样需要这一功能,去有效的避开恶意注册,恶意攻击。那么该如何实现呢?

    这里介绍一种,数字英文随机生成的图片验证码,使用很简单,一行代码,调用一个工具类,就能完美的实现图片验证的显示了。

    效果如下:

    请输入图片验证码

    具体思路如下:
    在一块固定宽高的画布上,画上固定个数的随机数字和字母,再画上固定条数的干扰线
    随机数和干扰线的颜色随机生成,随机数的样式随机生成。

    理清思路,接下来看下代码吧!

    public class CodeUtils {
    
        //随机码集
        private static final char[] CHARS = {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
                'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
                'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
                'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
        };
    
        private static CodeUtils mCodeUtils;
        private int mPaddingLeft, mPaddingTop;
        private StringBuilder mBuilder = new StringBuilder();
        private Random mRandom = new Random();
    
        //Default Settings
        private static final int DEFAULT_CODE_LENGTH = 4;//验证码的长度  这里是4位
        private static final int DEFAULT_FONT_SIZE = 60;//字体大小
        private static final int DEFAULT_LINE_NUMBER = 3;//多少条干扰线
        private static final int BASE_PADDING_LEFT = 20; //左边距
        private static final int RANGE_PADDING_LEFT = 30;//左边距范围值
        private static final int BASE_PADDING_TOP = 70;//上边距
        private static final int RANGE_PADDING_TOP = 15;//上边距范围值
        private static final int DEFAULT_WIDTH = 200;//默认宽度.图片的总宽
        private static final int DEFAULT_HEIGHT = 100;//默认高度.图片的总高
        private static final int DEFAULT_COLOR = Color.rgb(0xee, 0xee, 0xee);//默认背景颜色值
    
        private String code;
    
        public static CodeUtils getInstance() {
            if (mCodeUtils == null) {
                mCodeUtils = new CodeUtils();
            }
            return mCodeUtils;
        }
    
        //生成验证码图片
        public Bitmap createBitmap() {
            mPaddingLeft = 0; //每次生成验证码图片时初始化
            mPaddingTop = 0;
    
            Bitmap bitmap = Bitmap.createBitmap(DEFAULT_WIDTH, DEFAULT_HEIGHT, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            code = createCode();
            canvas.drawARGB(0, 0, 0, 0);
            canvas.drawColor(DEFAULT_COLOR);
            Paint paint = new Paint();
            paint.setTextSize(DEFAULT_FONT_SIZE);
    
            for (int i = 0; i < code.length(); i++) {
                randomTextStyle(paint);
                randomPadding();
                canvas.drawText(code.charAt(i) + "", mPaddingLeft, mPaddingTop, paint);
            }
    
            //干扰线
            for (int i = 0; i < DEFAULT_LINE_NUMBER; i++) {
                drawLine(canvas, paint);
            }
    
            canvas.save(Canvas.ALL_SAVE_FLAG);//保存
            canvas.restore();
            return bitmap;
        }
    
        /**
         * 得到图片中的验证码字符串
         *
         * @return
         */
        public String getCode() {
            return code;
        }
    
        //生成验证码
        public String createCode() {
            mBuilder.delete(0, mBuilder.length()); //使用之前首先清空内容
            for (int i = 0; i < DEFAULT_CODE_LENGTH; i++) {
                mBuilder.append(CHARS[mRandom.nextInt(CHARS.length)]);
            }
            return mBuilder.toString();
        }
    
        //生成干扰线
        private void drawLine(Canvas canvas, Paint paint) {
            int color = randomColor();
            int startX = mRandom.nextInt(DEFAULT_WIDTH);
            int startY = mRandom.nextInt(DEFAULT_HEIGHT);
            int stopX = mRandom.nextInt(DEFAULT_WIDTH);
            int stopY = mRandom.nextInt(DEFAULT_HEIGHT);
            paint.setStrokeWidth(1);
            paint.setColor(color);
            canvas.drawLine(startX, startY, stopX, stopY, paint);
        }
    
        //随机颜色
        private int randomColor() {
            mBuilder.delete(0, mBuilder.length()); //使用之前首先清空内容
            String haxString;
            for (int i = 0; i < 3; i++) {
                haxString = Integer.toHexString(mRandom.nextInt(0xEE));
                if (haxString.length() == 1) {
                    haxString = "0" + haxString;
                }
                mBuilder.append(haxString);
            }
            return Color.parseColor("#" + mBuilder.toString());
        }
    
        //随机文本样式
        private void randomTextStyle(Paint paint) {
            int color = randomColor();
            paint.setColor(color);
            paint.setFakeBoldText(mRandom.nextBoolean());  //true为粗体,false为非粗体
            float skewX = mRandom.nextInt(11) / 10;
            skewX = mRandom.nextBoolean() ? skewX : -skewX;
            paint.setTextSkewX(skewX); //float类型参数,负数表示右斜,整数左斜
            paint.setUnderlineText(mRandom.nextBoolean()); //true为下划线,false为非下划线
            paint.setStrikeThruText(mRandom.nextBoolean()); //true为删除线,false为非删除线
        }
    
        //随机间距
        private void randomPadding() {
            mPaddingLeft += BASE_PADDING_LEFT + mRandom.nextInt(RANGE_PADDING_LEFT);
            mPaddingTop = BASE_PADDING_TOP + mRandom.nextInt(RANGE_PADDING_TOP);
        }
    }
    
    

    至此,我们的工具类就完成了,是不是很简单,那么怎么使用呢?

    也很简单,我们可以看到通过CodeUtils.getInstance().createBitmap();方法,就可以获取生成的由工具类生成的图片验证码的bitmap,那么我们只需要将这个bitmap,设置到需要展示图片验证码的ImageView上即可。

    以下是完整代码:

    布局界面:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="@android:color/holo_red_light">
    
            <TextView
                android:id="@+id/tv_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:text="设置登录密码"
                android:textColor="#fff"
                android:textSize="20sp" />
        </RelativeLayout>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="45dp"
            android:layout_marginLeft="15dp"
            android:layout_marginRight="15dp"
            android:layout_marginTop="30dp"
            android:background="@drawable/bg"
            android:orientation="vertical">
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center_vertical"
                android:orientation="horizontal">
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="20dp"
                    android:layout_marginRight="20dp"
                    android:text="中国+86"
                    android:textColor="#A2CD5A"
                    android:textSize="16sp" />
    
                <View
                    android:layout_width="0.1dp"
                    android:layout_height="match_parent"
                    android:background="#FF7F00" />
    
                <EditText
                    android:id="@+id/et_forgetPass_PhoneNum"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="20dp"
                    android:background="@null"
                    android:digits="0123456789"
                    android:hint="请填入您的手机号"
                    android:inputType="number"
                    android:maxLength="11"
                    android:textSize="16sp" />
            </LinearLayout>
        </LinearLayout>
    
    
        <LinearLayout
    
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="15dp"
            android:layout_marginRight="15dp"
            android:layout_marginTop="20dp"
            android:orientation="horizontal">
    
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="45dp"
                android:background="@drawable/bg">
                <EditText
                    android:id="@+id/et_phoneCodes"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_marginLeft="10dp"
                    android:layout_marginRight="10dp"
                    android:background="@null"
                    android:hint="请输入右侧验证码" />
            </LinearLayout>
    
            <ImageView
                android:id="@+id/image"
                android:layout_width="100dp"
                android:layout_height="match_parent"
                android:layout_marginLeft="10dp" />
    
        </LinearLayout>
    
        <Button
            android:id="@+id/but_forgetpass_toSetCodes"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="35dp"
            android:background="#ff5e00"
            android:text="获取验证码"
            android:textColor="#fff" />
    
    </LinearLayout>
    

    Activity界面:

    public class MainActivity extends AppCompatActivity {
    
        private Bitmap bitmap;
        private String code;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //获取需要展示图片验证码的ImageView
            final ImageView image = (ImageView) findViewById(R.id.image);
            //获取工具类生成的图片验证码对象
            bitmap = CodeUtils.getInstance().createBitmap();
            //获取当前图片验证码的对应内容用于校验
            code = CodeUtils.getInstance().getCode();
    
            image.setImageBitmap(bitmap);
            image.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    bitmap = CodeUtils.getInstance().createBitmap();
                    code = CodeUtils.getInstance().getCode();
                    image.setImageBitmap(bitmap);
                    Toast.makeText(MainActivity.this, code, Toast.LENGTH_SHORT).show();
                }
            });
    
        }
    }
    

    综上;我们就完成了一个常见的图片验证码工具的封装和使用

    当然一定还有更多方法和更优化的逻辑,还请大家提出,共同完善,
    有了需求才有了功能,有了想法才有了创作,你的反馈会是使我进步的最大动力。

    觉得还不够方便?还想要什么功能?告诉我!欢迎反馈,欢迎Star。

    我的其他文章推荐:
    Android-返回桌面?退出程序?
    一句话搞定高仿ios底部弹出提示框。
    一句话搞定的Android底部导航栏,一键绑定片段,ViewPager。

    相关文章

      网友评论

        本文标题:Android-来填写一个验证码吧!(一)

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