Android自定义View

自定View的概念, 什么是自定义View??

在Android系统中,使用系统自带的控件重新组合或者自定义类继承View或者ViewGroup实现特定的效果。

为什么学习自定义View??

1, 整个View控件在不同设备上的风格统一。例如QQ,微信,支付宝。
2, 系统自带的View功能过多,或者过少不能满足我们的需求,例如listView没有下拉刷新功能。还有例如我们不希望ViewPager有滑动功能。
3, 系统自带View不能满足我们的需求,我们需要自己实现.

自定义View的重要性

1, Android程序员一定离不开自定义View。
2, 工作必须用到。
3, 看懂别人的代码。
4, 面试的时候必须会被问到。

自定义View的原则:

如果系统View能够完成的尽量使用系统控件,新的自定义View容易引起BUG。

自定义view的有四种形式:

(一) 组合View:
 组合控件,顾名思义就是将一些系统控件组合起来形成一个新的控件,形成UI特定的效果。比如很多应用中普遍使用的标题栏控件,其实用的就是组合控件,达到形成自己统一的风格。
(二)自定义View:
自绘控件就是继承View,自定义其中的内容,并在View的onDraw方法中按照规定完成绘制功能。
(三)继承ViewGroup:
就是继承已有的ViewGroup,创建新的ViewGroup。
(四)继承原有的系统控件,例如ListView或者ViewPager。
在保留原有特性的基础上,增加或者减少原有的特性。

View类简介:
• View类是Android中各种组件的基类,如View是ViewGroup基类
• View表现为显示在屏幕上的各种视图
Android中的UI组件都由View、ViewGroup组成。
其框架如下图所示:

为什么需要自定义View?是因为Android原生的View不能满足我们的需求了,所以需要我们自定义自己的View。

View的构造函数
【第一个问题】
如果我们在继承了View类实现自定义类时,需要重写哪个构造函数?
回答这个问题,首先需要知道,在定义了View时,我们都调用了哪个构造函数。

1public View(Context context)

2public View(Context context, @Nullable AttributeSet attrs)

3public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr)

4public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)

当我们自定义一个View,且在布局文件中引用时,在系统初始化该View时,调用的是第二个构造函数,(演示)

View整个绘制流程??

Measure->Layout->Draw
onMeasure()->onLayout()->onDraw()
需要计算View的大小(measure)、重新安置视图的位置(layout)、绘制视图(draw)。

• measure: 计算View的大小,需要的话则计算大小;我们自定义View时实现onMeasure()方法,在该方法确定控件的实际大小。
• layout: 计算View的位置,需要的话则计算位置;我们自定义ViewGroup时,实现onLayout()方法,该方法摆放控件的位置。
• draw:绘制View,绘制视图。自定义View时,实现onDraw()方法。去实现绘制自己。
我们自定义View,需要实现的几个方法。

onMeasure()方法:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int specWidthMode = MeasureSpec.getMode(widthMeasureSpec);
int specHeightMode = MeasureSpec.getMode(heightMeasureSpec);

switch (specHeightMode) {
    case MeasureSpec.EXACTLY:
        break;
    case MeasureSpec.AT_MOST:
        break;
    case MeasureSpec.UNSPECIFIED:
        break;
    default:
        break;
}
/**
 *设置自定义view的尺寸.
 */
setMeasuredDimension(300, 300);

}
该方法就是我们自定义View中实现测量逻辑的方法,该方法的参数是父视图对子视图的 width 和 height 的测量要求。在我们自身的自定义视图中,要做的就是根据该 widthMeasureSpec 和 heightMeasureSpec 计算视图的 width 和 height,不同的模式处理方式不同。

MeasureSpec的使用:

  1. 获取测量模式(Mode) int specMode = MeasureSpec.getMode(measureSpec) 2. 获取测量大小(Size) int specSize = MeasureSpec.getSize(measureSpec)
    Mode:

onLayout()方法:
protected abstract void onLayout(boolean changed,
int l, int t, int r, int b);

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
layoutChildren(left, top, right, bottom, false /* no force left gravity */);
}

首先要明确的是,子视图的具体位置都是相对于父视图而言的。View 的 onLayout 方法为空实现,而 ViewGroup 的 onLayout 为 abstract 的,因此,如果自定义的 View 要继承 ViewGroup 时,必须实现 onLayout 函数。
在 layout 过程中,子视图会调用getMeasuredWidth()和getMeasuredHeight()方法获取到 measure 过程得到的 mMeasuredWidth 和 mMeasuredHeight,作为自己的 width 和 height。然后调用每一个子视图的layout(l, t, r, b)函数,来确定每个子视图在父视图中的位置。

protected void onDraw(Canvas canvas)
View 的onDraw(Canvas)默认是空实现,自定义View绘制过程需要复写的方法,绘制自身的内容。

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

// 绘制一个填充色为蓝色的矩形
mPaint.setColor(Color.BLUE);
canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
mPaint.setColor(Color.YELLOW);
mPaint.setTextSize(50);
String text = String.valueOf(mCount);
// 获取文字的宽和高
mPaint.getTextBounds(text, 0, text.length(), mBounds);
float textWidth  = mBounds.width();
float textHeight = mBounds.height();
// 绘制字符串
canvas.drawText(text, getWidth() / 2 - textWidth / 2, getHeight() / 2
        + textHeight / 2, mPaint);

}

自定义View属性。
自定义View的自定义属性,为了能让自定义View在xml文件中编写时可以设置自己特有的属性值

创建attrs.xml文件
在res/values/中创建一个attrs.xml。
创建declare-styleable节点
在根节点resources内添加declare-styleable节点,declare-styleable节点只有一个name属性且为必填,name可以自由定义。

<?xml version="1.0" encoding=
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值