Android實(shí)現(xiàn)一個(gè)圓角

最近項(xiàng)目中需要背景做成圓角溪胶,心說(shuō)這還是不是很容易的事兒搂擦,后來(lái)發(fā)現(xiàn)有性能問(wèn)題!網(wǎng)上查了一圈载荔,才發(fā)現(xiàn)圓角不同的實(shí)現(xiàn)方式盾饮,對(duì)性能竟然有這么大的影響采桃!

首先想到的就是去看看大名鼎鼎的Fresco是怎么實(shí)現(xiàn)圓角的懒熙。

其實(shí)核心就是RoundedCornersDrawable,其中普办,有兩種類型

  public enum Type {
    /**
     * Draws rounded corners on top of the underlying drawable by overlaying a solid color which
     * is specified by {@code setOverlayColor}. This option should only be used when the
     * background beneath the underlying drawable is static and of the same solid color.
     */
    OVERLAY_COLOR,

    /**
     * Clips the drawable to be rounded. This option is not supported right now but is expected to
     * be made available in the future.
     */
    CLIPPING
  }

對(duì)應(yīng)兩種不同的實(shí)現(xiàn)方式

  @Override
  public void draw(Canvas canvas) {
    Rect bounds = getBounds();
    switch (mType) {
      case CLIPPING:
        int saveCount = canvas.save();
        // clip, note: doesn't support anti-aliasing
        mPath.setFillType(Path.FillType.EVEN_ODD);
        canvas.clipPath(mPath);
        super.draw(canvas);
        canvas.restoreToCount(saveCount);
        break;
      case OVERLAY_COLOR:
        super.draw(canvas);
        mPaint.setColor(mOverlayColor);
        mPaint.setStyle(Paint.Style.FILL);
        mPath.setFillType(Path.FillType.INVERSE_EVEN_ODD);
        canvas.drawPath(mPath, mPaint);

        if (mIsCircle) {
          // INVERSE_EVEN_ODD will only draw inverse circle within its bounding box, so we need to
          // fill the rest manually if the bounds are not square.
          float paddingH = (bounds.width() - bounds.height() + mBorderWidth) / 2f;
          float paddingV = (bounds.height() - bounds.width() + mBorderWidth) / 2f;
          if (paddingH > 0) {
            canvas.drawRect(bounds.left, bounds.top, bounds.left + paddingH, bounds.bottom, mPaint);
            canvas.drawRect(
                bounds.right - paddingH,
                bounds.top,
                bounds.right,
                bounds.bottom,
                mPaint);
          }
          if (paddingV > 0) {
            canvas.drawRect(bounds.left, bounds.top, bounds.right, bounds.top + paddingV, mPaint);
            canvas.drawRect(
                bounds.left,
                bounds.bottom - paddingV,
                bounds.right,
                bounds.bottom,
                mPaint);
          }
        }
        break;
    }

    if (mBorderColor != Color.TRANSPARENT) {
      mPaint.setStyle(Paint.Style.STROKE);
      mPaint.setColor(mBorderColor);
      mPaint.setStrokeWidth(mBorderWidth);
      mPath.setFillType(Path.FillType.EVEN_ODD);
      canvas.drawPath(mBorderPath, mPaint);
    }
  }

CLIPPING就是裁剪工扎,直接對(duì)canvas進(jìn)行操作,性能不好衔蹲,并且有很多限制

OVERLAY_COLOR是在上面蓋了一個(gè)純色的圖層肢娘,達(dá)到圓角的效果,性能好

還有一種實(shí)現(xiàn)舆驶,是使用一個(gè)GradientDrawable橱健,設(shè)置setCornerRadius,用作背景沙廉。目前我不太清楚這種實(shí)現(xiàn)性能上表現(xiàn)怎么樣拘荡,據(jù)說(shuō)在某些機(jī)器上顯示效果不好,有黑邊什么的撬陵,不過(guò)我還沒(méi)有見過(guò)珊皿。

其實(shí)關(guān)于不同方式的對(duì)比,F(xiàn)resco的官方文檔圓角和圓圈里面已經(jīng)寫的很清楚了

當(dāng)使用BITMAP_ONLY(默認(rèn))模式時(shí)的限制:
并非所有的圖片分支部分都可以實(shí)現(xiàn)圓角巨税,目前只有占位圖片和實(shí)際圖片可以實(shí)現(xiàn)圓角蟋定,我們正在努力為背景圖片實(shí)現(xiàn)圓角功能。
只有BitmapDrawable 和 ColorDrawable類的圖片可以實(shí)現(xiàn)圓角草添。我們目前不支持包括NinePatchDrawable和 ShapeDrawable在內(nèi)的其他類型圖片驶兜。(無(wú)論他們是在XML或是程序中聲明的)
動(dòng)畫不能被圓角。
由于Android的BitmapShader的限制远寸,當(dāng)一個(gè)圖片不能覆蓋全部的View的時(shí)候抄淑,邊緣部分會(huì)被重復(fù)顯示,而非留白而晒。對(duì)這種情況可以使用不同的縮放類型(比如centerCrop)來(lái)保證圖片覆蓋了全部的View蝇狼。
OVERLAY_COLOR模式?jīng)]有上述限制,但由于這個(gè)模式使用在圖片上覆蓋一個(gè)純色圖層的方式來(lái)模擬圓角效果倡怎,因此只有在圖標(biāo)背景是靜止的并且與圖層同色的情況下才能獲得較好的效果迅耘。
Drawee 內(nèi)部實(shí)現(xiàn)了一個(gè)CLIPPING模式贱枣。但由于有些Canvas的實(shí)現(xiàn)并不支持路徑剪裁(Path Clipping),這個(gè)模式被禁用了且不對(duì)外開放颤专。并且由于路徑剪裁不支持反鋸齒纽哥,會(huì)導(dǎo)致圓角的邊緣呈現(xiàn)像素化的效果。
總之栖秕,如果生成臨時(shí)bitmap的方法春塌,所有的上述問(wèn)題都可以避免。但是這個(gè)方法并不被支持因?yàn)檫@會(huì)導(dǎo)致很嚴(yán)重的內(nèi)存問(wèn)題簇捍。
綜上所述只壳,在 Android 中實(shí)現(xiàn)圓角效果,沒(méi)有一個(gè)絕對(duì)好的方案暑塑,你必須在上述的方案中進(jìn)行選擇吼句。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市事格,隨后出現(xiàn)的幾起案子惕艳,更是在濱河造成了極大的恐慌,老刑警劉巖驹愚,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件远搪,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡逢捺,警方通過(guò)查閱死者的電腦和手機(jī)谁鳍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蒸甜,“玉大人棠耕,你說(shuō)我怎么就攤上這事∧拢” “怎么了窍荧?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)恨憎。 經(jīng)常有香客問(wèn)我蕊退,道長(zhǎng),這世上最難降的妖魔是什么憔恳? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任瓤荔,我火速辦了婚禮,結(jié)果婚禮上钥组,老公的妹妹穿的比我還像新娘输硝。我一直安慰自己,他們只是感情好程梦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布点把。 她就那樣靜靜地躺著橘荠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪郎逃。 梳的紋絲不亂的頭發(fā)上哥童,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音褒翰,去河邊找鬼贮懈。 笑死,一個(gè)胖子當(dāng)著我的面吹牛优训,可吹牛的內(nèi)容都是我干的朵你。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼型宙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼撬呢!你這毒婦竟也來(lái)了伦吠?” 一聲冷哼從身側(cè)響起妆兑,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎毛仪,沒(méi)想到半個(gè)月后搁嗓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡箱靴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年腺逛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片衡怀。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡棍矛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出抛杨,到底是詐尸還是另有隱情够委,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布怖现,位于F島的核電站茁帽,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏屈嗤。R本人自食惡果不足惜潘拨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望饶号。 院中可真熱鬧铁追,春花似錦、人聲如沸茫船。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至狰闪,卻和暖如春疯搅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背埋泵。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工幔欧, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人丽声。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓礁蔗,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親雁社。 傳聞我的和親對(duì)象是個(gè)殘疾皇子浴井,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,110評(píng)論 25 707
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過(guò)程并不復(fù)雜霉撵,今天將帶大家一窺iOS動(dòng)畫全貌磺浙。在這里你可以看...
    F麥子閱讀 5,110評(píng)論 5 13
  • 有一天撕氧,我們終于長(zhǎng)成了成年人,一個(gè)人呼吸著空氣喇完,一個(gè)人踽踽獨(dú)行在時(shí)間的長(zhǎng)河里伦泥,沒(méi)有他人的打擾,我們一個(gè)人默默的獨(dú)處...
    淑琦記閱讀 1,493評(píng)論 0 3
  • 問(wèn)題描述: 刪除數(shù)組中滿足某一條件的元素锦溪。 上述代碼的結(jié)果顯然是錯(cuò)誤的不脯。原因是arr.enumerated() 返...
    coderzcj閱讀 197評(píng)論 0 0
  • 春意已隨著四季蛻變的輪回已悄然露出嫩芽, 勤勞的楊樹爺爺已在緊隨春天的腳步 在炎炎的夏至到來(lái)之前讓自己的雙臂穿上密...
    微光丸子閱讀 354評(píng)論 0 1