开发自定义控件的步骤:
1、了解View的工作原理 
2、 编写继承自View的子类
3、 为自定义View类增加属性 
4、 绘制控件 
5、 响应用户消息 
6 、自定义回调函数 
一、View结构原理
Android系统的视图结构的设计也采用了组合模式,即View作为所有图形的基类,Viewgroup对View继承扩展为视图容器类。
View定义了绘图的基本操作
基本操作由三个函数完成:measure()、layout()、draw(),其内部又分别包含了onMeasure()、onLayout()、onDraw()三个子方法。具体操作如下:
1、measure操作
measure操作主要用于计算视图的大小,即视图的宽度和长度。在view中定义为final类型,要求子类不能修改。measure()函数中又会调用下面的函数:
(1)onMeasure(),视图大小的将在这里最终确定,也就是说measure只是对onMeasure的一个包装,子类可以覆写onMeasure()方法实现自己的计算视图大小的方式,并通过setMeasuredDimension(width, height)保存计算结果。
2、layout操作
layout操作用于设置视图在屏幕中显示的位置。在view中定义为final类型,要求子类不能修改。layout()函数中有两个基本操作:
(1)setFrame(l,t,r,b),l,t,r,b即子视图在父视图中的具体位置,该函数用于将这些参数保存起来;
(2)onLayout(),在View中这个函数什么都不会做,提供该函数主要是为viewGroup类型布局子视图用的;
3、draw操作
draw操作利用前两部得到的参数,将视图显示在屏幕上,到这里也就完成了整个的视图绘制工作。子类也不应该修改该方法,因为其内部定义了绘图的基本操作:
(1)绘制背景;
(2)如果要视图显示渐变框,这里会做一些准备工作;
(3)绘制视图本身,即调用onDraw()函数。在view中onDraw()是个空函数,也就是说具体的视图都要覆写该函数来实现自己的显示(比如TextView在这里实现了绘制文字的过程)。而对于ViewGroup则不需要实现该函数,因为作为容器是“没有内容“的,其包含了多个子view,而子View已经实现了自己的绘制方法,因此只需要告诉子view绘制自己就可以了,也就是下面的dispatchDraw()方法;
(4)绘制子视图,即dispatchDraw()函数。在view中这是个空函数,具体的视图不需要实现该方法,它是专门为容器类准备的,也就是容器类必须实现该方法;
(5)如果需要(应用程序调用了setVerticalFadingEdge或者setHorizontalFadingEdge),开始绘制渐变框;
(6)绘制滚动条;
从上面可以看出自定义View需要最少覆写onMeasure()和onDraw()两个方法。
二、View类的构造方法
创建自定义控件的3种主要实现方式:
1)继承已有的控件来实现自定义控件: 主要是当要实现的控件和已有的控件在很多方面比较类似, 通过对已有控件的扩展来满足要求。
2)通过继承一个布局文件实现自定义控件,一般来说做组合控件时可以通过这个方式来实现。
注意此时不用onDraw方法,在构造广告中通过inflater加载自定义控件的布局文件,再addView(view),自定义控件的图形界面就加载进来了。
3)通过继承view类来实现自定义控件,使用GDI绘制出组件界面,一般无法通过上述两种方式来实现时用该方式。
三、自定义View增加属性的两种方法:
1)在View类中定义。通过构造函数中引入的AttributeSet 去查找XML布局的属性名称,然后找到它对应引用的资源ID去找值。
案例:实现一个带文字的图片(图片、文字是onDraw方法重绘实现)
public class MyView extends View {private String mtext;private int msrc;public MyView(Context context) {super(context);}public MyView(Context context, AttributeSet attrs) {super(context, attrs);int resourceId = 0;int textId = attrs.getAttributeResourceValue(null, "Text",0);int srcId = attrs.getAttributeResourceValue(null, "Src", 0);mtext = context.getResources().getText(textId).toString();msrc = srcId;}@Overrideprotected void onDraw(Canvas canvas) {Paint paint = new Paint();paint.setColor(Color.RED);InputStream is = getResources().openRawResource(msrc); Bitmap mBitmap = BitmapFactory.decodeStream(is);int bh = mBitmap.getHeight();int bw = mBitmap.getWidth();canvas.drawBitmap(mBitmap, 0,0, paint);//canvas.drawCircle(40, 90, 15, paint);canvas.drawText(mtext, bw/2, 30, paint);}
}

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><com.example.myimageview2.MyViewandroid:id="@+id/myView1"android:layout_width="wrap_content"android:layout_height="wrap_content" Text="@string/hello_world"Src="@drawable/xh"/></LinearLayout>

属性Text, Src在自定义View类的构造方法中读取。

2)通过XML为View注册属性。与Android提供的标准属性写法一样。
案例:  实现一个带文字说明的ImageView (ImageView+TextView组合,文字说明,可在布局文件中设置位置)
public class MyImageView extends LinearLayout {public MyImageView(Context context) {super(context);}public MyImageView(Context context, AttributeSet attrs) {super(context, attrs);int resourceId = -1;TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.MyImageView);ImageView iv = new ImageView(context);TextView tv = new TextView(context);int N = typedArray.getIndexCount();for (int i = 0; i < N; i++) {int attr = typedArray.getIndex(i);switch (attr) {case R.styleable.MyImageView_Oriental:resourceId = typedArray.getInt(R.styleable.MyImageView_Oriental, 0);this.setOrientation(resourceId == 1 ? LinearLayout.HORIZONTAL: LinearLayout.VERTICAL);break;case R.styleable.MyImageView_Text:resourceId = typedArray.getResourceId(R.styleable.MyImageView_Text, 0);tv.setText(resourceId > 0 ? typedArray.getResources().getText(resourceId) : typedArray.getString(R.styleable.MyImageView_Text));break;case R.styleable.MyImageView_Src:resourceId = typedArray.getResourceId(R.styleable.MyImageView_Src, 0);iv.setImageResource(resourceId > 0 ?resourceId:R.drawable.ic_launcher);break;   }}addView(iv);addView(tv);typedArray.recycle();}
}

attrs.xml进行属性声明, 文件放在values目录下

<?xml version="1.0" encoding="utf-8"?>
<resources><declare-styleable name="MyImageView"><attr name="Text" format="reference|string"></attr><attr name="Oriental" ><enum name="Horizontal" value="1"></enum><enum name="Vertical" value="0"></enum></attr><attr name="Src" format="reference|integer"></attr></declare-styleable></resources>

MainActivity的布局文件:先定义命名空间 xmlns:uview="http://schemas.android.com/apk/res/com.example.myimageview2" (com.example.myimageview2为你
在manifest中定义的包名)
然后可以像使用系统的属性一样使用:uview:Oriental="Vertical"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:uview="http://schemas.android.com/apk/res/com.example.myimageview2"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity" ><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/hello_world" /><com.example.myimageview2.MyImageViewandroid:id="@+id/myImageView1"android:layout_width="wrap_content"android:layout_height="wrap_content"uview:Text="这是一个图片说明" uview:Src="@drawable/tw"uview:Oriental="Vertical"></com.example.myimageview2.MyImageView></LinearLayout>

四、控件绘制 onDraw()
五、

六:自定义View的方法

onFinishInflate() 回调方法,当应用从XML加载该组件并用它构建界面之后调用的方法
onMeasure() 检测View组件及其子组件的大小
onLayout() 当该组件需要分配其子组件的位置、大小时
onSizeChange() 当该组件的大小被改变时
onDraw() 当组件将要绘制它的内容时
onKeyDown 当按下某个键盘时
onKeyUp  当松开某个键盘时
onTrackballEvent 当发生轨迹球事件时
onTouchEvent 当发生触屏事件时
onWindowFocusChanged(boolean)  当该组件得到、失去焦点时
onAtrrachedToWindow() 当把该组件放入到某个窗口时
onDetachedFromWindow() 当把该组件从某个窗口上分离时触发的方法
onWindowVisibilityChanged(int): 当包含该组件的窗口的可见性发生改变时触发的方法

[Android自定义控件] Android自定义控件相关推荐

  1. Android开发技巧——自定义控件之自定义属性

    Android开发技巧--自定义控件之自定义属性 掌握自定义控件是很重要的,因为通过自定义控件,能够:解决UI问题,优化布局性能,简化布局代码. 上一篇讲了如何通过xml把几个控件组织起来,并继承某个 ...

  2. Android开发技巧——自定义控件之组合控件

    Android开发技巧--自定义控件之组合控件 我准备在接下来一段时间,写一系列有关Android自定义控件的博客,包括如何进行各种自定义,并分享一下我所知道的其中的技巧,注意点等. 还是那句老话,尽 ...

  3. Android开发之自定义控件——直尺

    Android开发之自定义控件--直尺 本人的第一篇技术博客,希望能够在分享的路上走的更远. 先上效果图: 涉及到的知识点: - Paint类 - Cancas类 - Path类 * 由于功能简单,此 ...

  4. Android开发之自定义控件的基本介绍(附源码)

    老套路先看效果图: 一个特别简单的字母排序列表如上图: 先看下有哪些属性: <com.xiayiye.honorfirst.custom.CustomNumViewandroid:id=&quo ...

  5. 【Android】Android开源项目分类汇总

    第一部分 个性化控件(View) 主要介绍那些不错个性化的View,包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.Pro ...

  6. android之android.intent.category.DEFAULT的用途和使用

    1.要弄清楚这个问题,首先需要弄明白什么是implicit(隐藏) intent什么是explicit(明确) intent. Explicit Intent明确的指定了要启动的Acitivity , ...

  7. android:layout_with=,android – 难以理解layout_alignWithParentIfMissing

    这仅适用于使用RelativeLayout时. 如果您将元素设置为一个其他元素,则表示该元素位于该元素的左侧. 但是如果这个元素会丢失,因为你删除它,例如它将与父对齐. 举个例子 android:la ...

  8. [Android Studio] Android Studio常用快捷键

    [Android Studio] Android Studio常用快捷键 (会持续更新)这边讲的常用快捷键是指做完Keymap到Eclipse后的,不是纯Android Studio的,这边主要讲下比 ...

  9. Android利用android:indeterminateDrawable来实现ProgressBar三种方式

    方式1:(效果为补间动画一样) [html] view plaincopyprint? <ProgressBar android:layout_width="wrap_content& ...

  10. Android之Android实现浮层的上下滑动(支持内部添加View)

    前言 我K,今天居然是情人节,对于资深的单身狗来说,简直是个噩耗,今天注定是各种秀恩爱,心塞中.... 话题到此结束,管他什么情人节,今天给大家带来的是一个浮层的上下滑动,浮层滑动时分三种状态:全部显 ...

最新文章

  1. 针对OAuth2的CSRF攻击
  2. [Egret]长按截屏分享、分享截屏图片、本地存储
  3. How To Do @Async in Spring--转
  4. 2011年c语言二级计算机考试,2011年9月全国计算机等级考试二级C语言机试
  5. “埋点”到底要不要?
  6. erlang rebar 配置mysql_Erlang Rebar 使用指南之四:依赖管理
  7. Libevent初探
  8. Spring Boot笔记-WebSocket的使用
  9. 在linux上安装jenkins
  10. 如何启动php程序下载,php – 最好的方式来启动下载?
  11. 原生JavaScript如何解决父元素查找指定类名的子元素的问题
  12. windows server 2012 动态访问控制
  13. 网络摄像机 c++ 抓拍_IP摄像机和工业摄像机怎么区分 IP摄像机和工业摄像机差异...
  14. oracle asm文件查找,Oracle ASM 文件管理
  15. 微信小程序:最新掌上题库微信小程序源码下载,修复登录接口,支持在线考试,自定义导入考题
  16. Autodesk Maya入门到精通学习教程
  17. SPL工业智能:发现时序数据的异常
  18. StringBuffer(史上最详细)
  19. 学习笔记:使用endnotesX9插入参考文献
  20. Y Combinator Is Boot Camp for Startups

热门文章

  1. 如何以CustomValidator搭配jQuery AJAX进行Server端验证(转)
  2. 牛客多校第九场H Cutting Bamboos(主席树 区间比k小的个数)题解
  3. Box,( UVa, 1587 )
  4. 大话机器学习之数据预处理与数据筛选
  5. hdu 1520(树形dp)
  6. 深入Linux内核架构(中文版)pdf
  7. 来教你用什么泡脚好,泡脚的好处有那些?
  8. Could not find an NgModule. Use the skip-import option to skip importing in NgModule.
  9. uoj#422. 【集训队作业2018】小Z的礼物(MIn-Max容斥+插头dp)
  10. 使用 profile 进行python代码性能分析