自定义View
来源:互联网 发布:淘客优惠券网站源码 编辑:程序博客网 时间:2024/06/03 16:08
前言
自定义View是Android开发者必须了解的基础
今天,我将手把手教你写一个自定义View,并理清自定义View所有应该的注意点
阅读本文前,请先阅读我写的一系列自定义View文章
自定义View基础 - 最易懂的自定义View原理系列(1)
自定义View Measure过程 - 最易懂的自定义View原理系列(2)
自定义View Layout过程 - 最易懂的自定义View原理系列(3)
自定义View Draw过程- 最易懂的自定义View原理系列(4)
目录
目录
- 自定义View的分类
自定义View一共分为两大类,具体如下图:
分类
- 具体介绍 & 使用场景
对于自定义View的类型介绍及使用场景如下图:
具体介绍 & 使用场景
- 使用注意点
在使用自定义View时有很多注意点(坑),希望大家要非常留意:
使用注意点
3.1 支持特殊属性
支持wrap_content
如果不在onMeasure()中对wrap_content作特殊处理,那么wrap_content属性将失效
具体原因请看文章:为什么你的自定义View wrap_content不起作用?
支持padding & margin
如果不支持,那么padding和margin(ViewGroup情况)的属性将失效
对于继承View的控件,padding是在draw()中处理
对于继承ViewGroup的控件,padding和margin会直接影响measure和layout过程
3.2 多线程应直接使用post方式
View的内部本身提供了post系列的方法,完全可以替代Handler的作用,使用起来更加方便、直接。
3.3 避免内存泄露
主要针对View中含有线程或动画的情况:当View退出或不可见时,记得及时停止该View包含的线程和动画,否则会造成内存泄露问题。
启动或停止线程/ 动画的方式:
1. 启动线程/ 动画:使用view.onAttachedToWindow(),因为该方法调用的时机是当包含View的Activity启动的时刻
2. 停止线程/ 动画:使用view.onDetachedFromWindow(),因为该方法调用的时机是当包含View的Activity退出或当前View被remove的时刻
3.4 处理好滑动冲突
当View带有滑动嵌套情况时,必须要处理好滑动冲突,否则会严重影响View的显示效果。
- 具体实例
接下来,我将用自定义View中最常用的继承View来说明自定义View的具体应用和需要注意的点
4.1 继承VIew的介绍
Paste_Image.png
在下面的例子中,我将讲解:
如何实现一个基本的自定义View(继承VIew)
如何自身支持wrap_content & padding属性
如何为自定义View提供自定义属性(如颜色等等)
实例说明:画一个实心圆
4.2 具体步骤
创建自定义View类(继承View类)
布局文件添加自定义View组件
注意点设置(支持wrap_content & padding属性自定义属性等等)
下面我将逐个步骤进行说明:
步骤1:创建自定义View类(继承View类)
CircleView.java
// 用于绘制自定义View的具体内容
// 具体绘制是在复写的onDraw()内实现
public class CircleView extends View {
// 设置画笔变量Paint mPaint1;// 自定义View有四个构造函数// 如果View是在Java代码里面new的,则调用第一个构造函数public CircleView(Context context){ super(context); // 在构造函数里初始化画笔的操作 init();}
// 如果View是在.xml里声明的,则调用第二个构造函数
// 自定义属性是从AttributeSet参数传进来的
public CircleView(Context context,AttributeSet attrs){
super(context, attrs);
init();
}
// 不会自动调用
// 一般是在第二个构造函数里主动调用
// 如View有style属性时
public CircleView(Context context,AttributeSet attrs,int defStyleAttr ){
super(context, attrs,defStyleAttr);
init();
}
//API21之后才使用// 不会自动调用// 一般是在第二个构造函数里主动调用// 如View有style属性时public CircleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes);}// 画笔初始化private void init() { // 创建画笔 mPaint1 = new Paint (); // 设置画笔颜色为蓝色 mPaint1.setColor(Color.BLUE); // 设置画笔宽度为10px mPaint1.setStrokeWidth(5f); //设置画笔模式为填充 mPaint1.setStyle(Paint.Style.FILL);}// 复写onDraw()进行绘制 @Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); // 获取控件的高度和宽度 int width = getWidth(); int height = getHeight(); // 设置圆的半径 = 宽,高最小值的2分之1 int r = Math.min(width, height)/2; // 画出圆(蓝色) // 圆心 = 控件的中央,半径 = 宽,高最小值的2分之1 canvas.drawCircle(width/2,height/2,r,mPaint1);}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
特别注意:
1. View的构造函数一共有4个,具体使用请看:深入理解View的构造函数和
理解View的构造函数
2. 对于绘制内容为何在复写onDraw()里实现,具体请看我写的文章:自定义View Draw过程- 最易懂的自定义View原理系列(4)
步骤2:在布局文件中添加自定义View类的组件
activity_main.xml
- 自定义view
- 自定义View
- 自定义view
- 自定义View
- 自定义View
- 自定义view
- 自定义View
- 自定义view
- 自定义view
- 自定义View
- 自定义View
- 自定义view
- 自定义view
- 自定义view
- 自定义view
- 自定义view
- 自定义View
- 自定义View
- tomcat建立连接
- 111. Minimum & Maximum Depth of Binary Tree
- RocketMQ在windows上安装和开发使用
- 如何判断是否是原生js函数
- angular-cli 常见用法
- 自定义View
- Android,Android介绍。
- Spring入门(Bean装配,@Qualifier)
- 松柏先生:电商的这六道死穴不解开,就等死吧!
- Ubuntu环境下访问phpmyadmin提示The mbstring extension is missing. Please check your PHP configura
- C/C++常量与变量的使用
- Bootstrap 多弹窗(模态闯),第二层覆盖前一层解决办法
- 10.leetCode419: Battleships in a Board
- 卡特兰数