周五的節奏真的心情爽啊,看看書啊,看看原始碼啊,時間都這樣毫不經意間過去了,爽啦啦!題外話就不說那麼多了啊。下面進入正題,帶你分析cardview
這種帶陰影、圓角的view
是怎麼一步步的實現的。
來看看cardview
構造器吧:
public
cardview(context context)
public
cardview(context context, attributeset attrs)
public
cardview(context context, attributeset attrs, int defstyleattr)
哈哈哈,還是逃不過自定義view的法則啊。再去看看initialize
方法吧:
private
void
initialize(context context, attributeset attrs, int defstyleattr) else
float radius = a.getdimension(r.styleable.cardview_cardcornerradius, 0);
float elevation = a.getdimension(r.styleable.cardview_cardelevation, 0);
float maxelevation = a.getdimension(r.styleable.cardview_cardmaxelevation, 0);
mcompatpadding = a.getboolean(r.styleable.cardview_cardusecompatpadding, false);
mpreventcorneroverlap = a.getboolean(r.styleable.cardview_cardpreventcorneroverlap, true);
int defaultpadding = a.getdimensionpixelsize(r.styleable.cardview_contentpadding, 0);
mcontentpadding.left = a.getdimensionpixelsize(r.styleable.cardview_contentpaddingleft,
defaultpadding);
mcontentpadding.top = a.getdimensionpixelsize(r.styleable.cardview_contentpaddingtop,
defaultpadding);
mcontentpadding.right = a.getdimensionpixelsize(r.styleable.cardview_contentpaddingright,
defaultpadding);
mcontentpadding.bottom = a.getdimensionpixelsize(r.styleable.cardview_contentpaddingbottom,
defaultpadding);
if (elevation > maxelevation)
musersetminwidth = a.getdimensionpixelsize(r.styleable.cardview_android_minwidth, 0);
musersetminheight = a.getdimensionpixelsize(r.styleable.cardview_android_minheight, 0);
a.recycle();
//這個地方很重要,這裡我們重點看
impl.initialize(mcardviewdelegate, context, backgroundcolor, radius,
elevation, maxelevation);
}
在這裡看到有乙個變數impl
,那去看看該變數是在哪生成的吧:
private
static
final cardviewimpl impl;
static else
if (build.version.sdk_int >= 17) else
impl.initstatic();
}
這裡有幾個版本的分支,根據不同的版本生成不同的cardviewimpl
,其實看設計模式的筒子們。這裡是工廠模式的一種,根據不同的情況生產不同的cardviewimpl(介面)
,那咋們先去看高版本的吧:
cardviewapi21
實現類,還是照常跟進cardviewapi21
的initialize
方法:
@override
public
void
initialize(cardviewdelegate cardview, context context,
colorstatelist backgroundcolor, float radius, float elevation, float maxelevation)
這裡cardview是什麼東東啊,別急,咱們回到cardview類中去看看就知道了啊
private
final cardviewdelegate mcardviewdelegate = new cardviewdelegate()
@override
public
boolean
getusecompatpadding()
@override
public
boolean
getpreventcorneroverlap()
@override
public
void
setshadowpadding(int left, int top, int right, int bottom)
@override
public
void
setminwidthheightinternal(int width, int height)
if (height > musersetminheight)
}@override
public drawable getcardbackground()
@override
public view getcardview()
};
可以看到它是cardview
內部的乙個final型別的內部類啊,這裡主要是來看下setcardbackground
方法,這裡是將impl
中drawable
回傳過來了,該處也沒做什麼,只是呼叫了cardview
的setbackgrounddrawable
方法啊,也即是我們的viewgroup
的setbackgrounddrawable
方法。看過設計模式的朋友其實不難發現,mcardviewdelegate
內部類是不是builder
的設計模式呢,builder
設計模式最大的特點就是將外部類的一些行為封裝到內部類中。其實如果外部類的屬性不是很多的話,也沒必要封裝成builder
模式。你們覺得呢?
上面提到了cardviewapi21
的initialize
方法中roundrectdrawable
變數,也提到了它是乙個drawable
,那咱們看看是怎麼自定義乙個drawable
吧:
1.對roundrectdrawable
的大小進行修正啊:
@override
protected
void
onboundschange(rect bounds)
private
void
updatebounds(rect bounds)
mboundsf.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
mboundsi.set(bounds);
//預設是true的
if (minsetforpadding)
}
上面對mboundsi
通過padding
和mradius
縮小,mboundsf
同樣也是縮小。
下面是對roundrectdrawable
的繪製部分了,繪製的話,就簡單了:
@override
public
void
draw(canvas canvas) else
//繪製帶圓角的矩形
canvas.drawroundrect(mboundsf, mradius, mradius, paint);
if (clearcolorfilter)
}
這裡只是分析21之上的**,具體低版本的**看下cardviewjellybeanmr1
和cardviewgingerbread
鴻蒙原始碼分析系列篇
鴻蒙核心原始碼注釋中文版 gitee倉 csdn倉 github倉 coding倉 專案中文註解鴻蒙官方核心原始碼,詳細闡述鴻蒙架構和 設計細節,精讀核心原始碼最大的好處是 將孤立知識點織成一張高濃度,高密度底層網,對計算機體系化理解形成永久記憶,從此高屋建瓴分析 解決問題.鴻蒙原始碼分析系列篇 c...
Android原始碼分析系列 整理篇
本系列主要走了一下android掛載sd卡的流程,從vold到framework,再從framework到ui。也熟悉了谷歌寫的c c 源 提高一下自己的類的設計與 的技巧,很感謝谷歌提供這麼乙個手機的開源作業系統android,讓鄙人也有機會來了解一下智慧型終端系統的實現原理。只要有c c 的基礎...
Android原始碼分析系列 整理篇
本系列主要走了一下android掛載sd卡的流程,從vold到framework,再從framework到ui。也熟悉了谷歌寫的c c 源 提高一下自己的類的設計與 的技巧,很感謝谷歌提供這麼乙個手機的開源作業系統android,讓鄙人也有機會來了解一下智慧型終端系統的實現原理。只要有c c 的基礎...