赞
踩
自定义View一般有三种方式
这里我们就只看第一种,也是比较基础的。自定义View一般重写三个方法onMeasure
,onLayout
和onDraw
首先定义一个CustomizeView
,看看怎么调用
class CustomizeView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : View(context, attrs, defStyleAttr) { init { } override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { super.onLayout(changed, left, top, right, bottom) XLogUtils.d("onLayout") } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) XLogUtils.d("onMeasure") } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) XLogUtils.d("onDraw") } }
Activity和XML代码很简单
<?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"> <FrameLayout android:layout_width="300dp" android:layout_height="300dp" android:background="@android:color/holo_blue_light"> <com.example.cb.test.ui.custom_view.CustomizeView android:layout_width="100dp" android:background="@android:color/holo_red_light" android:layout_height="100dp" /> </FrameLayout> </LinearLayout> class CustomViewActivity : BaseActivity() { override fun getLayoutId()= R.layout.activity_custom_view override fun initUI() {} override fun initEvent() {} }
运行之后可以看到
onMeasure
执行了两次,onLayout
和onDraw
各执行一次;onMeasure
不一定全是执行两次,这里不讨论这个了,有兴趣的可以去搜下。
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {}
widthMeasureSpec宽的测量模式,heightMeasureSpec高度测量模式,测量模式??什么东西?
我们看下google的解释
大概的意思是 父View对其的要求,也就是这里的参数是父View传来的MeasureSpec
,MeasureSpec
是一个32位的int值,高2位表示SpecMode
,低30位表示SpecSize
也就是测量的大小,先记着后面会讲,MeasureSpec
也提供的方法可以直接获取SpecMode
和SpecSize
/**
* Extracts the mode from the supplied measure specification.
*
* @param measureSpec the measure specification to extract the mode from
* @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
* {@link android.view.View.MeasureSpec#AT_MOST} or
* {@link android.view.View.MeasureSpec#EXACTLY}
*/
public static int getMode(int measureSpec) {
//noinspection ResourceType
return (measureSpec & MODE_MASK);
}
/**
* Extracts the size from the supplied measure specification.
*
* @param measureSpec the measure specification to extract the size from
* @return the size in pixels defined in the supplied measure specification
*/
public static int getSize(int measureSpec) {
return (measureSpec & ~MODE_MASK);
}
从getMode
可以看出来 测量模式一共有三种
下面代码演示两个,第一行第二个 和 第三行第一个
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) XLogUtils.d("onMeasure") val widthMode = MeasureSpec.getMode(widthMeasureSpec) val heightMode = MeasureSpec.getMode(heightMeasureSpec) val widthSize = MeasureSpec.getSize(widthMeasureSpec) val heightSize = MeasureSpec.getSize(heightMeasureSpec) when (widthMode) { MeasureSpec.AT_MOST -> XLogUtils.i("MeasureSpec.AT_MOST") MeasureSpec.UNSPECIFIED -> XLogUtils.i("MeasureSpec.UNSPECIFIED") MeasureSpec.EXACTLY -> XLogUtils.i("MeasureSpec.EXACTLY") else -> XLogUtils.i("") } }
都和上面的图对上了,小伙伴们可以自己去试试,这么说还不明显 我用一张图来表示,
两张图一对照就明白了了。加入我们要自定义一个宽高相等的view利用上面所讲的内容代码如下
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) val widthMode = MeasureSpec.getMode(widthMeasureSpec) val heightMode = MeasureSpec.getMode(heightMeasureSpec) val widthSize = MeasureSpec.getSize(widthMeasureSpec) val heightSize = MeasureSpec.getSize(heightMeasureSpec) val screenWidth = 500//假设屏幕宽度 var width = when (widthMode) { MeasureSpec.AT_MOST -> min(screenWidth, widthSize) MeasureSpec.UNSPECIFIED -> screenWidth MeasureSpec.EXACTLY -> widthSize else -> widthSize //不写要报错 } //存储测量测的值 setMeasuredDimension(width, width) }
基本上onMeasure
差不多就上面的这些东西,具体还要看业务中的需求。
只会执行一次,用来决定子View的位置
@Override
public boolean onTouchEvent(MotionEvent ev) {
return super.onTouchEvent(ev);
}
int action = ev.getAction(); 常用的有下面几种
还有需要注意的一点就是
ev.getX()和ev.getRawX()区别
前者是获取在相对父View的x轴位置,后者是获取相对屏幕的x轴位置
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。