本來想在網上找個圓角的例子看一看,不盡人意啊,基本都是官方的demo的那張原理圖,稍後會貼出。于是自己自定義了個view,實作圖檔的圓角以及圓形效果。效果圖:
第一個是原圖,第二個是圓形效果,第三第四設定了不同的圓角大小。
準備改變一個部落格的風格,首先給大家講一下原理,讓大家明白了,然後再貼代碼,不然可以直接看那麼長的代碼也比較痛苦,核心代碼其實就那麼幾行:
核心代碼分析:
/**
* 根據原圖和變長繪制圓形圖檔
*
* @param source
* @param min
* @return
*/
private bitmap createcircleimage(bitmap source, int min)
{
final paint paint = new paint();
paint.setantialias(true);
bitmap target = bitmap.createbitmap(min, min, config.argb_8888);
/**
* 産生一個同樣大小的畫布
*/
canvas canvas = new canvas(target);
* 首先繪制圓形
canvas.drawcircle(min / 2, min / 2, min / 2, paint);
* 使用src_in
paint.setxfermode(new porterduffxfermode(porterduff.mode.src_in));
* 繪制圖檔
canvas.drawbitmap(source, 0, 0, paint);
return target;
}
其實主要靠:paint.setxfermode(new porterduffxfermode(porterduff.mode.src_in));這行代碼,為什麼呢,我給大家解釋下,src_in這種模式,兩個繪制的效果疊加後取交集展現後圖,怎麼說呢,咱們第一個繪制的是個圓形,第二個繪制的是個bitmap,于是交集為圓形,展現的是bitmap,就實作了圓形圖檔效果。圓角,其實就是先繪制圓角矩形,是不是很簡單,以後别人再說實作圓角,你就把這一行代碼給他就行了。
從android的示例中,給大家證明一下:
下面有一張porterduff.mode的16中效果圖,咱們的隻是其一:
源碼咱們隻關心誰先誰後繪制的:
canvas.translate(x, y);
canvas.drawbitmap(mdstb, 0, 0, paint);
paint.setxfermode(smodes[i]);
canvas.drawbitmap(msrcb, 0, 0, paint);
paint.setxfermode(null);
canvas.restoretocount(sc);
可以看出先繪制的dst,再繪制的src,最後的展示是srcin那個圖:顯示的區域是二者交集,展示的是src(後者)。和咱們前面結論一緻。效果16種,大家可以自由組合展示不同的效果。
好了,原理和核心代碼解釋完成。下面開始寫自定義view。
1、自定義屬性:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="borderradius" format="dimension" />
<attr name="type">
<enum name="circle" value="0" />
<enum name="round" value="1" />
</attr>
<attr name="src" format="reference"></attr>
<declare-styleable name="customimageview">
<attr name="borderradius" />
<attr name="type" />
<attr name="src" />
</declare-styleable>
</resources>
2、構造中擷取自定義的屬性:
* type_circle / type_round
*/
private int type;
private static final int type_circle = 0;
private static final int type_round = 1;
* 圖檔
private bitmap msrc;
* 圓角的大小
private int mradius;
* 控件的寬度
private int mwidth;
* 控件的高度
private int mheight;
public customimageview(context context, attributeset attrs)
{
this(context, attrs, 0);
}
public customimageview(context context)
this(context, null);
* 初始化一些自定義的參數
*
* @param context
* @param attrs
* @param defstyle
public customimageview(context context, attributeset attrs, int defstyle)
super(context, attrs, defstyle);
typedarray a = context.gettheme().obtainstyledattributes(attrs, r.styleable.customimageview, defstyle, 0);
int n = a.getindexcount();
for (int i = 0; i < n; i++)
int attr = a.getindex(i);
switch (attr)
{
case r.styleable.customimageview_src:
msrc = bitmapfactory.decoderesource(getresources(), a.getresourceid(attr, 0));
break;
case r.styleable.customimageview_type:
type = a.getint(attr, 0);// 預設為circle
case r.styleable.customimageview_borderradius:
type = a.getdimensionpixelsize(attr, (int) typedvalue.applydimension(typedvalue.complex_unit_dip, 10f,
getresources().getdisplaymetrics()));// 預設為10dp
}
a.recycle();
3、onmeasure中擷取控件寬高:
* 計算控件的高度和寬度
@override
protected void onmeasure(int widthmeasurespec, int heightmeasurespec)
// super.onmeasure(widthmeasurespec, heightmeasurespec);
* 設定寬度
int specmode = measurespec.getmode(widthmeasurespec);
int specsize = measurespec.getsize(widthmeasurespec);
if (specmode == measurespec.exactly)// match_parent , accurate
mwidth = specsize;
} else
// 由圖檔決定的寬
int desirebyimg = getpaddingleft() + getpaddingright() + msrc.getwidth();
if (specmode == measurespec.at_most)// wrap_content
{
mwidth = math.min(desirebyimg, specsize);
}
/***
* 設定高度
specmode = measurespec.getmode(heightmeasurespec);
specsize = measurespec.getsize(heightmeasurespec);
mheight = specsize;
int desire = getpaddingtop() + getpaddingbottom() + msrc.getheight();
mheight = math.min(desire, specsize);
setmeasureddimension(mwidth, mheight);
4、根據type繪制:
* 繪制
protected void ondraw(canvas canvas)
switch (type)
// 如果是type_circle繪制圓形
case type_circle:
int min = math.min(mwidth, mheight);
/**
* 長度如果不一緻,按小的值進行壓縮
*/
msrc = bitmap.createscaledbitmap(msrc, min, min, false);
canvas.drawbitmap(createcircleimage(msrc, min), 0, 0, null);
case type_round:
canvas.drawbitmap(createroundconerimage(msrc), 0, 0, null);
/**
* 使用src_in,參考上面的說明
* 根據原圖添加圓角
private bitmap createroundconerimage(bitmap source)
bitmap target = bitmap.createbitmap(mwidth, mheight, config.argb_8888);
rectf rect = new rectf(0, 0, source.getwidth(), source.getheight());
canvas.drawroundrect(rect, 50f, 50f, paint);
好了,我就不解析代碼了,自定義view這是第五篇了,,,,寫得好惡心,,,,
各位贊一個或者留個言,算是對我的支援~