在我们平时的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. HYSBZ - 3676

    模板题.问你一个串里最大的值(回文子串*出现次数) /* gyt Live up to every day */ #include<cstdio> #include<cmath> ...

  2. sql心跳

    因为interactive_timeout决定的是交互连接的时间长短,而wait_timeout决定的是非交互连接的时间长短. 问:为什么需要设置interactive_timeout  wait_t ...

  3. ubuntu16下的/etc/resolv.conf重置的解决方案

    此文件存放了网络网关信息,重启后会刷新,刷新来源有两个可能 一个是根据文件中的resolvconf目录下的resolv.conf.d目录下的base文件 另一个来源是/etc/network/inte ...

  4. day08作业---函数

    '''2.写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者.'''#学会了 原来 range(len(iter)) 是 从零到len-1 的数的组合 建新放在 ...

  5. Maven手动将jar包放入本地仓库

    mvn install:install-file -Dfile=jar包的位置 -DgroupId=上面的groupId -DartifactId=上面的artifactId -Dversion=上面 ...

  6. 模块and包

    一.模块 1.import 加载的模块四个通用类别 1.使用python编写的py文件 2.已被编译为共享库或者DLL或者C\C++的扩展 3.包好一组模块的包 4.使用c编写并连接到python解释 ...

  7. docker 批量操作容器

    docker stop $(sudo docker ps -q)

  8. MacBook小技巧

    退出全屏:Control+Command+F.关闭当前的应用程序:Command+W.退出应用程序,可对着Dock上的应用程序辅助点按(右键),选择退出.也可直接按Commnad+Q退出当前的应用程序 ...

  9. 算法工程师A

    美团点评2017校招笔试真题-算法工程师A   美团点评2017校招笔试真题-算法工程师A 1.下面哪种STL容器的实现和其它三个不一样 A. set B. deque C. multimap D. ...

  10. maven学习之一:maven安装

    1.下载maven: 地址:https://maven.apache.org/ 点击download后; 解压: 解压后放在d:\develop目录下 下面我们去配置环境变量,找到计算机,右键,找到属 ...