前言

  Android提供了丰富的控件,但是有时候还是不能满足自己的需求,这时候就需要自定义视图了,自定义视图分为几种,一种为继承为View的,一种为继承于ViewGroup的。继承于View的需要我们自己去绘制控件,继承于ViewGroup的可以组织已有的控件,下面就先介绍下继承于View的情况。

效果图

  下面就是自定义了一个简单的圆形图来介绍整个的绘制过程,如下所示

  aaarticlea/png;base64,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y0ZQb+GjKS2rwrzy5pR+8URNKue1dmef2B8VpF7GxrRR1PvJBCu6tKwL88r+8JAzrf1PT4oLurigb33Eyxi7fiOo13ungxUdfDHFz+cvw3Be6+KiDlZMadE4r6mXsbFsNL+N3XmjvVljXl2EOqWcN9qfc5zX/DI6xsY1/hUyxqSOehmTOuplTOqolzGpo17GpI56GZM66mVM6qiXMambeAJAJuoFpJpofm0yxiRuIgEg00Sapulpev6/jLGHtqttXjQ7YX8fGmNM3Cbyszw/yzMAEvRrzc/y83oZY+I2kZ8N/KOdg/8N4KE5G/jfPJ+4vxsC4E6oF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpblZv+Uv5AW5Mdw3wwFEvINXfrjefmBga9QK3M/Z6r+Z6/agX+ENjrPem3d664THdNcADN5Z679LtLQIe010DPHCjr3ck6d6o4THdNcADN+J6R5vuHwY8prsGeOBGVu84uv3Dhsd01wAP3GjqHXe61wc8prsGeOCoF5BqBPX+nXSvCXhMdw3wwN213r+Z7q8CHtNdAzxwd6r376dLvUCfvHqvBjymuwZ44G5f732lezXgMd01wANHvYBUt6z3ftMdCnhMdw3wwFEvIBX1AlJRLyAV9QJS3abee+92KOAx3TXAA0e9gFTUC0hFvYBU1AtIRb2AVHzHCJCKegGpqBeQinoBqagXkIqfzgekol5AKn4rHSCVvHqHbgP14tHit7EDUvEvoQBS8a+QAVJRLyAV//o2INXI6h1fw7+/UuBRGnG9Iw/4j64ReJRGX++oAv7D66JePFpjqffuDd/sioBHaYz13q7h21wF8CiNvd7fxjyCywQepb9d7zg2prsGeOCoF5DqZvUCeDioF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6Aan+A3BrsqnlXz9RAAAAAElFTkSuQmCC" alt="" />

概述

  绘制一个控件需要绘制两部分内容,一是尺寸,二是内容,这通过两个方法来进行绘制,一个是onMeasure、一个是onDraw,整体结构如下所示

  

 public class CustomView extends View {

     public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
//绘制内容
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
//计算尺寸大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} }

onMeasure

  这个函数用来计算控件的大小尺寸,尺寸这个地方有一个概念为绘制模式

  MeasureSpec.AT_MOST:父元素指定控件最大达到的尺寸,通过设定为wrap_content为此模式

  MeasureSpec.EXACTLY:父元素指定控件精确的大小,比如设置为100dip,或者match_parent为此模式

  MeasureSpec.UNSPECIFIED:父元素不控制控件的大小,其大小完全由内部控制

  这个模式,可以通过int mode = MeasureSpec.getMode(widthMeasureSpec);方法来获取模式。

  等计算好大小后,通过setMeasuredDimension(width, height);方法来设置宽高

onDraw

  这个函数用来绘制控件的内容,这个函数传入了一个Canvas对象,这个是当前的Canvas对象,把需要绘制的内容绘制到这个Canvas上即可,可以通过Canvas中的drawCircle、drawLine、drawText等方法来绘制内容,如果需要设定笔线内容,通过paint对象来设定

源码

  Java

  

 public class CustomView extends View {

     int height=0,width=0;
private int cx; //圆心x
private int cy; //圆心y
private int padding=5; //控件边距 public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//计算圆心位置、半径
cx = width/2;
cy = height/2;
int radius = cx>cy?cy:cx; Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawCircle(cx, cy, radius, paint);
canvas.drawColor(Color.GRAY);
}
//计算尺寸大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); widthMeasureSpec = MeasureSpec.getSize(widthMeasureSpec);
heightMeasureSpec = MeasureSpec.getSize(heightMeasureSpec);
//计算宽度
int mode = MeasureSpec.getMode(widthMeasureSpec);
if(mode==MeasureSpec.EXACTLY){
width = widthMeasureSpec + padding;
}else{
width = widthMeasureSpec;
} //计算高度
mode = MeasureSpec.getMode(heightMeasureSpec);
if(mode==MeasureSpec.EXACTLY){
height = heightMeasureSpec + padding;
}else{
height = heightMeasureSpec;
}
setMeasuredDimension(width, height);
} }

  布局文件

  

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
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=".MainActivity" > <com.example.customview.CustomView
android:id="@+id/customView1"
android:layout_width="50dip"
android:layout_height="50dip"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
/> </RelativeLayout>

后记

  这篇文章主要是说了下绘制的一个整体过程,实现的功能比较简单,但是再复杂的内容其原理是相同的,通过这个过程可以发挥想象力来绘制控件,关于通过组合控件来进行绘制的情况再下篇文章中进行叙述。

原文地址:http://www.cnblogs.com/luoaz/p/3980651.html

  

自定义视图(继承View)的更多相关文章

  1. 自定义控件(视图)2期笔记10:自定义视图之View事件分发机制("瀑布流"的案例)

    1. Touch事件的传递:   图解Touch事件的传递,如下: 当我们点击子View 02内部的Button控件时候,我们就触发了Touch事件. • 这个Touch事件首先传递给了顶级父View ...

  2. 自定义控件(视图)2期笔记14:自定义视图之View事件分发 dispatchTouchEvent,onTouch,onTouchEvent,onClick逻辑顺序过程

    1. 这里我们先从案例角度说明dispatchTouchEvent,onTouch,onTouchEvent,onClick逻辑顺序过程: (1)首先我们重写一个MyButton 继承自 Button ...

  3. UI 自定义视图 ,视图管理器

    一>自定义label - textField 视图 自定义视图:系统标准UI之外,自己组合而出的新的视图 iOS 提供了很多UI组件 ,借助它们,我们可以做各种程序 尽管如此,实际开发中,我们还 ...

  4. SpringMVC(二七) 自定义视图

    可以参考博客http://www.cnblogs.com/parryyang/p/5683600.html,举例很清晰. 对自定义的视图名称匹配不同的解析器进行解析. 作用:自己定义视图,视图继承vi ...

  5. 自定义View 一 (继承VIew重写onDraw方法)

    项目:具有圆形效果的自定义View 一.继承View并重写onDraw方法 public class CircleView extends View{ private static final int ...

  6. Android中的自定义视图控件

    简介 当现有控件不能满足需求时,就需要自定义控件. 自定义控件属性 自定义控件首先要继承自View,重写两个构造函数. 第一个是代码中使用的: public MyRect(Context contex ...

  7. 自定义视图引擎,实现MVC主题快速切换

    一个网站的主题包括布局,色调,内容展示等,每种主题在某些方面应该或多或少不一样的,否则就不能称之为不同的主题了.每一个网站至少都有一个主题,我这里称之为默认主题,也就是我们平常开发设计网站时的一个固定 ...

  8. (翻译)为你的MVC应用程序创建自定义视图引擎

    Creating your own MVC View Engine For MVC Application 原文链接:http://www.codeproject.com/Articles/29429 ...

  9. 自定义视图一:扩展现有的视图,添加新的XML属性

    这个系列是老外写的,干货!翻译出来一起学习.如有不妥,不吝赐教! 简介 这个系列详细的介绍了如何穿件Android自定义视图.主要涉及的内容有如何绘制内容,layout和measure的原理,如何继承 ...

随机推荐

  1. 让ConfigurationManager打开任意的配置文件

    VisualStudio的配置文件很好很强大,用来保存数据库连接字符串或键值对都非常方便,只需要通过ConfigurationManager的ConnectionStrings或AppSettings ...

  2. JavaScript中数组操作

    var arr1=new Array(); arr1.push(1);//在数组的中末尾添加元素,并返回新的长度 arr1.push(2);//在数组的中末尾添加元素,并返回新的长度 arr1.pop ...

  3. Boost.Any

    支持类型安全地存储和获取任意类型的值 #include <list> #include <boost/any.hpp> #include <string> #inc ...

  4. 【Shell脚本学习13】Shell数组:shell数组的定义、数组长度

    Shell在编程方面比Windows批处理强大很多,无论是在循环.运算. bash支持一维数组(不支持多维数组),并且没有限定数组的大小.类似与C语言,数组元素的下标由0开始编号.获取数组中的元素要利 ...

  5. HDU 1875 畅通工程再续 (最小生成树)

    畅通工程再续 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  6. WPF全球化与本地化 (二)

    Visual Baml Visual Locbaml is a free and open-source software to simplify the task of WPF applicatio ...

  7. 考上好大学,然后进入IT行业是穷人孩子晋级中产的唯一出路?

    今天看到一篇不错的文章,内容如下: 这个问题来自于我在知乎上参与的一个热贴讨论,作为一个10年的老码农,创业公司呆过,二.三流的互联网公司混过,BAT也遛了一趟,如今再次回归创业,经历算得上狗血了,看 ...

  8. disucz!NT 3.5.0 验证码点击不能变化只是样式变化

    来博客园这么久了,第一次写博客啊!公司有个论坛10年没动了,是discuz!NT 3.5.0版本的,由于验证码不能变化老是被人刷.网上找了很多资料根本没有.可能有同行下次也会遇到这样的问题,我就把我的 ...

  9. onclick和onblur的冲突问题

    新浪首页的搜索框里面有一个使用ajax的下拉框.我们需要实现一个点击下拉框里面的一项,让搜索框里面的值变成这一项,同时下拉框消失的效果,但同时在点击其他地方的时候,这个下拉框也要消失.大致如图: 我们 ...

  10. 微信公众号与HTML 5混合模式揭秘2——分享手机相册中照片

    本书是分享微信jssdk开发的第二篇.     4.2.1 项目需求 需求说明:实现微信端的手机用户,点击按钮选取1张图片,分享到朋友圈. 4.2.2 需求分解 通过对需求的了解,可以将其分解为: ( ...