Android自定义View基本步骤
一.自定義屬性
1.在res下的values下面新建attrs.xml
2.在布局中使用,聲明命名空間
3.在自定義View構造方法中通過TypedArray獲取屬性
4.必須回收 array.recycle();
二.重寫onMeasure()方法
//widthMeasureSpec : 一個32位的值,會包含兩個信息:
//模式:前2位;對應的值:后30位
// 獲取寬高的模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
// 獲取前兩位
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
// 獲取寬高的值
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
// 獲取后面30位
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
MeasureSpec.AT_MOST : 在布局中指定了wrap_content
MeasureSpec.EXACTLY : 在不居中指定了確切的值 100dp match_parent fill_parent
MeasureSpec.UNSPECIFIED : 盡可能的大,很少能用到。ListView , ScrollView 在測量子布局的時候會用UNSPECIFIED 。ScrollView + ListView 會顯示不全問題
三.重寫onDraw(canvas)
常用方法:
canvas.drawText();//畫文本
canvas.drawArc();//畫弧
canvas.drawCircle();//畫圓
canvas.drawBitmap();
canvas.drawLine();canvas.drawLines();
canvas.drawPath();
canvas.drawRect();canvas.drawRoundRect();
canvas.drawOval();
canvas.drawPoint();
問題:自定義view時繼承LinearLayout能不能顯示效果?不能,默認的ViewGroup不會調用onDraw方法,為什么?
draw(Canvas canvas)方法中,采用模板設計:
if (!dirtyOpaque) onDraw(canvas);dispatchDraw(canvas);onDrawForeground(canvas);
dirtyOpaque是false才執行,其實就是由privateFlags -> mPrivateFlags的值決定
final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE
&& (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
mPrivateFlags 到底是怎么賦值的?在View的構造函數中調用 computeOpaqueFlags
protected void computeOpaqueFlags() {if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;} else {mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;}final int flags = mViewFlags;if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||(flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||(flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;} else {mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;}
}
在ViewGroup的initViewGroup方法中:
private void initViewGroup() {// ViewGroup doesn't draw by defaultif (!debugDraw()) {setFlags(WILL_NOT_DRAW, DRAW_MASK);}
}
這里會使mPrivateFlags重新賦值,導致dirtyOpaque為true,最終不執行onDraw方法
如何解決? 思路:改變 mPrivateFlags
1.在自定義View構造方法中調用一下方法,二選一即可
(1).setBackgroundColor(Color.TRANSPARENT);
(2).setWillNotDraw(false);
2.調用dispatchDraw()
總結
以上是生活随笔為你收集整理的Android自定义View基本步骤的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HashMap 的长度为什么是 2 的幂
- 下一篇: invalidate()源码分析