前言
对Android开发者而言,学习到一定时候,就会发现Android自带的控件诸如TextView,Button,ImageView,配合上布局如LinearLayout, RelativeLayout,TableLayout,FrameLayout等,做不出自己想要的效果。这个时候就要用到自定义控件。
- 自定义空间的有点有很多,包括:
- 用户交互体验的优化;
- 在大数据量情况下自定义控件比写布局效率高
- 布局上更加符合需求;
- 能配合App整体UI风格的设计;
- 等等
现在网上有许多开源的自定义控件共享,供开发者使用。而我们在实际情况中也会遇到需要自定义控件的时候,今天我们就来一起学习如何自定义控件。
(PS:本文内容基于官方教程进行学习解析,若想查看原文请点击阅读。
参考博客:guolin博文&博文,大家可以看看,受益匪浅)
View
View是我们平时所见到的所有视图的父类,每个布局,控件,都是直接或者间接继承自View。一个View在屏幕上显示出来要涉及到三个函数measure(),layout()和draw()。
它们的作用分别是:
- measure()测量视图布局大小
- layout()设置视图在屏幕中的位置
- draw()将视图显示在屏幕上
Measure:
- 调用measure()测量
- measure()中调用onMeasure(),onMeasure()是实际测量视图大小的函数
- onMeasure()中调用setMeasureDimension()保存测量结果;
Layout:
- layout调用setFrame(l,t,r,b),l,t,r,b即left, top, right, bottom,是与父View的距离。setFrame()会判断这个视图大小有没有改变来决定是否重绘。然后调用onLayout()
- onLayout()是个空方法由子类去实现,如TextView继承自View里面就对这个方法进行了重写。
- 特别一提,onLayout()在ViewGroup中是个抽象方法,没有进行实现。意思是在如果你创建了一个View继承自ViewGroup,则必须重写onLayout()方法。
Draw:
- draw会在一个canvas对象上进行绘制,然后显示在屏幕上
- 和上面两个类似,draw()中也有实际上负责绘制逻辑的函数onDraw(),诸如TextView,ImageView中有自己重写的onDraw()函数。
- onDraw()通过对传入的canvas对象进行逻辑处理,得到所要显示的样子。
自定义控件
知道了View的绘制流程之后,我们开始学习怎么去自定义一个控件。
- 自定义控件按照对View及其子类的依赖程度,可以分为:
- 组合型控件。利用现有控件的组合实现更加复杂的布局。
- 继承型控件。继承现有的View或者View的子类,如TextView,ImageView等,并在此基础上增加一点内容。
- 自创型控件。利用上面说的View绘制原理,自行设计绘制出来的全部内容并加以实现。
组合型控件:
先是在layout中创建一个布局文件,如例子中是一个Button和一个TextView,view_layout.xml,实现类似标题栏的效果:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#ff0000" >
<Button
android:background="#00ff00"
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:textSize="18sp"
android:text="Button"
android:textColor="#0000ff" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="TextView"
android:textColor="#0000ff"
android:textSize="22sp" />
</RelativeLayout>
然后是控件对应的类,在里面实现逻辑处理,CombView.java:
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.example.wujiayi.testapplication.R;