闲来无事,撸了一个自定义view随机数,也算是学习啦
class TestView : View {
constructor(context: Context) : super(context) {
init(context, null);
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
init(context, attrs);
}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
init(context, attrs);
}
private var textSize: Int = 0;
private var textTest: String = "";
private var textColor: Int = 0;
private var mPain: Paint? = null;
private var mBound: Rect? = null;
private fun init(context: Context, attrs: AttributeSet?) {
//获取控件中包含的属性
val typeArray = context.obtainStyledAttributes(attrs, R.styleable.text_view);
//分别获取设置的值
val indexCount = typeArray.indexCount
(0..indexCount).map { typeArray.getIndex(it) }.forEach {
when (it) {
R.styleable.text_view_titleTextSize -> {
textSize = typeArray.getDimensionPixelSize(it, 16)
}
R.styleable.text_view_titleText -> {
textTest = typeArray.getString(it);
}
R.styleable.text_view_titleColor -> {
textColor = typeArray.getColor(it, Color.BLACK);
}
}
}
typeArray.recycle(); //此方法即使回收获取属性,避免内存泄漏
mPain = Paint();
mPain!!.textSize = textSize.toFloat();
mBound = Rect();
mPain!!.getTextBounds(textTest, 0, textTest.length, mBound);
//设置控件点击事件
setOnClickListener {
textTest = randomText();
postInvalidate(); //重新绘制该方法调用后只会调用onDraw方法
}
}
/**
* 处理布局文件中设置wrap_content时view满屏问题
* 系统默认测量宽高为match_parent
* MeasureSpec分为三种模式:
* EXACTLY设置确切的值或Match_parent
* AT_MOST布局限制在最大的值wrap_content
* UNSPECIFIED 布局想要多大可以多大,一般为源码所用
*/
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
var width: Int;
var height: Int;
val widthMode = MeasureSpec.getMode(widthMeasureSpec);
val widthSize = MeasureSpec.getSize(widthMeasureSpec);
val heightMode = MeasureSpec.getMode(heightMeasureSpec);
val heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else {
mPain!!.textSize = textSize.toFloat();
mPain!!.getTextBounds(textTest, 0, textTest.length, mBound);
val textWidth = mBound!!.width();
width = paddingLeft + textWidth + paddingRight;
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {
mPain!!.textSize = textSize.toFloat();
mPain!!.getTextBounds(textTest, 0, textTest.length, mBound);
val textHeight = mBound!!.height();
height = paddingBottom + paddingTop + textHeight;
}
setMeasuredDimension(width, height); //设置最终测量宽高
}
/**
* 绘制界面方法
* 尽量不要在view中做耗时操作
*/
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
mPain!!.color = Color.YELLOW //绘制背景
canvas.drawRect(0f, 0f, measuredWidth.toFloat(), measuredHeight.toFloat(), mPain);
mPain!!.color = Color.GREEN //绘制文字
canvas.drawText(textTest, (width / 2 - mBound!!.width() / 2).toFloat(), (height / 2 + mBound!!.height()/2).toFloat(), mPain)
}
private fun randomText(): String {
val random = Random();
var set = HashSet();
while (set.size < 4){
val randomInt = random.nextInt(10);
set.add(randomInt)
}
val sb= StringBuffer();
for (item in set){
sb.append(""+item)
}
return sb.toString();
}
}