首先來看看我們模仿的效果圖,相信對于使用過QQ的人來說都不陌生,效果圖如下:
成都創(chuàng)新互聯(lián)公司-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價比大荔網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式大荔網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋大荔地區(qū)。費(fèi)用合理售后完善,十載實(shí)體公司更值得信賴。在以前的一個項(xiàng)目中,需要實(shí)現(xiàn)類似QQ討論組頭像的控件,只是頭像數(shù)量和布局有一小點(diǎn)不一樣:一是最頭像數(shù)是4個,二是頭像數(shù)是2個時的布局是橫著排的。其實(shí)當(dāng)時GitHub上就有類似的開源控件,只是那個控件在每一次繪制View的時候都會新創(chuàng)建一些Bitmap對象,這肯定是不可取的,而且那個控件頭像輸入的是Bitmap對象,不滿足需求。所以只能自己實(shí)現(xiàn)一個了。實(shí)現(xiàn)的時候也沒有過多的考慮,傳入頭像Drawable對象,根據(jù)數(shù)量排列顯示就算完成了,而且傳入的圖像還必需是圓形的,限制很大,根本不具備通用性。因此要實(shí)現(xiàn)和QQ討論組頭像一樣的又具備一定通用性的控件,還得重新設(shè)計(jì)、實(shí)現(xiàn)。
下面就讓我們開始實(shí)現(xiàn)吧。
布局
首先需要解決的是頭像的布局,在頭像數(shù)量分別為1至5的情況下,定義頭像的布局排列方式,并計(jì)算出圖像的大小和位置。先把布局圖畫出來再說:
其中黑色正方形就是View的顯示區(qū),藍(lán)色圓形就是頭像了。已知的條件是View大小,姑且設(shè)為 D 吧,還有頭像的數(shù)量 n ,求藍(lán)色圓的半徑 r 及圓心位置。這不就是一道幾何題嗎?翻開初中的數(shù)學(xué)課本——勾三股四弦五……好像不夠用啊……
輔助線畫了又畫,頭皮撓了又撓,α,θ,OMG......sin,cos,sh*t......終于算出了 r 與 D 和 n 的關(guān)系:
其實(shí) n=3 的時候半徑和 n=4 的時候是一樣的,但是考慮到 n=3,5 時在Y軸上還有一個偏移量 dy ,而且 r 和 dy 在 n=3,5 時是有通式的,所以就合在一起了。求偏移量 dy 的公式:
式中 R 就是布局圖中紅色大圓的半徑。
有了公式,那么代碼就好寫了,計(jì)算每個頭像的大小和位置的代碼如下:
// 頭像信息類,記錄大小、位置等信息 private static class DrawableInfo { int mId = View.NO_ID; Drawable mDrawable; // 中心點(diǎn)位置 float mCenterX; float mCenterY; // 頭像上缺口弧所在圓上的圓心位置,其實(shí)就是下一個相鄰頭像的中心點(diǎn) float mGapCenterX; float mGapCenterY; boolean mHasGap; // 頭像邊界 final RectF mBounds = new RectF(); // 圓形蒙板路徑,把頭像弄成圓形 final Path mMaskPath = new Path(); }