day03 创建自定义控件

来源:互联网 发布:有效工作时间 知乎 编辑:程序博客网 时间:2024/06/05 02:51

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当中去注册监听事件了.

0 0
原创粉丝点击