实际编程中,系统提供的控件往往无法满足我们的需求,一来是样子丑陋,二来是一些复杂的组合需要多次使用的话,每次都写一堆控件的组合会很耗费时间,所以我们将这些组件的组合自定义为一个新的控件,以后使用的时候直接用该控件,方便又简单。最常见的例子就是软件中的titleTar

实现自定义控件的步骤:

1.设置控件的属性

2.实现我们的View

3.引用我们自定的View

  官方文档:http://developer.android.com/training/custom-views/create-view.html

下面开始:

设置控件的属性:

  分析一下上面四个titleBar,都是由一个居中的文本和一个右边一个图片按钮组成,只不过后面两个没有按钮而已

  那么我们自定义的这个组件就得包含一下几个基本属性:文本内容,文本大小,文本颜色,按钮路径

  在value中新建一个xml文件attrs.xml,把这些属性创建出来

<?xml version="1.0" encoding="utf-8"?>
<resources><declare-styleable name="MyCustomTitleBar"><attr name="titleText" format="string"/><attr name="titleTextSize" format="dimension"/><attr name="titleTextColor" format="color"/><attr name="titleButtonImage" format="reference"/></declare-styleable>
</resources>

  declare-styleable标签是用来定义自定义控件的属性的,我们的控件属性都以attr形式存放在declare-styleable标签中,format是用来形容该属性的类型,有如下值可选:string,color,dimension,integer,enum,reference,float,boolean,fraction,flag

实现我们的View

定义一个继承自RelativeLayout的类MyCustomTitltBar,然后在他的构造方法中获取我们自定义的控件样式

package cn.lixyz.customviewdemo;import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.TextView;@SuppressLint("NewApi")
public class MyCustomTitleBar extends RelativeLayout {// 定义自定义控件包含的组件private TextView title;private ImageButton button;// 定义控件的属性private String titleText;private float titleTextSize;private int titleTextColor;private Drawable titleButtonImage;// 为每个控件定义LayoutParamsprivate LayoutParams textLayoutParams;private LayoutParams buttonLayoutParams;public MyCustomTitleBar(Context context, AttributeSet attrs) {super(context, attrs);// 获取我们定义的属性TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyCustomTitleBar);titleText = array.getString(R.styleable.MyCustomTitleBar_titleText);titleTextColor = array.getColor(R.styleable.MyCustomTitleBar_titleTextColor, 0);titleTextSize = array.getDimension(R.styleable.MyCustomTitleBar_titleTextSize, 10);titleButtonImage = array.getDrawable(R.styleable.MyCustomTitleBar_titleButtonImage);// 回收,以防出错
        array.recycle();// 新建包含的子组件title = new TextView(context);button = new ImageButton(context);// 为子组件赋值
        title.setText(titleText);title.setTextColor(titleTextColor);title.setTextSize(titleTextSize);button.setBackground(titleButtonImage);// 设置背景色setBackgroundColor(0xFF38373c);// 设置包含控件的属性并添加到view中textLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);textLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);addView(title, textLayoutParams);buttonLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);buttonLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);addView(button, buttonLayoutParams);}
}

   其中LayoutParams是用于child view(子视图) 向 parent view(父视图)传达自己的意愿的一个东西

  在获取属性的时候,android定义的格式为控件名_属性名  例如上面的MyCustomTitleBar_titleText、MyCustomTitleBar_titleTextSize

LayoutParams继承于Android.View.ViewGroup.LayoutParams. 
      LayoutParams相当于一个Layout的信息包,它封装了Layout的位置、高、宽等信息。假设在屏幕上一块区域是由一个Layout占领的,如果将一个View添加到一个Layout中,最好告诉Layout用户期望的布局方式,也就是将一个认可的layoutParams传递进去。 
      可以这样去形容LayoutParams,在象棋的棋盘上,每个棋子都占据一个位置,也就是每个棋子都有一个位置的信息,如这个棋子在4行4列,这里的“4行4列”就是棋子的LayoutParams。 
      但LayoutParams类也只是简单的描述了宽高,宽和高都可以设置成三种值: 
           1,一个确定的值; 
           2,FILL_PARENT,即填满(和父容器一样大小); 
           3,WRAP_CONTENT,即包裹住组件就好。

http://byandby.iteye.com/blog/816718

  TypedArray实例是个属性的容器,通过context.obtainStyledAttributes()方法返回得到

引用我们自定的View

在布局文件中引入我们自定义的控件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:custom="http://schemas.android.com/apk/res/cn.lixyz.customviewdemo"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="cn.lixyz.customviewdemo.MainActivity" ><cn.lixyz.customviewdemo.MyCustomTitleBarandroid:layout_width="wrap_content"android:layout_height="wrap_content"custom:titleButtonImage="@drawable/image"custom:titleText="通讯录"custom:titleTextColor="#ffffff"custom:titleTextSize="5dp" ></cn.lixyz.customviewdemo.MyCustomTitleBar><cn.lixyz.customviewdemo.MyCustomTitleBarandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="10dp"custom:titleButtonImage="@drawable/plus"custom:titleText="微信"custom:titleTextColor="#ffffff"custom:titleTextSize="5dp" ></cn.lixyz.customviewdemo.MyCustomTitleBar><cn.lixyz.customviewdemo.MyCustomTitleBarandroid:layout_width="wrap_content"android:layout_height="30dp"android:layout_marginTop="10dp"custom:titleText="发现"custom:titleTextColor="#ffffff"custom:titleTextSize="5dp" ></cn.lixyz.customviewdemo.MyCustomTitleBar><cn.lixyz.customviewdemo.MyCustomTitleBarandroid:layout_width="wrap_content"android:layout_height="30dp"android:layout_marginTop="10dp"custom:titleText="我"custom:titleTextColor="#ffffff"custom:titleTextSize="5dp" ></cn.lixyz.customviewdemo.MyCustomTitleBar></LinearLayout>

一定要在布局中引入我们的命名空间

  格式为:xmlns:自定义名称="http://schemas.android.com/apk/res/包名"
  因为只有引入了我们的命名空间,才可以使用xxx:xxx格式来设置我们定义的属性,我们平时使用的android:xx也是因为上面的xmlns:android="http://schemas.android.com/apk/res/android"
  这样运行一下软件查看效果

      为按钮设置点击事件

观察我们平时为按钮设置点击事件时候的方法:

bt.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stub
                }});

我们通过按钮的setOnClickListener方法传入一个匿名内部类OnClickListener为按钮设置点击事件,我们查看OnClickListener的介绍

    /*** Interface definition for a callback to be invoked when a view is clicked.*/public interface OnClickListener {/*** Called when a view has been clicked.** @param v The view that was clicked.*/void onClick(View v);}

  

我们也可以仿照这个形式,为我们的MyCustomTieleBar设置一个setCustomTitleBarListener,然后传入一个内部类来让这个按钮的点击调用这个类的click方法

修改MyCustomTitleBar:

package cn.lixyz.customviewdemo;import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.TextView;@SuppressLint("NewApi")
public class MyCustomTitleBar extends RelativeLayout {// 定义自定义控件包含的组件private TextView title;private ImageButton button;// 定义控件的属性private String titleText;private float titleTextSize;private int titleTextColor;private Drawable titleButtonImage;// 为每个控件定义LayoutParamsprivate LayoutParams textLayoutParams;private LayoutParams buttonLayoutParams;private customTitleBarListener listener;public interface customTitleBarListener {public void click();}public void setCustomTitleBarListener(customTitleBarListener listener) {this.listener = listener;}public MyCustomTitleBar(Context context, AttributeSet attrs) {super(context, attrs);// 获取我们定义的属性TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyCustomTitleBar);titleText = array.getString(R.styleable.MyCustomTitleBar_titleText);titleTextColor = array.getColor(R.styleable.MyCustomTitleBar_titleTextColor, 0);titleTextSize = array.getDimension(R.styleable.MyCustomTitleBar_titleTextSize, 10);titleButtonImage = array.getDrawable(R.styleable.MyCustomTitleBar_titleButtonImage);// 回收,以防出错
        array.recycle();// 新建包含的子组件title = new TextView(context);button = new ImageButton(context);// 为子组件赋值
        title.setText(titleText);title.setTextColor(titleTextColor);title.setTextSize(titleTextSize);button.setBackground(titleButtonImage);// 设置背景色setBackgroundColor(0xFF38373c);// 设置包含控件的属性并添加到view中textLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);textLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);addView(title, textLayoutParams);buttonLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);buttonLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);addView(button, buttonLayoutParams);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {listener.click();}});}
}

  这样我们在MainActivity中就可以为按钮设置点击事件了

package cn.lixyz.customviewdemo;import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;public class MainActivity extends Activity {private MyCustomTitleBar addressListBar, wechatBar;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button bt = new Button(this);bt.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stub
                }});addressListBar = (MyCustomTitleBar) findViewById(R.id.addressListBar);wechatBar = (MyCustomTitleBar) findViewById(R.id.wechatBar);addressListBar.setCustomTitleBarListener(new MyCustomTitleBar.customTitleBarListener() {@Overridepublic void click() {Toast.makeText(MainActivity.this, "通讯录按钮被点击", Toast.LENGTH_SHORT).show();}});wechatBar.setCustomTitleBarListener(new MyCustomTitleBar.customTitleBarListener() {@Overridepublic void click() {Toast.makeText(MainActivity.this, "微信按钮被点击", Toast.LENGTH_SHORT).show();}});}}

 
 

转载于:https://www.cnblogs.com/xs104/p/5077406.html

Android笔记(六十七) 自定义控件相关推荐

  1. 前端入门学习笔记六十七

    <!DOCTYPE html> <html><head><meta charset="utf-8"><title>CSS ...

  2. GEE学习笔记 六十七:【GEE之Python版教程一】GEE学习背景介绍

    相信很多人都对GEE已经比较熟悉了(只是不熟悉GEE的Python的API而已),这里只是做一个简单的总结概括一下GEE相关内容. 1.GEE学习基本要求 目前市面上无论出现什么新的技术,总会出现一种 ...

  3. Android开发六年收获阿里offer定级P7,多亏在阿里P8师兄给的攻略、面试技巧以及学习笔记!!!

    前言 又到了每年的毕业季,应届毕业生在找工作过程对于简历设计和面试技巧有一定的欠缺,这对于求职是比较重要的两个因素,因此掌握一定的面试技巧对于找互联网技术岗位的工作帮助非常大.本篇文章给大家分享一波职 ...

  4. OpenCV学习笔记(十六)——CamShift研究 OpenCV学习笔记(十七)——运动分析和物体跟踪Video OpenCV学习笔记(十八)——图像的各种变换(cvtColor*+)imgproc

    OpenCV学习笔记(十六)--CamShift研究 CamShitf算法,即Continuously Apative Mean-Shift算法,基本思想就是对视频图像的多帧进行MeanShift运算 ...

  5. Android开发笔记(十七)GIF动画的实现GifAnimation

    GIF在Windows上是常见的图片格式,主要用来播放短小的动画.但在手机上由于系统资源紧张,所以Android并没有直接支持GIF格式,如果在ImageView中放入一张gif文件,你会发现显示出来 ...

  6. 【Visual C++】游戏开发笔记二十七 Direct3D 11入门级知识介绍

    游戏开发笔记二十七 Direct3D 11入门级知识介绍 作者:毛星云    邮箱: happylifemxy@163.com    期待着与志同道合的朋友们相互交流 上一节里我们介绍了在迈入Dire ...

  7. android api版本 闪退_经验分享:从事 Android 开发六年,我学到的那些事

    你的代码质量应该随着经验的增加而提高,在本文作者基于 Android 开发者六年间,其都学到了什么? 以下为译文: 六年来,我为多家公司编写过各种应用程序.你编写代码或处理代码库的文化和方式会随着你的 ...

  8. 深度学习入门笔记(十七):深度学习的极限在哪?

    欢迎关注WX公众号:[程序员管小亮] 专栏--深度学习入门笔记 声明 1)该文章整理自网上的大牛和机器学习专家无私奉献的资料,具体引用的资料请看参考文献. 2)本文仅供学术交流,非商用.所以每一部分具 ...

  9. 【CS231n】斯坦福大学李飞飞视觉识别课程笔记(十七):神经网络笔记3(下)

    [CS231n]斯坦福大学李飞飞视觉识别课程笔记 由官方授权的CS231n课程笔记翻译知乎专栏--智能单元,比较详细地翻译了课程笔记,我这里就是参考和总结. [CS231n]斯坦福大学李飞飞视觉识别课 ...

最新文章

  1. 计算机php外文翻译,php外文翻译.doc
  2. correlation 蒙特卡洛_蒙特卡洛模拟法及其Matlab案例
  3. 20165303实验一 Java开发环境的熟悉
  4. c语言如果读不到数据就跳过,4,VS常见问题解决(一闪而过、等问题)不断更新...
  5. ajax 中文乱码问题 主要是IE浏览器
  6. Linux 启/关 自启动服务
  7. android里canvas视频帧,移动端用canvas截取视频封面,如何不截取第一帧,而是截取其它的帧?...
  8. 全网最新Redis结合Kaptcha实现验证码功能篇一(前后端分离)
  9. Javascript特效:一个不停的表盘
  10. Python 基础测试题(含答案)
  11. mybatisplus代码生成器
  12. 短视频直播行业服务器选择
  13. 使用Python横向合并excel文件的实例
  14. 数据分析——数据指标
  15. scp 给ipv6_scp传输常用命令
  16. 【独行秀才】macOS Big Sur 11.5 Beta3版(20G5042c)原版镜像
  17. MyEclipse 2014 破解失败,cracker.jar文件打开闪退
  18. php利用phpqrcode生成二维码,并将二维码盖在一张图上实现美化
  19. 基于Java的旅行管理系统的设计与实现
  20. 安徽大学计算机专业参考书目,安徽大学计算机科学与技术(专业学位)研究生考试科目和考研参考书目...

热门文章

  1. USB device如何进入suspend模式
  2. 康美药业财务造假给股民造成的损失,股民该怎么办?
  3. keras的学习笔记
  4. 月息2%的贷款算高利贷吗?
  5. Ubuntu 14.04 LTS 下升级 gcc 到 gcc-4.9、gcc-5 版本
  6. C语言中字符型和浮点型能否相加,C语言中数据结构的基本类型(整型、浮点型和字符型)...
  7. linux传输文件scp自动接密码,配置scp在Linux或Unix之间传输文件无需密码
  8. java同步转化成异步_Java 如何把异步调用模拟成同步调用
  9. 艾为数字ic面试题_每日学习:数字后端面试100问(2019全新版)
  10. java changestr,java change