移动端日薄西山每况愈下
呸 。移动开发日渐成熟 同时也淘汰大量初级程序员
自定义view以前作为有些水平的必备技能 。
也被越来越多工作年限低的掌握
在学校时看自定义view一知半解 这段时间又看了看突然豁然开朗
一个自定义view写出来超级多 其实必备的骨骼就几个 (一个自定义view中大部分是逻辑计算)
这篇文章目的是用最简单的语言解释下自定义view的流程和常用类
让小白吃饭的时候知道吃的可能是什么,可能怎么烹饪的(说真的自定义view内容真不少)
需要什么在去百度搜索 (百度超级多)
通常最基本的自定义view会有以下几点
零:
自定义属性(成熟的自定义view都会有这一步)
在res/values目录下创建attrs.xml文件
<resources>
<declare-styleable name="MyView">
<attr name="a" format="string" />
<attr name="b format="string" />
<attr name="c" format="string" />
<attr name="d" format="string" />
</declare-styleable>
</resources
要注意的是<declare-styleable>标签的name是自定义View的名称
<attr >标签一行代表一个自定义属性
format是该属性应该的数值类型 常用的有integer string color:颜色值 dimension:尺寸值 reference:参考某一资源ID等
而使用方式在对应xml添加引用空间(通常在根标签上输入 “app” studio自动联想选择第二个 “adds application namespace”)
xmlns:app="http://schemas.android.com/apk/res-auto"
(当然“app”可以随便换)
然后在自己的自定义view标签下 app:a = "" (系统的是android:id="")
至于要在自定义view的java构造函数中查找创建自定义属性等下再提
一:
继承View (正式开始自定义view)
继承View 或系统的textView那些View
通常自己写都是继承VIew
如:public class MyView extends View{
}
二:
构造函数
创建了MyView这个java文件并继承View之后就会提示重写构造函数
构造函数当然常用与初始化一些必要参数啦
其中有4个构造函数 其中前两个构造函数最常使用
1)只有一个context参数 貌似使用情况也比较少
被调用是在代码中new MyView(context)时调用
public MyView (Context context) {
super(context);
}
2)两个参数 这种是在xml中引用MyView时被调用
其中AttributeSet是res/values目录下创建attrs.xml文件的自定义属性的返回集合
public MyView (Context context, AttributeSet attrs) {
super(context,attrs);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyView);
String a = ta.getString(R.styleable.MyView_a);
String b = ta.getString(R.styleable.MyView_b);
ta.recycle();
}
对TypedArray有兴趣可以百度我就说下用法
string a和b 的值是xml中设置的自定义属性值
3)三个参数 多了一个int defStyleAttr 作用是接受一个style资源
但也比较少用就不说了 4个参数普通情况用处更少
三:
onMeasure(int widthMeasureSpec, int heightMeasureSpec) 决定View的大小(也是一个完善的自定义view要具备的,我自己写练习都不重写这个方法 手动滑稽)
onMeasure()是view的大小赋值函数 当一个MyView所在界面要被绘制在屏幕上
MyView的父容器会调用measure()去通知子View测量自己需要大小
这时候自定义MyView就会通过onMeasure()设置要显示的大小(反正说的不是viewgroup 现在知道onmeasure能控制自定义view大小)
两个参数包含了长宽对应的一些数据(总共32位 知道下就行)
高2位能通过getMode得到模式(就是xml里宽高设置match_parent还是wrap_content还是具体数值)
后30位能通过getSize得到自动测量的期望数值
具体代码如下
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 父容器传过来的宽度方向上的模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
// 父容器传过来的高度方向上的模式
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
// 父容器传过来的宽度的值
int width = MeasureSpec.getSize(widthMeasureSpec);
// 父容器传过来的高度的值
int height = MeasureSpec.getSize(heightMeasureSpec);
switch (widthMode){
case MeasureSpec.EXACTLY:
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.UNSPECIFIED:
break;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
由上面看出我先得到长宽模式widthMode和heightMode
接着得到期望大小长宽width和height
然后以widthmode举例3种模式
MeasureSpec.EXACTLY用在具体数值时 如xml设置match_parent或具体数值
MeasureSpec.AT_MOST用在xml设置wrap_content。通常逻辑里让他使用期望数值
MeasureSpec.UNSPECIFIED 不常用 一般和AT_MOST放一起
当然这是最普通的情况 具体情况具体分析 有时还要考虑padding和margin(加加减减什么的)
个人觉得onMeasure能在自定义view都能用以后在重写(真的只是简单说下onMeasure()要说清楚要说到绘制流程和源码)
四:
onDraw(Canvas canvas) 自定义view的绘制
重写这个方法后就能在对应位置绘制我们的自定义view
canvas 顾名思义是画布
他提供了
canvas.drawCircle();//画圆
canvas.drawText(); //写字
canvas.drawPoint(); //画点
canvas.drawPath(); //画路径
canvas.clipRect() //截取固定范围显示
等
这些方法中又共有一个Paint的参数 画笔(有画布当然有画笔)
画笔又能设置颜色,填充模式,画笔多粗(边框大小)
这里要还需要掌握
Rect和RectF 都是一个矩形范围 画圆和矩形 裁剪等会用到
Path 一种坐标转化为预计图形提供给canvas等使用 内置moveTo() lineTo()等方法
等等
一般在这步就能得到一个不可交互的静态或动态(可以添加属性动画使view展示动画)自定义view
如果要使自定义view变的可交互就要重写ontouch() (触摸机制又是一大块其他内容)
五:
onTouchEvent(MotionEvent event)和GestureDetector
什么按下 移动 抬起就不说了 吧onDraw里的画图位置加上全局变量 然后在触摸监听对应改变(数值改变一堆逻辑)
再调用invalidate()或postInvalidate()重绘
六:
通篇整理 对一些属性提供set方法如在activity中setColor等
有的还要写几个接口给activity得到相应的响应
看完是不是不会的还是写不出自定义view 本来就不是教你怎么写只是说下
个人认为自定义view的流程 最近还写了几个例子练习 找时间结合起来介绍下
另外我记得鸿洋大神建议继续做android的要有自己研究不该注重界面展示效果
确实懂了之后自定义view这类花时间就能做出
但我这种彩笔能研究什么啊
看过一点openCV 视频流 都什么鬼 手动自抱自泣
研究搞不来 做程序这块就要多学点啊 手动自抱自泣