自定义View系列01
2018-12-29 本文已影响0人
Thor_果冻
@[toc]
自定义View系列01
简单理解
构造方法
/**
* new的时候调用
*/
constructor(context: Context) : this(context, null)
/**
* 在布局layout中使用(调用)
*/
constructor(context: Context, @Nullable attrs: AttributeSet?) : this(context, attrs, 0)
/**
* 在布局layout中使用,但是会有style(比如在布局中使用style=@style/xxx)
*/
constructor(context: Context, @Nullable attrs: AttributeSet?, defStyleAttr: Int): super(context, attrs, defStyleAttr)
onMeasure方法
/**
* 测量方法
* 布局的宽高都是在这里指定
*/
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
//获取宽高模式,wrap_content
val widthMode = MeasureSpec.getMode(widthMeasureSpec)//获取32位数中前2位
val heightMode = MeasureSpec.getMode(heightMeasureSpec)
val widthSize = MeasureSpec.getSize(widthMeasureSpec)//获取32位数中的后30位
val heightSize = MeasureSpec.getSize(heightMeasureSpec)
when (heightMode) {
MeasureSpec.AT_MOST -> {
//在布局中指定了wrap_content
}
MeasureSpec.EXACTLY -> {
//在布局中指定了确定的值match_parent,100dp
}
MeasureSpec.UNSPECIFIED -> {
//尽可能地大,这种很少用到,但是系统由用到如listView,ScrollView
/*
比如我们以前用的ScrollView嵌套ListView中显示不全问题,是因为ListView,ScrollView在测量子布局
的时候会用MeasureSpec.UNSPECIFIED这种模式,所以我们只要自定义其子布局重新定义其onMeasure方法就好了
比如现在的只要自定义ListView重写OnMeasure方法然后再其super上添加
heightMeasureSpec = MeasureSpec.makeMeasureSpec(Int.MAX_VALUE >> 2, MeasureSpec.AT_MOST)
heightMeasureSpec = MeasureSpec.makeMeasureSpec(Int.MAX_VALUE shr 2, MeasureSpec.AT_MOST)
为什么最大值右移2为:因为一个32位的数 前2位为模式,后30位为数值
*/
}
}
}
OnDraw方法
/**
* 绘制方法
*/
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
with(canvas){
//文本
//drawText()
//弧
//drawArc()
//圆
//drawCircle()
}
}
onTouchEvent
/**
* 处理事件分发
*/
@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent): Boolean {
when(event.action){
MotionEvent.ACTION_UP ->{
//抬起
}
MotionEvent.ACTION_MOVE ->{
//移动
}
MotionEvent.ACTION_DOWN ->{
//按下
}
}
return super.onTouchEvent(event)
}
自定义属性
在res中的values中创建一个attrs.xml文件,里面添加自定义属性
获取自定义属性
//获取自定义属性
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.xxx)//R.styleable.xxx自定义style名称
val id_str = typedArray.getString(R.styleable.id_xxx)//styel中id名称
//回收
typedArray.recycle()