六芒(bian)星(xing)ImageView

六芒星寫輪眼

今天突然看到自己的發(fā)泥盒(一個(gè)六邊形的盒子)查剖,所以突發(fā)奇想想封裝一個(gè)這樣的ImageView控件飒泻,之后用鞭光,有什么用吏廉,不告訴你泞遗。發(fā)泥盒我就不發(fā)照片了,以免認(rèn)為我在做廣告席覆。

PS:我只寫干貨史辙,如果你發(fā)現(xiàn)文中有不是干貨的地方,你就當(dāng)沒看見佩伤。

題目可能有些不清楚聊倔,其實(shí)是要實(shí)現(xiàn)一個(gè)正六邊形的ImageView。感覺這個(gè)也沒什么好寫的生巡。圓形呀耙蔑,圓角矩形呀,類似的這些基本都寫爛了孤荣,你就隨便看看好了甸陌。

實(shí)現(xiàn)這個(gè)東西须揣,本人想到兩種方法:

  1. Xformode
  2. Shader

Xformode可以說是處理這種萬能的方法。用過的應(yīng)該都懂钱豁。但是它的性能不高耻卡,因?yàn)槊看味妓媰纱危粋€(gè)蒙板一個(gè)原圖牲尺,然后兩個(gè)圖疊加做相應(yīng)的計(jì)算卵酪。所以如果不是其他方法都不行,我是絕對不會用它的谤碳。

那么Shader貌似是一個(gè)好的方案溃卡,但是Shader就是需要自己想辦法畫出一個(gè)正六邊形了。這個(gè)時(shí)候我內(nèi)心OS了一下估蹄∷芗澹靠,我要是畫不出個(gè)正六邊形臭蚁,我就不做Android了!

正六邊形畫法

正六邊形

在Android中的畫法和現(xiàn)實(shí)中的畫法基本差不多最铁。這個(gè)其實(shí)看成一個(gè)簡單的多邊形,使用Android中的Path就好了垮兑。只是需要確定幾個(gè)關(guān)鍵點(diǎn)的坐標(biāo)冷尉。這里我們假設(shè)寬度撐滿。高度居中系枪。那么我們的代碼基本就是這個(gè)樣子:

正六邊形的邊長l就是寬的一半雀哨,正六邊形的高是 Math.sqrt(3)*l ,然后可以算出正六邊形頂部的top值私爷,之后只要依次遍歷連接每個(gè)點(diǎn)雾棺,即可畫出正六邊形。

代碼如下:

float l = (float) (getWidth() / 2);
float h = (float) (Math.sqrt(3)*l);
float top = (getHeight() - h) / 2  ;
mPath.reset();
mPath.moveTo(l/2,top);
mPath.lineTo(0,h/2+top);
mPath.lineTo(l/2,h+top);
mPath.lineTo((float) (l*1.5),h+top);
mPath.lineTo(2*l,h/2+top);
mPath.lineTo((float) (l*1.5),top);
mPath.lineTo(l/2,top);
mPath.close();

設(shè)置Shader

對于Shader還不了解的人衬浑,可以去搜一搜其他博客捌浩,講這個(gè)的已經(jīng)很多了,我就不再講一遍了工秩。這里我們使用的是BitmapShader尸饺,這個(gè)類名副其實(shí),它可以把一個(gè)Bitmap做為我們的渲染對象助币,在設(shè)置Bitmap的時(shí)候把Bitmap初始化BitmapShader浪听,然后設(shè)置給Paint。直接上代碼了眉菱。

// 先把要設(shè)置的bitmap設(shè)置給一個(gè)BitmapShader
shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP) ;
// 然后給Paint設(shè)置shader
mPaint.setShader(shader) ;

使用Shader繪制正六邊形

我們重寫onDraw方法:

@Override
public void onDraw(Canvas canvas) {
    canvas.drawPath(mPath,mPaint);
}

看下效果:

效果圖

封裝到Drawable中

寫完之后迹栓,發(fā)現(xiàn)功能簡單相對獨(dú)立,沒有使用自定義View的必要俭缓,因此將其封裝成Drawable克伊,使用起來也將更加方便叉抡。代碼如下:

public class HiveDrawable extends Drawable {
    // 用于記錄邊界信息的Rect
    Rect mRect = new Rect();
    Paint mPaint;
    Path mPath ;
    BitmapShader mShader;
    Bitmap mBitmap ;

    public HiveDrawable() {
        this(null) ;
    }

    public HiveDrawable(Bitmap bitmap) {
        init();
        setBitmap(bitmap);
    }

    private void init() {
        initPaint() ;
        initPath() ;
    }

    private void ensurePaint(){
        if (mPaint == null) {
            mPaint = new Paint() ;
        }
    }

    private void ensurePath(){
        if (mPath == null) {
            mPath = new Path() ;
        }
    }

    private void initPaint() {
        ensurePaint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeWidth(3f);
    }

    public Bitmap getBitmap() {
        return mBitmap;
    }

    // 設(shè)置Bitmap的時(shí)候初始化shader,并設(shè)置給paint
    public void setBitmap(Bitmap bitmap) {
        this.mBitmap = bitmap;
        if (bitmap == null) {
            mShader =null ;
        } else {
            mShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP) ;
            mPaint.setShader(mShader) ;
        }
    }

    // 初始化好Path要走的路徑
    private void initPath() {
        ensurePath();
        float l = (float) (mRect.width() / 2);
        float h = (float) (Math.sqrt(3)*l);
        float top = (mRect.height() - h) / 2  ;
        mPath.reset();
        mPath.moveTo(l/2,top);
        mPath.lineTo(0,h/2+top);
        mPath.lineTo(l/2,h+top);
        mPath.lineTo((float) (l*1.5),h+top);
        mPath.lineTo(2*l,h/2+top);
        mPath.lineTo((float) (l*1.5),top);
        mPath.lineTo(l/2,top);
        mPath.close();
    }

    @Override
    public void draw(Canvas canvas) {
        canvas.drawPath(mPath,mPaint);
    }

    @Override
    public void setAlpha(int alpha) {
        if (mPaint != null) {
            mPaint.setAlpha(alpha);
        }
    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {
        if (mPaint != null) {
            mPaint.setColorFilter(colorFilter) ;
        }
    }

    @Override
    public int getOpacity() {
        return 0 ;
    }

    // 設(shè)置邊界信息
    @Override
    public void setBounds(int left, int top, int right, int bottom) {
        super.setBounds(left, top, right, bottom);
        mRect.set(left, top, right, bottom);
        initPath();
    }

    @Override
    public int getIntrinsicWidth() {
        if (mBitmap != null) {
            return mBitmap.getWidth();
        } else {
            return super.getIntrinsicWidth() ;
        }
    }

    @Override
    public int getIntrinsicHeight() {
        if (mBitmap != null) {
            return mBitmap.getHeight() ;
        }
        return super.getIntrinsicHeight();
    }
}

HiveDrawable 的使用:

// imageView是一個(gè)ImageView直接通過ImageDrawable方法設(shè)置一個(gè)HiveDrawable進(jìn)來即可答毫。
imageView.setImageDrawable(new HiveDrawable(BitmapFactory.decodeResource(getResources(),R.drawable.img_1)));

運(yùn)行效果是一樣的褥民,就不展示了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末洗搂,一起剝皮案震驚了整個(gè)濱河市消返,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌耘拇,老刑警劉巖撵颊,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異惫叛,居然都是意外死亡倡勇,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進(jìn)店門嘉涌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妻熊,“玉大人,你說我怎么就攤上這事仑最∪右郏” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵警医,是天一觀的道長亿胸。 經(jīng)常有香客問我,道長预皇,這世上最難降的妖魔是什么侈玄? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮吟温,結(jié)果婚禮上序仙,老公的妹妹穿的比我還像新娘。我一直安慰自己溯街,他們只是感情好诱桂,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布洋丐。 她就那樣靜靜地躺著呈昔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪友绝。 梳的紋絲不亂的頭發(fā)上堤尾,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天,我揣著相機(jī)與錄音迁客,去河邊找鬼郭宝。 笑死辞槐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的粘室。 我是一名探鬼主播榄檬,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼衔统!你這毒婦竟也來了鹿榜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤锦爵,失蹤者是張志新(化名)和其女友劉穎舱殿,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體险掀,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沪袭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了樟氢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冈绊。...
    茶點(diǎn)故事閱讀 39,739評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖埠啃,靈堂內(nèi)的尸體忽然破棺而出焚碌,到底是詐尸還是另有隱情,我是刑警寧澤霸妹,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布十电,位于F島的核電站,受9級特大地震影響叹螟,放射性物質(zhì)發(fā)生泄漏鹃骂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一罢绽、第九天 我趴在偏房一處隱蔽的房頂上張望畏线。 院中可真熱鬧,春花似錦良价、人聲如沸寝殴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蚣常。三九已至,卻和暖如春痊银,著一層夾襖步出監(jiān)牢的瞬間抵蚊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贞绳,地道東北人谷醉。 一個(gè)月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像冈闭,于是被迫代替她去往敵國和親俱尼。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,082評論 25 707
  • 內(nèi)容抽屜菜單ListViewWebViewSwitchButton按鈕點(diǎn)贊按鈕進(jìn)度條TabLayout圖標(biāo)下拉刷新...
    皇小弟閱讀 46,755評論 22 665
  • 上午萎攒,在陽光屋里做了養(yǎng)生功号显。壽與天齊,往左旋轉(zhuǎn)的時(shí)候右腿拉伸的特別不舒服躺酒,好在比前兩天強(qiáng)押蚤。往右側(cè)轉(zhuǎn)就沒事兒。應(yīng)該還...
    jzqqqqjz閱讀 269評論 0 6
  • [目錄] 文 | 零分J 第六話 洗浴驚魂 兩個(gè)女孩子就這樣一路有說有笑羹应、打打鬧鬧揽碘,很快便到了傳媒藝校的公共浴室,...
    零分J閱讀 338評論 0 1
  • 頂著北京六級的大風(fēng)园匹,被吹到國家博物館雳刺,觀賞惦記了一個(gè)假期的“盧浮宮的創(chuàng)想”展覽。 正好趕上“兩會”裸违,進(jìn)...
    木易青苑閱讀 671評論 2 1