1.Android 控件和布局的继承结构
可以看到,我们所用的多有的控件都是直接或间接继承自View的,所有的布局都是直接或间接继承自
ViewGroup的.View是android中一种基本的UI组件,它可以在屏幕上绘制一块矩形区域,并能够响应这块区域的各种事件.
而ViewGroup是一种特殊的View,它可以包含很多的子View和子ViewGroup,是一个用于放置控件和布局的容器.
而当系统的控件不满足我们的需求的时候,我们就可以利用系统的控件来创建自定义的控件.
2.自定义控件的使用方式
2.1 引入布局
如果我们的应用程序很多的界面都显示一个固定的标题栏,这个时候我们可以自定义一个xml文件,把那个需要的
标题栏写在这个xml文件中,在我们需要的地方引入即可.
title.xml (两个按钮,一个返回,一个编辑,中间是编辑文本的edittext)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#333333"
android:orientation="horizontal"
tools:context="com.example.my03_mycomponent.MainActivity"
tools:ignore="HardcodedText" >
<Button
android:id="@+id/btn_title_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dp"
android:background="#22ff11"
android:text="Back"
android:textColor="#1100ff"
/>
<TextView
android:id="@+id/tv_title_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="center"
android:textSize="24sp"
android:textColor="#22ff11"
android:text="Title Text"
/>
<Button
android:id="@+id/btn_title_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dp"
android:background="#22ff11"
android:text="Edit"
android:textColor="#1100ff"
android:textSize="24sp"
/>
</LinearLayout>
然后修改activity_main.xml中的代码:
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<include layout="@layout/title"/>
</LinearLayout>
这样我们就通过
这一行代码将整个标题栏引入进来了.在MainActivity当中利用
requestWindowFreature(Window.FEATURE_NO_TITLE);将原来的title隐藏掉即可.
使用这种方式,不管有多少布局要引入标题栏,只需要一行代码即可.
2.2 创建自定义控件
引入布局的技巧确实解决了重复编写布局代码的问题,但是如果布局中有一些控件要求能够响应事件,我们还是
需要在每个活动中为这些控件编写事件注册和处理代码.比如说标题栏中的返回按钮,其实不管是哪一个活动
这个按钮的功能都是销毁当前的活动.而如果在每一个活动中都需要重新注册一般返回按钮的点击事件,无疑
增加了很多重复的代码,这种情况下最好是使用自定义控件的方式来解决.
新建TitleLayout继承自LinearLayout,让它成为我们自定义的标题栏控件,代码如下:
package com.example.my03_mycomponent;
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);
/**
* @R.layout.title 要加载的布局文件的id
* @this 加载好的布局再添加到的一个父布局,这里是this
*/
LayoutInflater.from(context).inflate(R.layout.title, this);
}
}
然后在我们的activity_main.xml当中引入这个控件
修改activity_main.xml中的代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<com.example.my03_mycomponent.TitleLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</com.example.my03_mycomponent.TitleLayout>
</LinearLayout>
在xml文件布局文件中,添加自定义的控件和普通的控件是一样的,只不过在添加自定义控件的时候我们需要指明控件的完整类名和
包名.然后我们为标题栏中的按钮注册点击事件,修改TitleLayout中的代码:如下所示:
TitleLayout.java
package com.example.my03_mycomponent;
import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;
/**
* 自定义控件类
*
*/
public class TitleLayout extends LinearLayout
{
public TitleLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
/**
* @R.layout.title 要加载的布局文件的id
* @this 加载好的布局再添加到的一个父布局,这里是this
*/
LayoutInflater.from(context).inflate(R.layout.title, this);
Button btnBack = (Button) findViewById(R.id.btn_title_back);
Button btnEdit = (Button) findViewById(R.id.btn_title_edit);
btnBack.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
((Activity)getContext()).finish();
}
});
btnEdit.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Toast.makeText(getContext(), "You Click The Edit!", Toast.LENGTH_SHORT).
}
});
}
}
这样的话,每当我们在一个布局中引入TitleLayout的时候,返回按钮和编辑按钮的点击事件就已经自动实现好了,也
就不用再每个activity当中去注册监听事件了.