自定义View入门 --转载自武老师博客160303
原文地址:http://blog.csdn.net/risky78125/article/details/50609538
自定义View入门
long time no see,这次写一个灰常简单的一个自定义的view.当然,虽然说简单,但是麻雀虽小五脏俱全,自定义view的流程基本涵盖了.
从简单入手,然后大致了解一下view的绘制过程.这个view有多简单呢,实际上咱们就画一个圆,然后上个色.
下面开始:
public class CircleView extends View {private static final String TAG = "CircleView"; /*** 定义一个默认的圆形颜色*/private static final int DEFAULT_COLOR = Color.GRAY; /*** 圆形的颜色*/private int color = DEFAULT_COLOR; /*** 画笔*/private Paint mPaint; public CircleView(Context context) { this(context, null);} public CircleView(Context context, AttributeSet attrs) { this(context, attrs, 0);} public CircleView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr);initPaint();} private void initPaint() { // 设置画笔抗锯齿,可以让图形的边缘更平滑.如果需要画的图形四四方方的那就没必要设置了mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); // 设置画笔的颜色mPaint.setColor(color);} @Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); // 获取控件本身的宽和高,并选择较短的一边的一半作为圆的半径int width = getWidth(); int height = getHeight(); int radius = Math.min(width, height) / 2; // 画圆,前两个参数确定圆心的位置,之后圆的半径,画笔canvas.drawCircle(width / 2, height / 2, radius, mPaint);}
}123456789101112131415161718192021222324252627282930313233343536373839404142434445
很简单吧,那么看一下布局文件
<?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:padding="10dp"android:orientation="vertical"><com.lanou3g.drawview.widget.CircleView android:layout_width="wrap_content"android:layout_height="wrap_content"/></LinearLayout>12345678910111213
布局也非常简单对吧,那好,看一下预览,还算是正常的吧
那好,接下来,咱们自定义一下这个圆圈的颜色,也就是需要在布局中有一条属性,可以控制这个view的颜色.
创建自定义属性文件,在res/values下,创建一个资源文件,命名为attrs,如下图:
文件里面就可以创建自定义的属性,继续贴代码:
<?xml version="1.0" encoding="utf-8"?><resources><!--一般来说,为某个控件自定义属性,name就跟控件名字一样--><declare-styleable name="CircleView"><!--定义一条属性叫circleColor,规定参数填颜色值--><attr name="circleColor" format="color"/></declare-styleable></resources>12345678
属性定义好了,就可以到代码中把颜色值取出,然后设置给画笔就可以了,继续代码
public class CircleView extends View {/** 这部分代码与上文一样,省略... */public CircleView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // 获取自定义属性TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleView); // 取出对应的值设置给color,并提供一个默认值color = a.getColor(R.styleable.CircleView_circleColor, DEFAULT_COLOR);initPaint();} private void initPaint() { // 设置画笔抗锯齿,可以让图形的边缘更平滑.如果需要画的图形四四方方的那就没必要设置了mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); // 设置画笔的颜色mPaint.setColor(color);} /** 画圆部分与上文一样,省略 */}12345678910111213141516171819
自定义的属性获取就写完了.然后在布局文件中,设置命名空间,目的为可以获取到自定义的属性,然后在CircleView中使用自定义的属性为圆上色.当然,命名空间的名字我写的是view,这个可以根据自己的爱好命名.
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:view="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="10dp"android:orientation="vertical"><com.lanou3g.drawview.widget.CircleView android:layout_width="wrap_content"android:layout_height="wrap_content"view:circleColor="#0088ff"/></LinearLayout>123456789101112131415
ok,看预览,可以看到颜色咱们可以自定义了
实 际上这个自定义的控件是灰常不专业的,不知道大家注意到没有.咱们在布局文件中给这个控件设置的宽高都为wrap_content,那显示成这么大肯定是 不正常的.实际上虽然给的是wrap_content,但是系统是按照match_parent来计算的.那为什么会出现这种情况呢?给10秒钟大家思考 一下
try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}12345
思考完了吧,那记住一句话就得了,对于直接继承自view的自定义组件,如果不在代码中对wrap_content进行处理,那么系统就会把它理解成match_parent,呵呵哒,气人不.
那接下来,咱们就处理一下吧.在自定义组件中,重写onMeasure()这个方法,处理的过程就在此方法中.思路就是,如果布局中的宽或高设置成了wrap_content,那么对应的宽高就给设置成188.
/** 其他部分的代码省略 */@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST){setMeasuredDimension(188,188);}else if (widthMode == MeasureSpec.AT_MOST){setMeasuredDimension(188,heightSize);}else if (heightMode == MeasureSpec.AT_MOST){setMeasuredDimension(widthSize,188);}}12345678910111213141516
接下来再看一下预览(PS:Android Studio真是个好东西)
<com.lanou3g.drawview.widget.CircleViewandroid:layout_width="match_parent"android:layout_height="wrap_content"view:circleColor="#0088ff"/>1234
接下来另一个问题,写到现在这个程度的时候,大家可以试一下给这个控件加上margin属性和padding属性,看一下效果,给大家半个小时尝试一下
try {Thread.sleep(30 * 60 * 1000);} catch (InterruptedException e) {e.printStackTrace();}12345
擦擦擦
/** Application Not Responding !!!!! */1
实 际结果是,margin是生效的,而padding是不会生效的.因为margin属性是由父容器控制的,所以会生效.而padding是控件本身控制 的,咱们没有进行处理,所有是无效的.那么接下来,继续处理一下padding.处理的过程也非常简单,在绘制的过程中,考虑一下padding即可.那 么修改一下onDraw方法,如下:
@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); // 获取padding值int paddingLeft = getPaddingLeft(); int paddingRight = getPaddingRight(); int paddingTop = getPaddingTop(); int paddingBottom = getPaddingBottom(); // 获取控件本身的宽和高,并选择较短的一边的一半作为圆的半径.计算时将padding考虑进去int width = getWidth() - paddingLeft - paddingRight; int height = getHeight() - paddingTop - paddingBottom; int radius = Math.min(width, height) / 2; // 画圆,前两个参数确定圆心的位置,之后圆的半径,画笔canvas.drawCircle(paddingLeft + width / 2, paddingTop + height / 2, radius, mPaint);}123456789101112131415
布局文件
<com.lanou3g.drawview.widget.CircleViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="30dp"android:paddingTop="5dp"android:paddingBottom="20dp"view:circleColor="#0088ff"/>1234567
预览
转载于:https://my.oschina.net/u/2531415/blog/639721
自定义View入门 --转载自武老师博客160303相关推荐
- 基于Android自带插入器的图形波动效果 --转载自李硕老师博客160303
原文地址:http://blog.csdn.net/u012215170/article/details/50598747 对于Android的各种动画我们并不陌生,但是可能很多同学不知道Interp ...
- codewarrior 入门(来源于逍遥呤博客)
codewarrior 入门(来源于逍遥呤博客) (2009-08-08 12:12:15) 转载 标签: 杂谈 分类: ARM系列 1.首先是要建立工程,new->ARM Executable ...
- 【学术】我读科学网“马臻”老师博客体会
从知乎看到有博士提到马臻老师博客,便去关注了一下.看了一上午,摘录一些自己有感觉的句子吧. 1. 心中一杆秤 我看,无论别人怎么做,我们自己心中应该自有一杆秤. 一个美国参议院对热切期望踏入政界的年轻 ...
- python 等高线地图图片转 tin_由等高线生成TIN并由TIN生成坡度图【解决中文环境翻译差别的问题】(转载请注明出自博客园)...
由等高线等生成TIN并生成坡度图的代码.在softline代码段对错误信息作了处理,不再使用"软线","软性线","柔性线","软 ...
- MD5算法在PB中的实现(转载自 - 阿多米 - 博客园)
MD5算法在PB中的实现(转载自 - 阿多米 - 博客园) 注:转载请写明出处.本文转载自--阿多米,原链接:http://www.cnblogs.com/zzjder/archive/2008/10 ...
- 如何快速转载别人的CSDN博客文章并附带格式与图片
1.问题背景 最近在学习Git过程中想了解git reflog命令的高级用法与命令详解,于是找到了这几篇特别优秀的文章: [1]使用git reflog 命令来查看历史提交记录并使用提交记录恢复已经被 ...
- 阮一峰老师博客爬取与博客文章存储持久化方式的思考
阮一峰老师博客爬取与博客文章存储持久化方式的思考 前言 博客文章存储持久化思考 文本形式存储 html形式存储 pdf形式存储 博客爬取思路 爬取思路一 爬取思路二 个人选择 pdf存储 结尾 前言 ...
- 解决阮一峰老师博客广告拦截器问题
在浏览器阮一峰老师博客时,存在广告拦截器,无法显示页面.如下: 这个问题是浏览器的adb广告拦截器插件导致的,只需要把该页面从adb插件中移除就可以. 具体操作为点击右上角插件按钮,取消该页面即可 关 ...
- 【机器学习】<刘建平Pinard老师博客学习记录>线性回归原理
目录 一.线性回归的模型函数和损失函数: 二.线性回归的算法: 1.梯度下降法: 2.最小二乘法: 三.线性回归的推广:多项式回归 四.线性回归的推广:广义线性回归 五.线性回归的正则化: 一.线性回 ...
最新文章
- JS判断访问设备(userAgent)加载不同页面 JS判断客户端操作系统类型(platform)
- javaBean【02】javaBean与表单应用
- rest post put_REST / HTTP方法:POST与PUT与PATCH
- visio对象放入word显示不全_办公人士必学visio技能 手把手教你使用visio绘制项目全景图!...
- 小程序mpvue图片绘制水印_开发笔记:使用 mpvue 开发斗图小程序
- 重磅官宣:Nacos2.0发布,性能提升10倍
- phpcmsV9调用顶级父栏目的所有子栏目 - 调用总结
- 今晚直播 | PostgreSQL基于非易失性内存优化探索
- jQuery的表单验证
- 【编译工具】之gcc中-march与-arch的使用
- linux安装php7.3
- doip 源码_DoIP协议源码车载以太网诊断协议ISO13400协议c源码
- 没有基础怎么学习PLC编程?
- 解决WORD输出Html图片Jpg变模糊的问题
- 大岩量化小白科普:什么是量化交易?什么是宽客?
- Source Files 与 Resource Files 的区别
- HDU 5437by cyl优先队列
- 一个简单的app爬虫:对近期热播剧《三十而已》进行知乎app关键词搜索
- 使用LSTM完成简单的中英翻译
- 耳机断线了怎么修 耳机头部断线了如何修4线修复的方法
热门文章
- 为什么你的下一餐要交给机器人?
- org.apache.tomcat.util.descriptor.web.WebXml.setVersion Unknown version stri
- VS2019 MFC 对话框拆分窗格
- 推荐系统的评价指标总结
- 2017高二会考计算机考试时间,2017年高中期末考试时间通知
- SpringBoot整合MongoDB 及 基本使用
- 实现微信生活缴费功能详细讲解
- <C++> 通讯录管理系统(纯手写含源码)
- “熬夜导致秃头”,因果关系推断说这话有问题!
- 课时23 递归:这帮小兔崽子