接触Android UI开发的这段时间以来,对自定义组合控件有了必定的了解,为此小结一下,本文小结内容主要讨论的是如何使用Android SDK提供的布局和控件组成一个功能完整组合控件并将其封装为面向对象的类,而并不是讨论如何继承自SDK提供的控件类(好比TextView),对其进行自定义扩展的问题。android
进入正题前,咱们先来看一组功能需求框架
假设在手机需求上,那么如上三个界面咱们能够使用三个Activity,每一个Activity一个布局文件,实现起来比较独立,可是假设在Android pad上要求如上三个界面在一个对话框上实现,并且切换过程当中要有渐变更画,那么该如何实现呢?个人方案是经过使用一个浮动的Activity外加ViewFlipper来实现。虽然咱们能够在这个浮动的Activity类内可以获取到每一个界面的控件并添加相应的操做,可是若是所有放在一个Activity类内,会使这个类内代码量很大,代码走读起来也不容易,并且也少了些OO的概念,为此能够考虑将每个界面用一个自定义的组合控件类来实现。同理,假设上面的第一个界面里面关于微博绑定的列表界面,咱们能够考虑使用ListView控件外加一个自定义扩展的Adapter,其中的每一项,其实也是一个组合控件,须要咱们在自定义的Adapter中建立出来。为了尝试自定义组合控件的使用,对于微博列表我也没有使用ListView来实现,而是采用了基础的addView方式。eclipse
下面具体分步骤来讲明自定义组合控件的实现和封装:ide
这一步和其它新建和编写布局资源的方法同样,能够使用拖动控件,也能够使用代码输入,亦能够经过其它第三方开发工具编写,总之,结果是要获得一个知足需求的布局,为了后面行文的方便,我就取上面第二个界面布局account_info_preview.xml中的部分代码来讲明下函数
<?xml version="1.0" encoding="utf-8"?>工具
<LinearLayout布局
xmlns:android="http://schemas.android.com/apk/res/android"开发工具
android:orientation="vertical"动画
android:layout_width="fill_parent"spa
android:layout_height="fill_parent"
android:background="@drawable/login_view_back">
<RelativeLayout
android:layout_height="@dimen/content_top_land_height"
android:layout_width="fill_parent"
android:padding="@dimen/login_title_padding"
android:background="@drawable/login_title_back">
……
</RelativeLayout>
</LinearLayout>
这一步的实现要求就是经过所见即所得的原理,使得编辑完后布局在Graphical Layout界面看到的效果就是你想要实现的界面的静态效果就能够了。
上面的account_info_preview.xml布局文件建立好以后,就能够为这个组合控件的布局建立一个你须要的自定义类了,假设这个类被命名为AccountInfoPreView类,那么经过eclipse先建立该类,该类的父类就是组合控件根元素对应的类,这里是LinearLayout,因此这个AccountInfoPreView就应该派生自LinearLayout。
LinearLayout有两个构造函数,在AccountInfoPreView类中咱们必须重写父类的构造函数,因为在使用中,咱们不采用直接new AccountInfoPreView(Context context)方式建立该组合控件,因此咱们只须要重载一个public AccountInfoPreView(Context context, AttributeSet attrs)构造函数就能够了,这个就看你自定义的组合控件的需求了。
另外为了在自定义类中进行对控件对象的实例化,咱们须要重写protected void onFinishInflate()函数,以实现资源id和控件对象的一一对应。下面以贴出代码为例
package com.netease.pris.hd.view;
……
public class AccountInfoPreView extends LinearLayout
{
TextView mViewTitle;
ImageView mHeader;
public AccountInfoPreView(Context context, AttributeSet attrs)
{
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
protected void onFinishInflate()
{
mViewTitle =(TextView)findViewById(R.id.aip_title_text);
mHeader = (ImageView)findViewById(R.id.aip_header_imgae);
}
……
}
如上就为自定义控件类搭好了框架,具体须要进行何种操做,就往里面写操做就能够了,好比添加控件点击事件等等。
自定义组合控件的类有了,自定义组合控件的布局也有了,虽然类内也用findViewById对组合控件内部的控件进行了一一实例化,可是整个组合控件类和布局尚未创建起关联关系,这一步就经过用自定义类的包名+类名来修改自定义组合控件布局的根元素完成。咱们看到咱们上面的自定义类的包名为com.netease.pris.hd.view,类名为AccountInfoPreView,因此咱们从新将上面的account_info_preview.xml内的LinearLayout根元素替换为AccountInfoPreView就能够了。具体以下示例
<?xml version="1.0" encoding="utf-8"?>
<com.netease.pris.hd.view.AccountInfoPreView
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/login_view_back">
<RelativeLayout
android:layout_height="@dimen/content_top_land_height"
android:layout_width="fill_parent"
android:padding="@dimen/login_title_padding"
android:background="@drawable/login_title_back">
……
</RelativeLayout>
</com.netease.pris.hd.view.AccountInfoPreView>
好了,上面已经将建立自定义组合控件的步骤介绍完了,也建立了一个AccountInfoPreView的自定义组合控件,接下来咱们就要讲解使用这个自定义组合控件了。
根据资源加载的静态和动态两种方式,使用自定义组合控件,也一样有静态和动态两种方式,其实也很简单的两种方式,跟Android的Inflate有关系。
这里所说的静态加载,就是自定义组合控件被使用它的布局在XML资源中包含了,而这个布局又经过Activity的setConentView()函数设置进去了,那么咱们就能够经过findViewById的方式来实例化自定义组合控件的对象。
好比上面建立的AccountInfoPreView自定义组合控件被Activity的setConentView函数设置的布局account_view_flipper.xml所包含,其内容以下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="@dimen/login_dialog_width"
android:layout_height="@dimen/login_dialog_height">
<ViewFlipper
android:id="@+id/account_view_flippe"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<include
android:id="@+id/account_info_preview"
layout="@layout/account_info_preview" />
</ViewFlipper>
</LinearLayout>
咱们就能够经过findViewById的方法来实例化自定义组合控件的对象,代码以下
AccountInfoPreView mAIPView = (AccountInfoPreView)findViewById(R.id.account_info_preview);
成功实例化了对象,至于后面对该对象的具体使用就不罗列了。
动态加载,就是自定义组合控件在资源布局中没有包含,咱们经过代码动态建立到所须要的ViewGroup中去。因为自定义组合控件,不像TextView等基础控件或自定义的不关联资源的View,因此不能经过new方式直接进行建立,须要经过Inflate方法实例化自定义组合控件对象,并将其添加到ViewGroup中去,咱们能够改写下上面的布局account_view_flipper.xml文件为
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="@dimen/login_dialog_width"
android:layout_height="@dimen/login_dialog_height">
<ViewFlipper
android:id="@+id/account_view_flippe"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</ViewFlipper>
</LinearLayout>
则在Activity的onCreate函数中咱们能够以下编写代码
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.account_view_flipper);
ViewFlipper mViewFlipper =(ViewFlipper)findViewById(R.id.account_view_flippe);
AccountInfoPreView mAIPView = (AccountInfoPreView)getLayoutInflater().inflate(R.id.account_info_preview, null);
mViewFlipper.addView(mAIPView);
}
经过上面的代码,咱们一样实例化了一个AccountInfoPreView控件对象,并将其动态加载到了界面上进行显示。具体操做一样根据具体需求来实现,这里就不作展开了。
关于Android自定义组合控件就小结到这里,假如文中有不正确的地方还望帮忙斧正,谢谢。