在我们平时的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. HXY玩卡片(水题测试2017082401&洛谷2192)

    题目链接:HXY玩卡片 很水, 简单讲一下思路. 如果没有0,直接无解,因为不可能是10的倍数. 是9的倍数,则各个数位上的数字和为9的倍数,所以5的数量一定是9的倍数,所以只要尽可能多输出9的倍数个 ...

  2. Django框架之验证码生成示例

    一.生成随机颜色的图片 1)前端代码展示 <!DOCTYPE html> <html lang="en"> <head> <meta ch ...

  3. 【转】如何用Redis做LRU-Cache

    LRU(Least Recently Used)最近最少使用算法是众多置换算法中的一种. Redis中有一个maxmemory概念,主要是为了将使用的内存限定在一个固定的大小.Redis用到的LRU ...

  4. 2019.01.21 bzoj2989: 数列(二进制分组+主席树)

    传送门 二进制分组入门题. 主席树写错调题2h+2h+2h+体验极差. 题意简述:给一堆点,支持加入一个点,询问有多少个点跟(x,y)(x,y)(x,y)曼哈顿距离不超过kkk. 思路:题目要求的是对 ...

  5. 走进JDK(三)------AbstractStringBuilder、StringBuffer、StringBuilder

    AbstractStringBuilder是一个抽象类,StringBuffer.StringBuilder则继承AbstractStringBuilder,所以先说AbstractStringBui ...

  6. 在 Linux/windows下 命令行中使用和执行 PHP 代码[交互式php]

    [注释]在ubuntu下,升级php到7.1版本,虽然提示的是Interactive mode enabled, 但实际上可以直接书写命令,和interactive shell效果一样. 一:wind ...

  7. c#中数组array和list在函数间传递 转置

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...

  8. 快速创建一个 Servlet 项目(2)

    1. 新建一个 webapp 参考 http://www.cnblogs.com/zno2/p/5909019.html 2.调整jdk版本 修改 pom.xml 文件,将jdk 调整为适当的版本,比 ...

  9. html5打开摄像头并用canvas模拟拍照 - 转

    <video id="video" width="640" height="480" autoplay></video&g ...

  10. POJ1446 Girls and Boys

    Girls and Boys Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 12747   Accepted: 5678 D ...