在我们平时的Android开发中,有时候原生的控件无法满足我们的需求,或者经常用到几个控件组合在一起来使用.这个时候,我们就可以根据自己的需求创建自定义的控件了,一般通过继承View或其子类来实现.

实现一个自定义控件一般需要下面三个步骤:

1. 设计控件中需要的属性 (xml)

2. 实现自定义的View (java)

3. 引用自定义的View (xml)

下面我们通过实例来实现一个完整的自定义组合控件--TopBar,左右两边各一个Button,中间是一个TextView.

先看下最终效果:

下面通过代码来完成自定义控件的完整过程.

.设计控件中需要的属性

我们可以先把要实现的自定义控件画一个草图,来分析需要设计哪些属性.我们需要在values资源文件夹下创建一个定义控件的xml文件.

atts.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--
使用declare-styleable标签定义控件,name为控件名
使用attr标签定义控件的属性,name为属性名,format为属性的类型
-->
<declare-styleable name="topBar">
<attr name="tbTitle" format="string" />
<attr name="titleTextSize" format="dimension" />
<attr name="titleTextColor" format="color" /> <attr name="leftText" format="string" />
<attr name="leftBackground" format="reference|color" />
<attr name="leftTextColor" format="color" /> <attr name="rightText" format="string" />
<attr name="rightBackground" format="reference|color" />
<attr name="rightTextColor" format="color" />
</declare-styleable>
</resources>

.实现自定义的View

TopBar.java

package scratchcard.cbt.com.learnuserdefinedview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView; /**
* Created by caobotao on 15/12/9.
*/
public class TopBar extends RelativeLayout{
/**
* 声明控件
*/
private Button leftBtn;//左按钮
private TextView textView;//中间文本框
private Button rightBtn;//右按钮 /**
* 声明三个控件的属性
*/
//声明左按钮的属性
private String leftText;//按钮文本
private Drawable leftBackground;//按钮背景
private int leftTextColor;//按钮文本颜色
//声明中间文本框的属性
private String tbTitle;//文本框文本
private float titleTextSize;//文本框字体大小
private int titleTextColor;//文本框字体颜色
//声明右按钮的属性
private String rightText;//按钮文本
private Drawable rightBackground;//按钮背景
private int rightTextColor;//按钮文本颜色 /**
* 声明三个控件的布局属性
*/
private LayoutParams leftBtnLayoutParams;
private LayoutParams textViewLayoutParams;
private LayoutParams rightBtnLayoutParams; //声明左右按钮点击监听
private TopBarBtnsOnClickListener listener; //创建一个监听左右按钮点击的接口
public interface TopBarBtnsOnClickListener{
public void leftBtnOnClick();//左按钮被点击的事件
public void rightBtnOnClick();//右按钮被点击的事件
} //向外提供一个设置监听的方法
public void setOnTopBarBtnsClick(TopBarBtnsOnClickListener listener){
this.listener = listener;
} //重写构造方法
public TopBar(Context context, AttributeSet attrs) {
super(context, attrs);
/**
* 用TypedArray可以获取用户在xml中声明的此控件的所有属性,以键值对存储,
* K:资源文件(例 R.styleable.topBar_leftText)
* V:属性值
*/
TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.topBar); //为左按钮的属性赋值
leftText = ta.getString(R.styleable.topBar_leftText);
leftBackground = ta.getDrawable(R.styleable.topBar_leftBackground);
leftTextColor = ta.getInt(R.styleable.topBar_leftTextColor,0); //为中间的文本框的属性赋值
tbTitle = ta.getString(R.styleable.topBar_tbTitle);
titleTextSize = ta.getDimension(R.styleable.topBar_titleTextSize,0);
titleTextColor = ta.getInt(R.styleable.topBar_titleTextColor,0); //为右按钮的属性赋值
rightText = ta.getString(R.styleable.topBar_rightText);
rightBackground = ta.getDrawable(R.styleable.topBar_rightBackground);
rightTextColor = ta.getInt(R.styleable.topBar_rightTextColor,0); //使用完TypedArray之后需要调用其recycle()方法,以便重用
ta.recycle(); //实例化三个控件
leftBtn = new Button(context);
textView = new TextView(context);
rightBtn = new Button(context); //设置左按钮的属性
leftBtn.setText(leftText);
leftBtn.setBackground(leftBackground);
leftBtn.setTextColor(leftTextColor);
//设置文本框的属性
textView.setText(tbTitle);
textView.setTextSize(titleTextSize);
textView.setTextColor(titleTextColor);
textView.setGravity(Gravity.CENTER);
//设置右按钮的属性
rightBtn.setText(rightText);
rightBtn.setBackground(rightBackground);
rightBtn.setTextColor(rightTextColor); //设置此自定义控件的背景颜色
setBackgroundColor(0xFFF59563); //实例化左按钮的布局属性
leftBtnLayoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
//设置左按钮靠左显示
leftBtnLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE);
//将左按钮添加到本自定义控件中
addView(leftBtn,leftBtnLayoutParams); //同上
rightBtnLayoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
rightBtnLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE);
addView(rightBtn,rightBtnLayoutParams); //同上
textViewLayoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
textViewLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE);
addView(textView,textViewLayoutParams); //回调左按钮的监听事件
leftBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.leftBtnOnClick();
}
}); //回调右按钮的监听事件
rightBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.rightBtnOnClick();
}
}); } //当然,我们还可以添加其他控制此控件的方法,如设置左按钮是否可见等等,大家可根据自己的需求进行扩展
public void setLeftBtnVisible(boolean isVisible){
leftBtn.setVisibility(isVisible ? VISIBLE : INVISIBLE);
}
}

.引用自定义的View

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>

<!--
使用自定义的控件的属性需要先添加命名空间
xmlns:cbt="http://schemas.android.com/apk/res-auto"
其中"cbt"可以任意指定,但是不能与系统的命名空间相同
在Android Studio中如上用res-auto,
在Eclipse需要在res后指定完整包名,如:
xmlns:cbt="http://schemas.android.com/apk/res/scratchcard.cbt.com.learnuserdefinedview.TopBar"
--> <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cbt="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="scratchcard.cbt.com.learnuserdefinedview.MainActivity">
<!-- 添加自定义控件及属性 -->
<scratchcard.cbt.com.learnuserdefinedview.TopBar
android:id="@+id/topbar"
android:layout_width="wrap_content"
android:layout_height="40dp"
cbt:leftText = "BACK"
cbt:leftBackground = "@android:color/holo_blue_bright"
cbt:leftTextColor = "#FFFFFF" cbt:tbTitle = "自定义标题"
cbt:titleTextSize = "10sp"
cbt:titleTextColor = "#000000" cbt:rightText = "MORE"
cbt:rightBackground = "@android:color/holo_blue_bright"
cbt:rightTextColor = "#FFFFFF"/> </LinearLayout>

MainActivity.java

package scratchcard.cbt.com.learnuserdefinedview;

import android.app.Activity;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.ViewTreeObserver;
import android.widget.Button;
import android.widget.Toast;
import scratchcard.cbt.com.learnuserdefinedview.TopBar.TopBarBtnsOnClickListener; public class MainActivity extends Activity {
//创建自定义控件
private TopBar topBar;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化自定义控件
topBar = (TopBar) findViewById(R.id.topbar);
//为自定义控件添加按钮的监听事件
topBar.setOnTopBarBtnsClick(new TopBarBtnsOnClickListener() {
@Override
public void leftBtnOnClick() {
Toast.makeText(MainActivity.this,"LEFT",Toast.LENGTH_SHORT).show();
}
@Override
public void rightBtnOnClick() {
Toast.makeText(MainActivity.this,"RIGHT",Toast.LENGTH_SHORT).show();
}
}); }
}

运行项目后点击左边按钮:                                  点击右边按钮:

           

至此,整个自定义控件就已经完成了.虽然效果有些寒碜,但是麻雀虽小,五脏俱全.主要是通过这个实例使大家掌握自定义组合控件的过程与方法.学会了创建自定义控件的方法之后可以举一反三完成自己的漂亮的作品.

完整源码 : 点击下载

作者:caobotao
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位 置给出原文连接,否则保留追究法律责任的权利。

作者:caobotao
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。

Android自定义组合控件详细示例 (附完整源码)的更多相关文章

  1. 014 Android 自定义组合控件

    1.需求介绍 将已经编写好的布局文件,抽取到一个类中去做管理,下次还需要使用类似布局时,直接使用该组合控件的对象. 优点:可复用. 例如要重复利用以下布局: <RelativeLayout an ...

  2. Android自定义组合控件

    今天和大家分享下组合控件的使用.很多时候android自定义控件并不能满足需求,如何做呢?很多方法,可以自己绘制一个,可以通过继承基础控件来重写某些环节,当然也可以将控件组合成一个新控件,这也是最方便 ...

  3. Android自定义组合控件内子控件无法显示问题

    今天自定义了一个组合控件,与到了个奇葩问题: 我自定义了一个RelativeLayout,这个layout内有多个子控件.但奇怪的是这些子控件一直显示不出来.调试了一下午,竟然是因为在获取(infla ...

  4. (转)android自定义组合控件

    原文地址:http://mypyg.iteye.com/blog/968646 目标:实现textview和ImageButton组合,可以通过Xml设置自定义控件的属性. 1.控件布局:以Linea ...

  5. android 自定义组合控件 顶部导航栏

    在软件开发过程中,经常见到,就是APP 的标题栏样式几乎都是一样的,只是文字不同而已,两边图标不同.为了减少重复代码,提高效率, 方便大家使用,我们把标题栏通过组合的方式定义成一个控件. 例下图: 点 ...

  6. Android自定义组合控件:UIScrollLayout(支持界面滑动及左右菜单滑动)

    一.前言: 我之前很早的时候,写过一篇<左右滑出菜单>的文章: http://blog.csdn.net/qingye_love/article/details/8776650 用的是对V ...

  7. Android 自定义组合控件

    1, you need to add this kind of code to the constructors of your custom view which must extend ViewG ...

  8. Android Studio自定义组合控件

    在Android的开发中,为了能够服用代码,会把有一定共有特点的控件组合在一起定义成一个自定义组合控件. 本文就详细讲述这一过程.虽然这样的View的组合有一个粒度的问题.粒度太大了无法复用,粒度太小 ...

  9. Android中自定义组合控件

    Android中自定义控件的情况非常多,一般自定义控件可以分为两种:继承控件及组合控件.前者是通过继承View或其子类,重写方法实现自定义的显示及事件处理方式:后者是通过组合已有的控件,来实现结构的简 ...

随机推荐

  1. Java第15章笔记

    字符串的概述 1.什么是字符串:零个或多个字符组成的有限序列 2.如何使用字符串:(使用字符串分为两步)          1)定义并初始化字符串          2)使用字符,对字符串进行一些处理 ...

  2. python下使用opencv拍照

    首先在命令中安装opencv: pip install opencv-python 然后打开notebook: jupyter notebook 建立文件,写入如下代码: import cv2 cap ...

  3. centos7 虚拟机安装docker-ce-17.09

    1.创建虚拟机使用iso镜像centos-x86_64-7.3.1611 2.安装centos选择桌面版 3.配置命令行环境,网卡(见博客另一篇文章) 4.安装container-selinux-2. ...

  4. ios alloc init 和 new 的区别

    1.在实际开发中很少会用到new,一般创建对象咱们看到的全是[[className alloc] init] 但是并不意味着你不会接触到new,在一些代码中还是会看到[className new], ...

  5. matlab 向量场线积分

    syms t x y z F x=cos(t); y=sin(t); z=*sin(t)^-; F=[x^*y , (/)*x^,x*y ] ; %场函数 V=[diff(x,t),diff(y,t) ...

  6. C++ 中 new 操作符内幕:new operator、operator new、placement new

    一.new 操作符(new operator) 人们有时好像喜欢有益使C++语言的术语难以理解.比方说new操作符(new operator)和operator new的差别. 当你写这种代码: st ...

  7. excel怎样添加的选项卡中含有下拉列表

    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui"> <ribbon s ...

  8. UVa 11542 Square (高斯消元)

    题意:给定 n 个数,从中选出一个,或者是多个,使得选出的整数的乘积是完全平方数,求一共有多少种选法,整数的素因子不大于 500. 析:从题目素因子不超过 500,就知道要把每个数进行分解.因为结果要 ...

  9. Struts2--HelloWord

    Struts2官网 官网指南 官网下载Struts2.5-min-lib.zip解压把lib目录下jar包拷贝到web项目lib目录下 配置web.xml文件 <filter> <f ...

  10. 使用 alt_disk_copy 克隆 rootvg

    地址:http://www.ibm.com/developerworks/cn/aix/library/au-alt_disk_copy/ 简介 大多数系统管理员都遇到过以下情况: 一次 ML 升级失 ...