关于自定义View
终于还是逃不过要实现自定义View的这一步,在实现调课的课程表这一功能中,没有发现合适的View可以处理,即使是GridView,也难以实现这上面盖有颜色,而且是在上面跨区域覆盖颜色这种情况.所以无可奈何之下,只能开始学习自定义绘制View.
Start:
- 定义一个View的子类,提供一个带有Context和AttributeSet参数的构造函数.
- 自定义属性:
- 在
元素中为View定义属性 - 在XML的布局文件中指定
- 在运行过程中,获取属性的值
-
把获取的值用在View上
<resources> <declare-styleable name="PieChart"> <attr name="showText" format="boolean" /> <attr name="labelPosition" format="enum"> <enum name="left" value="0"/> <enum name="right" value="1"/> </attr> </declare-styleable> </resources>
这段代码定义了两个自定义的属性,showText和labelPosition,这属于实体PieChart.
- 在
-
通过resource bundle 构成一个AttributeSet实体.之后再通过obtainStyledAttributes()方法,返回给一个TypeArray实体.
public PieChart(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.getTheme().obtainStyledAttributes( attrs, R.styleable.PieChart, 0, 0); try { mShowText = a.getBoolean(R.styleable.PieChart_showText, false); mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0); } finally { a.recycle(); } } 用完之后记得把TypedArray recycled.
- 为属性提供getter和setter方法,以至于动态改变属性的值.在改变完属性的值后,要记得调用invalidate和requestLayout方法,保证view的行为发生了改变.
- 还需要暴露自定义的实现,特别是看得见的一些View.
自定义绘制: 绘制自定义的view是非常重要的一步.有以下几个常用的操作.
- 复写onDraw方法.它的参数Canvas对象可以用来自绘.Canvas定义一些方法,绘制文本,线条,图片还有一些其他图形,你可以用这些方法绘制你的自定义界面.在绘制之前,要先创建一个Paint对象,画笔对象.
- 创建一个绘画对象分为两步:
- 画什么,取决于 Canvas
- 怎么画.取决于 Paint
例如,Canvas提供一个方法去画一条线,而Paint提供一个方法去定义这条线绘制什么颜色.Canvas定义你要在屏幕绘制怎么样的形状,而Paint定义颜色,样式,字体,还有其他等等.
onDraw方法会被频繁调用,所以不要在其中做耗时的初始化操作,否者会出现卡顿的情况. - 处理布局事件.
为了正确的绘制自定义的view,需要计算view的形状以及在屏幕的位置.但是,又无法假定屏幕的大小,因为android手机有多种多样的屏幕尺寸,还可以横屏,竖屏.
虽然view提供多个计算尺寸的方法,但大多数都不需要复写,只需要复写一个方法:onSizeChanged.
onSizeChanged方法在View第一次分配大小的时候,还有在view的大小发生改变的情况下会被调用.在其中计算位置,尺寸,还有其他与size相关的值.
onMeasure方法是用来处理布局超出能显示的范围用的.方法中的MeasureSpec值会告诉你,你的view的parent期望的大小,还有告诉你这是硬性规定还是建议.
需要注意三点:- 需要计算view的padding
- resolveSizeAndState()方法计算最后的宽高的值.返回一个合适的值存在View.MeasureSpec中.最后传递给onMeasure()
- onMeasure方法不会返回值,取而代之的事通过调用setMeasureDimension方法来分享值.必须调用该方法,否则会抛运行异常.
给View加入各种反馈事件: