一.复合控件TopBar
 
创建复合控件可以很好地创建出具有重用功能的控件集合。比如TopBar。
做法:一般需要继承ViewGroup,再给它添加指定功能的控件。
 
以TopBar为例:
 
1.自定义属性
在values目录下创建attrs.xml文件,在该文件中定义相关的属性即可。
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="TopBar">
        <!--<attr name="android:title"/>-->
        <attr name="title1" format="string" />
        <attr name="titleTextSize1" format="dimension" />
        <attr name="titleTextColor1" format="color" />

<attr name="leftTextColor" format="color" />
        <attr name="leftBackground" format="reference|color" />
        <attr name="leftText" format="string" />

<attr name="rightTextColor" format="color" />
        <attr name="rightBackground" format="reference|color" />
        <attr name="rightText" format="string" />
    </declare-styleable>

</resources>
 
遇到的问题:
我在写代码的时候,开始是写成<attr name="title" format="string" />;当我运行的时候会出现错误:Attribute "title" has already been defined。
后来我将所有的title,titleTextSize,titleTextColor都改成title1,titleTextSize1,titleTextColor1,就不会出错了。
其实原因在于title等在系统中已经有了明确的语义定义了,也就是已经存在了。
我们也可以直接使用系统中已经定义好的属性<attr name="android:title" />,记住不要写format(判断是自己申明的,还是直接使用系统的,就看format)。
 
2.创建自定义控件,这里简单点,只是继承RelativeLayout,然后在构造方法中,写如下代码。这里需要使用带AttributeSet类型的构造方法,因为需要解析属性。
//1.通过这个方法,将你在attrs.xml中定义的所有属性的值存储到TypedArray集合中。
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TopBar);

//2.从TypedArray中取出对应的值来为要设置的属性赋值。
String mTitle = ta.getString(R.styleable.TopBar_title1);
float mTitleTextSize = ta.getDimension(R.styleable.TopBar_titleTextSize1, 10);
int mTitleTextColor = ta.getColor(R.styleable.TopBar_titleTextColor1, 0);

String mLeftText = ta.getString(R.styleable.TopBar_leftText);
Drawable mLeftBackground = ta.getDrawable(R.styleable.TopBar_leftBackground);
int mLeftTextColor = ta.getColor(R.styleable.TopBar_leftTextColor, 0);

String mRightText = ta.getString(R.styleable.TopBar_rightText);
Drawable mRightBackground = ta.getDrawable(R.styleable.TopBar_rightBackground);
int mRightTextColor = ta.getColor(R.styleable.TopBar_rightTextColor, 0);

//3.获取完TypedArray的值后,调用recycle进行资源的回收,避免重新创建的时候的错误。

ta.recycle();
 
分析:
1.获取存储自定义属性的TypedArray集合。
2.取出对应的属性值,注意其类型。
3.资源回收,避免重新创建时出现错误。
 
3.动态添加控件(在TopBar中,需要左右Button,和一个TextView)
//1.创建需要的控件
mLeftButton = new Button(context);
mRightButton = new Button(context);
mTitleView = new TextView(context);

//2.为控件赋值(自定义的属性)
mLeftButton.setText(mLeftText);
mLeftButton.setBackground(mLeftBackground);
mLeftButton.setTextColor(mLeftTextColor);

mRightButton.setText(mRightText);
mRightButton.setBackground(mRightBackground);
mRightButton.setTextColor(mRightTextColor);

mTitleView.setText(mTitle);
mTitleView.setTextSize(mTitleTextSize);
mTitleView.setTextColor(mTitleTextColor);
mTitleView.setGravity(Gravity.CENTER);

//3.设置布局
LayoutParams mLeftParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
mLeftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE);
addView(mLeftButton, mLeftParams);

LayoutParams mRightParams = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.MATCH_PARENT);
mRightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, TRUE);
addView(mRightButton, mRightParams);

LayoutParams mTitleParams = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.MATCH_PARENT);
mTitleParams.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE);;

addView(mTitleView, mTitleParams);
 
分析:
动态添加控件更加具有重用性,而不是仅仅写在xml文件中。
1.创建控件实例
2.为控件设置自定义属性
3.设置控件的布局参数(注意是RelativeLayout.LayoutParams)
4.添加控件到View中
 
4.在构造方法中实现左右按钮的点击事件,但是具体的逻辑不给出。因为想要做的是整个UI模板。所以具体的逻辑给调用者去写。这里也涉及到了接口回调。详见接口回调。
     接口回调的具体步骤(要去理解,而不是去死记硬背):
1.定义接口,抽象方法
2.定义接口对象,在要实现的地方调用方法
3.暴露一个公共方法给调用者使用
mLeftButton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        mListener.leftClick();
    }
});

mRightButton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        mListener.rightClick();
    }
});

 
5.实现接口回调的最后步骤
在调用者代码中,实现上述接口,并且完成暴露出来的方法。具体要实现的逻辑由调用者决定。
topBar.setOnTopbarClickListener(new TopBar.topbarClickListener() {
    @Override
    public void leftClick() {
        Toast.makeText(MainActivity.this,"点击左边按钮",Toast.LENGTH_SHORT).show();
    }

@Override
    public void rightClick() {
        Toast.makeText(MainActivity.this,"点击右边按钮",Toast.LENGTH_SHORT).show();
    }
});

 
6.引用UI模板
上述1~5点是完整的TopBar.java
1.在引用前,需要指定引用第三方控件的名字空间(xmlns---xmlnamespace)
xmlns:custom="http://schemas.android.com/apk/res-auto"  custom就是命名空间,该名字可以随便取
系统的引用:xmlns:android="http:schemas.android.com/apk/res/android"。现在明白了为什么在创建xml文件的时候,总会有这句话了吧。
 
之后在XML文件中使用自定义属性的时候,就可以通过这个名字空间来引用
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

<com.example.geyan.textviewdemo.TopBar
        android:id="@+id/topbar"
        android:layout_width="match_parent"
        android:layout_height="40dp"

custom:leftBackground="#ffa4c161"
        custom:leftText="Back"
        custom:leftTextColor="#FFFFFF"

custom:rightBackground="#ffa4c161"
        custom:rightText="More"
        custom:rightTextColor="#FFFFFF"

custom:title1="自定义标题"
        custom:titleTextColor1="#000000"
        custom:titleTextSize1="8sp"></com.example.geyan.textviewdemo.TopBar>

</RelativeLayout>

 
分析:
最好不要写到activity_main.xml文件中,创建一个xml文件写入,是为了让activity_main.xml文件看起来不会太复杂;而且很方便的可以在其他布局文件中引用。
从代码中可以看出,使用自定义的View和系统原生的View最大区别在于申明控件时,需要指定完整的包名;而引用自定义属性时,需要使用自定义的xmlns
 
2.在主布局文件中引用topbar.xml即可
<include layout="@layout/topbar" />
 
 
 

android复合控件的更多相关文章

  1. android:layout_margin真实含义 及 自己定义复合控件 layout()运行无效的问题解决

    一.关于layout_margin 搞Android时间也不短了.对layout_margin也不陌生了,可近期遇到一个问题让我发现,对它的认识还不够深入全面.大量网络资料上都说,layout_mar ...

  2. 介绍几个工作开发中封装的好用的android自定义控件

    首先看效果图, 看下这两个界面,第一个中用到了一个自定义的FlowRadioGroup,支持复合子控件,自定义布局: 第二个界面中看到了输入的数字 自动4位分割了吧:也用到了自定义的DivisionE ...

  3. 怎样进行Android UI元素设计

    Android UI元素里面包含了许多的内容,比如:该平台由操作系统.中间件.用户界面和应用软件组成,一个应用程序要想受用户喜爱,那么UI可不能差. Android为相似的编程名词引入了一些新的术语, ...

  4. 《Android群英传》读书笔记 (2) 第三章 控件架构与自定义控件详解 + 第四章 ListView使用技巧 + 第五章 Scroll分析

    第三章 Android控件架构与自定义控件详解 1.Android控件架构下图是UI界面架构图,每个Activity都有一个Window对象,通常是由PhoneWindow类来实现的.PhoneWin ...

  5. 我的Android 4 学习系列之创建用户基本界面

    目录 使用视图和布局 理解Fragment 优化布局 创建分辨率无关的用户界面 扩展.分组.创建和使用视图 使用适配器将数据绑定到视图 使用视图和布局 1. Android UI 几个基本概念 视图: ...

  6. 介绍几个好用的android自定义控件

    首先看效果图, 看下这两个界面,第一个中用到了一个自定义的FlowRadioGroup,支持复合子控件,自定义布局: 第二个界面中看到了输入的数字 自动4位分割了吧:也用到了自定义的DivisionE ...

  7. Android群英传笔记——第三章:Android控件架构与自定义控件讲解

    Android群英传笔记--第三章:Android控件架构与自定义控件讲解 真的很久没有更新博客了,三四天了吧,搬家干嘛的,心累,事件又很紧,抽时间把第三章大致的看完了,当然,我还是有一点View的基 ...

  8. Android群英传笔记——摘要,概述,新的出发点,温故而知新,可以为师矣!

    Android群英传笔记--摘要,概述,新的出发点,温故而知新,可以为师矣! 当工作的越久,就越感到力不从心了,基础和理解才是最重要的,所以买了两本书,医生的<Android群英传>和主席 ...

  9. 细说Android事件传递

    一.View的dispatchTouchEvent和onTouchEvent 探讨Android事件传递机制前,明确android的两大基础控件类型:View和ViewGroup.View即普通的控件 ...

随机推荐

  1. java 中 正则 正则表达式 匹配 url

    不多说 [http|https]+[://]+[0-9A-Za-z:/[-]_#[?][=][.][&]]* 这个就是匹配 网络上的网址 又称 url . 最起码 绝大部分的taobao ur ...

  2. Codeforces 372

    A (被装的袋鼠不可以装的袋鼠)贪心,排序,从n/2分成两部分. B 好一道前缀和的题目. C 标准算法不难想,m^2的算法见http://codeforces.com/blog/entry/9907 ...

  3. linux高级数据存储

    linux内此存储模式由5部分组成,自低向上的顺序: 物理卷,内核块设备驱动,内核文件系统驱动,虚拟文件系统,应用程序数据结构; 系统中所有的文件仅按此模式存储,无论是数据还是元数据,均在此模式下统一 ...

  4. 第二百六十九天 how can I 坚持

    什么是明事理,搞不懂啊,好烦. 有点像我妈. 为什么突然就想买房了呢,为什么?年龄到了,考虑的东西就不一样了. 哎,不要想太多,睡觉.

  5. Spring bean configuration inheritance

    In Spring, the inheritance is supported in bean configuration for a bean to share common values, pro ...

  6. spring注解使用

    一.各种注解方式 1.@Autowired注解(不推荐使用,建议使用@Resource) @Autowired可以对成员变量.方法和构造函数进行标注,来完成自动装配的工作.@Autowired的标注位 ...

  7. linux中vi编辑器

    vi编辑器,通常称之为vi,是一种广泛存在于各种UNIX和Linux系 统中的文本编辑程序.它的功能十分强大,但是命令繁多,不容易掌握,它可以执行输出.删除.查找.替换.块操作等众多文本操作,而且用户 ...

  8. 解读XMP元数据中ALAssetRepresentation

    当用户进行某些更改(裁剪,消除红眼,...),在内置 Photos.app iOS上,这些更改将不会应用到由相应 fullResolutionImage 返回的 ALAssetRepresentati ...

  9. Qt 自动搜索串口号列表

    @功能: SerialPortList 类实现当前可用的串口进行实时扫描,当发现有新的串口 或是现有串口消失时,SerialPortList类将发出一个QStringList类型的 信号onNewSe ...

  10. Wifi热点工具-青青草原WiFi

    有时只有有线网络,但手机需要上网,这时需要将笔记本作为无线热点. 青青草原WiFi,这个工具用起来挺方便,http://www.22zy.net/.