创建自定义控件
控件和布局结构
要创建控件应当了解一下控件和布局的继承结构,一下是他们的继承结构:
可以看到,我们所用的所有控件都是直接或间接继承自 View的,所用的所有布局都是 直接或间接继承自 ViewGroup的。View是 Android中一种最基本的 UI组件,它可以在屏幕 上绘制一块矩形区域,并能响应这块区域的各种事件,因此,我们使用的各种控件其实就是 在 View的基础之上又添加了各自特有的功能。而 ViewGroup则是一种特殊的 View,它可以 包含很多的子 View和子 ViewGroup,是一个用于放置控件和布局的容器。
如果系统自带的控件并不能满足我们的需求时,可以利用上面的继承结构来创建自定义控件
一、引入布局
代码重用,当有些布局需要重复使用时
示例:创建一个标题栏控件
1. 第一步:创建自定义的布局:
<?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="wrap_content"
android:background="@drawable/title_bg">
<Button
android:id="@+id/title_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dip"
android:background="@drawable/back_bg"
android:text="Back"
android:textColor="#fff" />
<TextView android:id="@+id/title_text"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="center"
android:text="Title Text"
android:textColor="#fff"
android:textSize="24sp" />
<Button
android:id="@+id/title_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dip"
android:background="@drawable/edit_bg"
android:text="Edit"
</LinearLayout>
1.1 属性说明:
1.1.1 android:background="@drawable/title_bg"
用于为布局或控件指定一个背景,可以使用颜色或图片来进行填充。
1.1.2 android:layout_margin
这个属 性,它可以指定控件在上下左右方向上偏移的距离。——当然也可以使用android:layout_marginLeft
或 android:layout_marginTop
等属性来单独指定控件在某个方向上偏移的距离。
1.1.3 注意事项:
作为引入布局,自身的属性应当在当前布局中确定,例如layout_width和layout_height确定当该自定义控件被引用时的宽高。
2. 第二步:引用该布局文件
2.1 引用布局文件,使用include标签,如下所示:
<?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="horizontal" >
<include layout="@layout/mylayout" />
</LinearLayout>
注意:在 MainActivity中将系统自带的标题栏隐藏掉
2.2 效果:
二、创建自定义控件
前面讲述的是创建布局和引用布局,但是如果布局中有一些控件要求 能够响应事件,我们还是需要在每个活动中为这些控件单独编写一次事件注册的代码。如果在每一个活动中都需要重新注册一遍返回按钮的点击事件,无疑又是增 加了很多重复代码,这种情况最好是使用自定义控件的方式来解决。
1. 第一步:新建TitleLayout继承自LinearLayout,让它成为我们自定义的标题控件
package com.example.mylayout;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.LinearLayout;
public class TitleLayout extends LinearLayout {
public TitleLayout(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.mylayout, this); //与布局相关联
}
}
1.1 代码说明:
首先我们重写了 LinearLayout中的带有两个参数的构造函数,在布局中引入 MyLayout 控件就会调用这个构造函数。然后在构造函数中需要对标题栏布局进行动态加载,这就要借 助 LayoutInflater来实现了。
通过 LayoutInflater的 from()方法可以构建出一个 LayoutInflater 对象,然后调用 inflate()方法就可以动态加载一个布局文件,inflate()方法接收两个参数,第 一个参数是要加载的布局文件的 id,这里我们传入 R.layout.title,第二个参数是给加载好的 布局再添加一个父布局,这里我们想要指定为 TitleLayout,于是直接传入 this。