android复合控件

一.复合控件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" />

时间: 2024-10-08 03:30:59

android复合控件的相关文章

Android之——自定义复合控件的实现

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47101387 有一定Android开发经验的童鞋都知道,有时候Android提供的原生视图无法满足我们自己项目的业务需求,这就需要我们自己去自定义Android控件了,在很多情况下,需要我们自己去将很多控件(Android原生控件,自定义控件)组合起来,生成一个新的视图来满足我们自己项目的业务需求.好了,本文就是向大家介绍如何自定义Android复合控件,我在这篇文章中,以一个文

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

一.关于layout_margin 搞Android时间也不短了,对layout_margin也不陌生了,可最近遇到一个问题让我发现,对它的认识还不够深入全面.大量网络资料上都说,layout_margin指view距离父view的距离.这个说法不够严谨,正确的说法是,距离view的相对view的距离才更准确. 在Linearlayout下,可以认为是距离父view的距离.但在RelativeLayout下则不然,如果view A已经写定在view B的右侧,则view A的layout_mar

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

一.关于layout_margin 搞Android时间也不短了.对layout_margin也不陌生了,可近期遇到一个问题让我发现,对它的认识还不够深入全面.大量网络资料上都说,layout_margin指view距离父view的距离.这个说法不够严谨.正确的说法是.距离view的相对view的距离才更准确. 在Linearlayout下,能够觉得是距离父view的距离. 但在RelativeLayout下则不然.假设view A已经写定在view B的右側.则view A的layout_ma

Android自定义View之自定义复合控件--标题栏

1 实现效果 2 例子代码讲解 2.1 attrs.xml <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="TopBar"> <attr name="title" format="string" /> <attr name="titleTex

Android自定义View入门

View架构简介: 在Android中,控件主要以ViewGroup和View的形式存在.ViewGroup控件可以包含多个View控件,该复合控件负责其内部所有子控件的测量和绘制,并传递交互事件.如图, 在Android的移动开发中,每个Activity都包含了一个PhoneWindow对象,该对象将DecorView设置为应用窗口的根View.该视图上的所有监听事件都通过WindowManagerService来进行接收,并通过Activity来回调相应的onClickListener.De

Android零基础入门第16节:Android用户界面开发概述

相信通过前面15期的学习,Android的开发环境已经基本掌握了,如果仍有问题,欢迎到Android零基础入门技术讨论微信群交流,从本期开始正式来一步一步踏入Android开发之路. Android应用开发的一项内容就是用户界面的开发.Android提供了非常丰富的用户界面组件,借助于这些用户界面组件,开发者可以非常方便地进行用户界面开发,而且可以开发出非常优秀的用户界面. 一.界面UI元素介绍 Android应用是运行于手机系统上的程序,这种程序给用户的第一印象就是用户界面.接下来从以下几个方

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

目录 使用视图和布局 理解Fragment 优化布局 创建分辨率无关的用户界面 扩展.分组.创建和使用视图 使用适配器将数据绑定到视图 使用视图和布局 1. Android UI 几个基本概念 视图: 所有可视界面的元素(通常称为控件或者小组件)的基类.所有的UI控件(包括布局类)都是由 View 派生而来的. 视图组:视图类的扩展,可以包含多个子视图.通过扩展ViewGroup类,可以创建由多个相互连接的子视图组成复合控件:还可以通过扩展ViewGroup类来提供布局管理器,以帮助在Aciti

Android视图控件架构分析之View、ViewGroup

在Android中,视图控件大致被分为两类,即ViewGroup和View,ViewGroup控件作为父控件,包含并管理着子View,通过ViewGroup和View便形成了控件树,各个ViewGoup对象和View对象就是控件树中的节点.在控件树中,以树的深度来遍历查找对应的控件元素,同时,上层控件负责子控件的测量与绘制,并传递交互事件. Android控件树: AndroidUI界面架构图: 一.测量View的工具类:MeasureSpec 1.MeasureSpec包含了测量的模式和测量的

android View的测量和绘制

本篇内容来源于android 群英传(徐易生著) 我写到这里,是觉得徐易生讲的确实很好, 另外加入了一些自己的理解,便于自己基础的提高. 如果要绘制一个View , 就需要先取测量它,也就是需要知道它的大小和位置. 这样我们就能在屏幕中滑出来它了.这个过程是在onMeasure()方法中完成的. 一.测量模式 测量view的大小时,需要用到MeasureSpec (测量规范)这个类来指定测量模式 ,一共有3种 EXACTLY (精确模式) , 系统默认值. 如果我们指定控件宽高为 xxdp, x