Android利用Xfermode剪裁圓角
通常的圖片圓角一般是對(duì)單獨(dú)的圖片進(jìn)行切圓角操作,但是像下圖的效果就沒那么合適了,雖然對(duì)單張圖片切圓角也能實(shí)現(xiàn),但更為繁瑣、不簡(jiǎn)潔,因?yàn)閿?shù)據(jù)內(nèi)容是動(dòng)態(tài)的,要根據(jù)數(shù)據(jù)源分很多種情況判斷哪張圖片該切哪個(gè)角。
所以,我在想能不能就在外層容器的四個(gè)角切圓角而不用管內(nèi)部圖片的圓角情況呢?答案顯然是能!主要思路就是自定義一個(gè)layout,在dispatchDraw的時(shí)候?qū)?shù)據(jù)圖片的canvas與圓角bitmap混合,設(shè)置Xfermode為PorterDuff.Mode.DST_IN使交集部分展示即可達(dá)到圖示的效果
關(guān)鍵代碼(根據(jù)后臺(tái)數(shù)據(jù)生成里面的每個(gè)item相關(guān)代碼沒有貼,根據(jù)業(yè)務(wù)場(chǎng)景改變即可):
public class HotCityView extends LinearLayout { ? ? private LinearLayout ll_item_container1, ll_item_container2; ? ? private int itemH, itemSpace; ? ? private int padding; ? ? private Paint clipPaint; ? ? private RectF clipRect; ? ? private Bitmap maskBitmap; ? ? private int cornerSize; ? ? public HotCityView(@NonNull Context context) { ? ? ? ? this(context, null); ? ? } ? ? public HotCityView(@NonNull Context context, @Nullable AttributeSet attrs) { ? ? ? ? this(context, attrs, 0); ? ? } ? ? public HotCityView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) { ? ? ? ? super(context, attrs, defStyle); ? ? ? ? setOrientation(VERTICAL); ? ? ? ? inflate(context, R.layout.m_layout_hot_city, this); ? ? ? ? padding = (int) getResources().getDimension(R.dimen.list_lr_margin1); ? ? ? ? setPadding(padding, 0, padding, 0); ? ? ? ? itemH = PixelUtil.dp2px(109); ? ? ? ? itemSpace = (int) getResources().getDimension(R.dimen.hot_item_space); ? ? ? ? cornerSize = PixelUtil.dp2px(8); ? ? ? ? ll_item_container1 = findViewById(R.id.m_hot_city_item_container1); ? ? ? ? ll_item_container2 = findViewById(R.id.m_hot_city_item_container2); ? ? ? ? clipPaint = new Paint(Paint.ANTI_ALIAS_FLAG); ? ? ? ? clipPaint.setStyle(Paint.Style.FILL); ? ? } ? ? @Override ? ? protected void dispatchDraw(Canvas canvas) { ? ? ? ? if (clipRect == null || getMeasuredWidth() == 0) { ? ? ? ? ? ? clipRect = new RectF(padding, 0, getMeasuredWidth() - padding, getMeasuredHeight()); ? ? ? ? ? ? maskBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_4444); ? ? ? ? ? ? Canvas c = new Canvas(maskBitmap); ? ? ? ? ? ? //在蒙版上畫需要覆蓋的圖形 ? ? ? ? ? ? c.drawRoundRect(clipRect, cornerSize, cornerSize, clipPaint); ? ? ? ? } ? ? ? ? //保存還沒有繪制之前的圖層 ? ? ? ? int layerId = canvas.saveLayer(clipRect, clipPaint, Canvas.ALL_SAVE_FLAG); ? ? ? ? //繪制底部圖層 ? ? ? ? super.dispatchDraw(canvas); ? ? ? ? //設(shè)置混合模式,實(shí)現(xiàn)view的四個(gè)圓角 ? ? ? ? clipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); ? ? ? ? canvas.drawBitmap(maskBitmap, 0, 0, clipPaint); ? ? ? ? clipPaint.setXfermode(null); ? ? ? ? //恢復(fù)之前的圖層,要不然背景是黑色的 ? ? ? ? canvas.restoreToCount(layerId); ? ? } ? ? //這種方式也可以實(shí)現(xiàn)裁剪效果,但是需要5.0以上 ? ? private void clipRoundView() { ? ? ? ? if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { ? ? ? ? ? ? ViewOutlineProvider viewOutlineProvider = new ViewOutlineProvider() { ? ? ? ? ? ? ? ? @Override ? ? ? ? ? ? ? ? public void getOutline(View view, Outline outline) { ? ? ? ? ? ? ? ? ? ? //修改outline為特定形狀 ? ? ? ? ? ? ? ? ? ? outline.setRoundRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), cornerSize); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }; ? ? ? ? ? ? //重新設(shè)置形狀 ? ? ? ? ? ? setOutlineProvider(viewOutlineProvider); ? ? ? ? ? ? //添加背景或者是ImageView的時(shí)候失效,添加如下設(shè)置 ? ? ? ? ? ? setClipToOutline(true); ? ? ? ? } ? ? } }
附各種Xfermode的效果(這張圖太經(jīng)典了,按照命名規(guī)則其實(shí)很容易理解,無需記住,到用的時(shí)候查閱即可):
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- android 實(shí)現(xiàn)圓角圖片解決方案
- Android中TextView顯示圓圈背景或設(shè)置圓角的方法
- Android關(guān)于Glide的使用(高斯模糊、加載監(jiān)聽、圓角圖片)
- Android圖片特效:黑白特效、圓角效果、高斯模糊
- Android開發(fā)使用自定義View將圓角矩形繪制在Canvas上的方法
- Android中實(shí)現(xiàn)EditText圓角的方法
- Android中Glide加載圓形圖片和圓角圖片實(shí)例代碼
- android 設(shè)置圓角圖片實(shí)現(xiàn)代碼
- Android自定義控件之圓形、圓角ImageView
- Android實(shí)現(xiàn)圓角矩形和圓形ImageView的方式
相關(guān)文章
Android編程之簡(jiǎn)單啟動(dòng)畫面實(shí)現(xiàn)方法
這篇文章主要介紹了Android編程之簡(jiǎn)單啟動(dòng)畫面實(shí)現(xiàn)方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了開機(jī)啟動(dòng)畫面的制作步驟及布局、Activity跳轉(zhuǎn)、權(quán)限控制等的相關(guān)操作技巧,需要的朋友可以參考下2016-11-11Android實(shí)戰(zhàn)打飛機(jī)游戲之子彈生成與碰撞以及爆炸效果(5)
這篇文章主要為大家詳細(xì)介紹了Android實(shí)戰(zhàn)打飛機(jī)游戲之子彈生成與碰撞以及爆炸效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-07-07Android中WebView加載網(wǎng)頁設(shè)置進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了Android中WebView加載網(wǎng)頁設(shè)置進(jìn)度條的相關(guān)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04Android運(yùn)行時(shí)權(quán)限終極方案(PermissionX)
這篇文章主要介紹了Android運(yùn)行時(shí)權(quán)限終極方案(PermissionX),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05android Animation監(jiān)聽器AnimationListener的使用方法)
AnimaitonListener的使用方法主要是在Animation上設(shè)置一個(gè)監(jiān)聽器,下面通過一個(gè)實(shí)例說明它的使用方法2013-11-11一個(gè)強(qiáng)大的側(cè)滑菜單控件ASwipeLayout
這篇文章主要為大家詳細(xì)介紹了強(qiáng)大的側(cè)滑菜單控件ASwipeLayout使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08Android來電監(jiān)聽和去電監(jiān)聽實(shí)現(xiàn)代碼
本文是關(guān)于來點(diǎn)監(jiān)聽和去電監(jiān)聽展開問題,通過實(shí)例代碼講解,對(duì)android來電監(jiān)聽和去電監(jiān)聽的相關(guān)知識(shí)感興趣的朋友一起看看吧2017-06-06Android學(xué)習(xí)筆記(一)環(huán)境安裝及第一個(gè)hello world
最近在學(xué)習(xí)安卓開發(fā),記錄下環(huán)境安裝和第一個(gè)hello world的誕生過程,希望對(duì)大家有所幫助2014-07-07Android判斷11位手機(jī)號(hào)碼的方法(正則表達(dá)式)
項(xiàng)目里頭需要做一個(gè)判斷用戶輸入的號(hào)碼是否是正確的手機(jī)號(hào)碼,正確的手機(jī)號(hào)碼應(yīng)該是11位的,這里我們需要用一個(gè)正則表達(dá)式來進(jìn)行判斷,下面我把寫法分享給大家2016-12-12