Android -- 自定义View小Demo,绘制四位数随机码(一)
1,现在有这样一个需求,实现显示随机随机数可能在代码中直接很简单的就实现了,但是现在我们直接自定义View来实现这个效果,那么我们来分析一波吧,我们允许开发者自己设置这个textview的大小,颜色,和初始四位随机数的文字,那么我们需要提供自定义属性,好吧,首先把自定义属性的简单使用介绍一下吧:
首先在res/values文件夹下建利attrs.xml文件,由于这次我们功能决定我们要提供三个自定义属性,分别是textTitle String类型的,textColor是color类型的,textSize是dimetion类型,代码如下:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="MyTextView"> <attr name="titleText" format="string"/> <attr name="titleTextColor" format="color"/> <attr name="titleTextSize" format="dimension"/> </declare-styleable> </resources>
再来看看我们怎么在布局文件中的自定义控件中去使用我们自定义的属性
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res/com.qianmo.VerificationCode" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <com.qianmo.VerificationCode.view.MyTextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="100dp" custom:titleText="3712" custom:titleTextColor="#ff0000" android:layout_centerInParent="true" custom:titleTextSize="40sp"/> </RelativeLayout>
关键的两句代码 :
xmlns:custom="http://schemas.android.com/apk/res/com.qianmo.VerificationCode" 添加自定义的空间名,com.qianmo.VerificationCode使我们的包名,使用是以custom:开头 ,例如:custom:titleTextSize
现在自定义的属性搞定了,开始我们的自定义View吧,首先选择,我们继承的是View还是ViewGroup,很明显,这次我们是一个简单的View,所以选择继承View,下面直接贴出来代码了,每一步代码里面都很详细,就不多给大家解释了
package com.qianmo.VerificationCode.view; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.view.View; import com.qianmo.VerificationCode.R; import java.util.HashSet; import java.util.Random; import java.util.Set; /** * Created by wangjitao on 2016/10/13 0013. * 用于实现获取随机码 */ public class MyTextView extends View { /** * 由于是自定义的View,首先我们要确定那些属性是用户可以自己定义的 * 1,View里面显示的字 * 2,显示字的大小 * 3,显示字的颜色 */ private String mTitleText; private int mTitleTextColor; private int mTitleTextSize; /** * 画笔 */ private Paint mPaint; /** * view的矩形背景 */ private Rect mBound; public MyTextView(Context context) { this(context, null); } public MyTextView(Context context, AttributeSet attrs) { this(context, attrs, 0); } /** * 获得自定义的属性 * * @param context * @param attrs * @param defStyleAttr */ public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); /** * 获得我们自定义的一些属性 */ TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyTextView, defStyleAttr, 0); mTitleText = randomText(); //初始化显示的数字 for (int i = 0; i < a.getIndexCount(); i++) { int attr = a.getIndex(i); switch (attr) { case R.styleable.MyTextView_titleText: mTitleText = a.getString(attr); break; case R.styleable.MyTextView_titleTextColor: mTitleTextColor = a.getColor(attr, Color.BLACK); break; case R.styleable.MyTextView_titleTextSize: //设置默认大小为16 mTitleTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics())); break; } } //将TypedArray对象回收 a.recycle(); /** * 初始化画笔 */ mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setTextSize(mTitleTextSize); mPaint.setColor(mTitleTextColor); mBound = new Rect(); mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound); /** * 模仿点击换验证码 */ this.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { mTitleText = randomText(); postInvalidate(); } }); } /** * 获取四位随机数验证码 * * @return */ private String randomText() { Random random = new Random(); Set<Integer> set = new HashSet<Integer>(); while (set.size() < 4) { int randomInt = random.nextInt(10); set.add(randomInt); } StringBuffer sb = new StringBuffer(); for (Integer i : set) { sb.append("" + i); } return sb.toString(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { /** * 处理当宽高都是wrap_content的情况 */ int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int width = 0; int height = 0; if (widthMode == MeasureSpec.EXACTLY) { width = widthSize; } else { mPaint.setTextSize(mTitleTextSize); mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound); float textWidth = mBound.width(); int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight()); width = desired; } if (heightMode == MeasureSpec.EXACTLY) { height = heightSize; } else { mPaint.setTextSize(mTitleTextSize); mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound); float textWidth = mBound.height(); int desired = (int) (getPaddingTop() + textWidth + getPaddingBottom()); height = desired; } setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { /** * 绘制文字和矩形 */ mPaint.setColor(Color.YELLOW); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint); mPaint.setColor(mTitleTextColor); canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint); } }
ok,最后看一下我们的效果图