Android开发之自定义View

自定义控件

使用场景: 在实际开发中经常会遇到现有的UI控件不能满足项目需求,或一个功能涉及到多个UI控件的组合,或实现某一特效的UI,这时必须通过自定义View的方式,实现这些功能,例如股票的实时统计图、电子书等。

分类

绘制控件 - 自绘控件

1.继承View
需要自定义绘制内容,需要继承View,必须要重写onDraw方法,在onDraw方法中来进行绘制,实现onMeasure方法,来测量控件的空间。

2.继承ViewGroup

  • 通过在ViewGroup中通过this.addView(<控件对象>)来添加控件
  • onMeasure方法,来测量控件的空间
  • onLayout方法必须实现,在此方法中处理子控件的位置。当视图初始化,或者视图位置发生改变时候,调用此方法。

组合控件

通过继承系统已经存在的视图容器,在初始化时候,直接加载布局

mInflater.inflate(<布局资源的ID>,this);
mIvBack = (ImageView) findViewById(R.id.btn_back);

继承控件

通过继承系统已经存在的视图或者视图容器,在内部改变此视图或者视图容器的功能
例如:通过改变ListView添加删除功能

自定义View步骤

  • 创建类,继承View及View的子类,并提供相关的构造方法
  • 重写onMeasure()方法,并调用setMeasuredDimension(int width, int height)设置控件的大小
  • 重写onDraw()方法,实现绘制特定内容
  • 重写onTouchEvent()方式处理触摸事件
  • 在布局文件中使用<类全名>并设置属性

自定义View属性

1.位置:res/values/attrs.xml

2.属性集

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 声明属性集 -->
    <declare-styleable name="LabelView">
        <attr name="text" format="string"/>
        <attr name="textSize" format="dimension"/>
        <attr name="textColor" format="color" />
    </declare-styleable>
</resources>

3.指定属性名及其内容格式
例:<attr name="text" format="string" />

string 字符型
integer 整数型
dimension 尺寸值
color 颜色值
reference 参考某一资源ID
boolean:布尔值

使用自定义View属性

在布局控件标签中引用:xmlns:my="http://schemas.android.com/apk/res/{package_name}"
或xmlns:app="http://schemas.android.com/apk/res-auto"
在自定义控件中使用:my:text=““或app:text=""

在自定义View的View(Context context, AttributeSet attrs)构造方法中,获取自定义属性的值

//TypedArray是一个用来存放由context.obtainStyledAttributes获得的属性的数组
        //在使用完成后,一定要调用recycle方法
         TypedArray ta = context.obtainStyledAttributes(attrs,
                    R.styleable.LabelView);

            CharSequence s = ta.getString(R.styleable.LabelView_text);
            if (s != null) {
                setText(s.toString());
            }

            setTextColor(ta.getColor(R.styleable.LabelView_textColor, 0xFF000000));

            int textSize = ta.getDimensionPixelSize(R.styleable.LabelView_textSize, 0);
            if (textSize > 0) {
                setTextSize(textSize);
            }
            ta.recycle();

涉及相关类

View 类

  • View(Context) 动态实例化控件的构造方法
  • View(Context context, AttributeSet attrs) 布局中使用控件的构造的方法
  • onMeasure(int widthMeasureSpec, int heightMeasureSpec) 自定义控件时重写的方法,用于测量控件大小
  • onDraw(Canvas canvas) 在自义控件上绘制相关内容
  • onTouchEvent(MotionEvent) 实现触摸事件处理方法
  • setPadding(int l,int t,int r,int b) 设置内部间距
  • layout(int l, int t, int r,int b) 改变控件位置的方法
  • requestLayout() //清除布局,获取新的布局空间(刷新UI,重新调用onDraw()方法绘制UI)
  • invalidate() //重新绘制新的数据(刷新UI,重新调用onDraw()方法绘制UI)

MeasureSpec 测量空间工具类

  • int MeasureSpec.getMode(mSpec) 获取控件大小模式
    • MeasureSpec.EXACTLY,确切空间,布局中的属性值一般为match_parent或160dp固定值
    • MeasureSpec.AT_MOST 尽量多的空间,布局中的属性值wrap_content
    • MeasureSpec.UNSPECIFIED 未指定的,一般在父控件中使用
  • MeasureSpec.getSize(mSpec) 获取控件大小

TypedArray 属性数组类

  • TypeArray Context.obtainStyledAttributes(attrs,R.styleable.LabelView) 获取指定attrs中的所有属性
  • String getString(R.styleable.LabelView_text) 获取指定属性的文本值
  • int getDimensionPixelSize(R.styleable.LabelView_textSize, 0) 获取指定属性的间距值
  • int getColor(R.styleable.LabelView_textColor, 0xFF000000) 获取指定属性的颜色值

Paint 画笔类

  • Paint.setAntiAlias(true) 启用抗锯齿
  • Paint.setTextSize(int pixes) 设置字体大小,像素,一般转成sp
  • Paint.setColor(int color) 设置颜色
  • Paint.setStyle(Paint.Style) 设置画笔样式
  • float mTextPaint.measureText(String) 测量文字的大小
  • Paint.ascent() 获取文字基准线以上到文字顶部的间距,负数
  • Paint.descent() 获取文字基准线以下到文字底部的间距

Canvas 画布类

  • canvas.drawText(String,int x,int y,Paint) 绘制文本
  • canvas.drawRoundRect(RectF,int rx,int ry,Paint) 绘制圆角四边方形
  • canvas.drawBitmap(bitmap, left, top, paint) 绘制图片
  • canvas.drawCircle(cx, cy, radius, paint) 绘制圆
  • canvas.drawLine(startX, startY, stopX, stopY, paint) 绘制线条

Xfermode 两个图层的转换模式

Xfermode有三个子类 :
AvoidXfermode 指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图)。
PixelXorXfermode 当覆盖已有的颜色时,应用一个简单的像素异或操作。
PorterDuffXfermode 这是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互。


要应用转换模式,可以使用setXferMode方法,如下所示:

AvoidXfermode avoid = new AvoidXfermode(Color.BLUE, 10, AvoidXfermode.Mode. AVOID);
borderPen.setXfermode(avoid);

PorterDuff.Mode为枚举类,一共有16个枚举值:

1.PorterDuff.Mode.CLEAR
所绘制不会提交到画布上。
2.PorterDuff.Mode.SRC
显示上层绘制图片
3.PorterDuff.Mode.DST
显示下层绘制图片
4.PorterDuff.Mode.SRC_OVER
正常绘制显示,上下层绘制叠盖。
5.PorterDuff.Mode.DST_OVER
上下层都显示。下层居上显示。
6.PorterDuff.Mode.SRC_IN
取两层绘制交集。显示上层。
7.PorterDuff.Mode.DST_IN
取两层绘制交集。显示下层。
8.PorterDuff.Mode.SRC_OUT
取上层绘制非交集部分。
9.PorterDuff.Mode.DST_OUT
取下层绘制非交集部分。
10.PorterDuff.Mode.SRC_ATOP
取下层非交集部分与上层交集部分
11.PorterDuff.Mode.DST_ATOP
取上层非交集部分与下层交集部分
12.PorterDuff.Mode.XOR
异或:去除两图层交集部分
13.PorterDuff.Mode.DARKEN
取两图层全部区域,交集部分颜色加深
14.PorterDuff.Mode.LIGHTEN
取两图层全部,点亮交集部分颜色
15.PorterDuff.Mode.MULTIPLY
取两图层交集部分叠加后颜色
16.PorterDuff.Mode.SCREEN
取两图层全部区域,交集部分变为透明色

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容