接触Android有一段时间了,但是一直都不会自定义控件。以前也写过一些,但是效果不是太显著,有些效果让我自己写我还是写不出来了。所以现在我要重头写自定义组件,我认为我现在写不出来有以下几个原因
1.对Android系统提供的一些方法接触的还是不够深刻。
2.自己写的少,没有什么思路。
3.自己写的少,没有什么思路。重要的东西要说两遍。
现在先将我的写的效果图给大家奉献上来
这个效果就是Android的TextView,我再下面说一下为什么我要写这样一个Android已经提供的效果,然后我会说一下我是怎么做的
一、说一下我为什么要写这样一个Android已经提供的效果
1.首先在这个效果中练习自定义属性
2.加深对onDraw和onMeasure方法的用法
3.通过这个组件,后面有关文字的自定义控件我都可以知道怎么写
二、下来我说一下这里的实现方法
在这个过程中,我将它大致分为四个部分
1.自定义属性的实现
2.有关Android中文字绘制的一些知识
3.onDraw方法中的实现
4.onMeasure方法的实现
一、自定属性的实现
首先我们在Values文件夹下创建一个布局,名字可以随便取,但是一般都会以attrs来命名
多说无益,先来看看布局中的代码,里面注释已经很全面
布局地址Values/attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- name 属性名称 一般是我么自定义组件的类名 -->
<declare-styleable name="MTextView">
<!-- name 属性名称
format 格式: string 文字 color 颜色
dimension 宽高 字体大小 integer 数字
reference 资源(drawable)
-->
<attr name="darrenText" format="string"/>
<attr name="darrenTextColor" format="color"/>
<attr name="darrenTextSize" format="dimension"/>
<attr name="darrenMaxLength" format="integer"/>
<!-- background 自定义View都是继承自View , 背景是由View管理的-->
<!--<attr name="darrenBackground" format="reference|color"/>-->
<!-- 枚举 -->
<attr name="darreninputType">
<enum name="number" value="1"/>
<enum name="text" value="2"/>
<enum name="password" value="3"/>
</attr>
</declare-styleable>
</resources>
二、有关Android中文字绘制的一些知识
先介绍一下文字的组成部分,这里我在网上借用别人的一张图
top:是指的是最高字符到baseline的值,即ascent的最大值,为负值
bottom:是指最低字符到baseline的值,即descent的最大值,为正值
baseline :基准线,我是这样理解基准线的,他才是文字的中间线。
然后在说下基准线的算法,然后我会在onDraw方法中,会具体说一下基准线的具体算法、
baseline =(bootom -top)/2 -bootom
三、onDraw方法中的实现
onDraw顾名思义就是绘制的意思,就是我们进行绘画,在这里可以绘画很多东西。比如:线条,文字,图片,矩形等很多形状。这里我们就是在绘制的就是文字.
这里贴出算基准线的代码
Paint.FontMetricsInt fontMetricsInt = mPaint.getFontMetricsInt();
//获取中心线到基准线的高度
int y =(fontMetricsInt.bottom -fontMetricsInt.top)/2-fontMetricsInt.bottom;
//计算基准线高度
int baseLine =getHeight()/2+y;
然后贴出绘制文字的代码
canvas.drawText(darrenText,x,baseLine,mPaint);
这里darrenText代表要绘制的文字,x代表轴的长度,y代表y轴的长度(一般是文字的中心,也就是基准线),mpaint画笔
四、onMeasure方法的实现
onMeasure代表测量,他决定了我们组件的大小。
在onMeasure中三种测量模式
AT_MOST(wrap_caontent)
EXTRALY (固定值) 针对不同的情况指定不同的宽高,wrap_content
UNSPECIFIED 不指定大小测量模式。
一般我们在进行测量的时候一般都是判断 AT_MOST,然后贴出onMeasure的代码
//进行测量
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取我们设置的宽度
int width =MeasureSpec.getSize(widthMeasureSpec);
int height =MeasureSpec.getSize(heightMeasureSpec);
//获取测量模式
int widthMode =MeasureSpec.getMode(widthMeasureSpec);
int heightMode =MeasureSpec.getMode(heightMeasureSpec);
if(widthMode ==MeasureSpec.AT_MOST){
Rect rect = new Rect();
mPaint.getTextBounds(darrenText,0,darrenText.length(),rect);
//获取宽度
width =rect.width()+getPaddingRight()+getPaddingLeft();
}
if(heightMode ==MeasureSpec.AT_MOST){
Rect rect = new Rect();
mPaint.getTextBounds(darrenText,0,darrenText.length(),rect);
//获取高度
height =rect.height()+getPaddingBottom()+getPaddingTop();
}
//设置我们想要设置的宽和高
setMeasuredDimension(width,height);
}
好了今天自定义组件TextView就到这里了。
最后献上我的项目源码https://github.com/GitHubToLiao/MyTextView.git