在前面一篇博文《Android高仿京東淘寶自動無限循環(huán)輪播控件的實現(xiàn)思路和過程》中已經(jīng)基本介紹了實現(xiàn)輪播廣告的基本思路和過程,但是仔細(xì)觀察淘寶的輪播廣告欄,發(fā)現(xiàn)在輪播廣告欄的底部有個小小的弧形,為了實現(xiàn)更好的效果,在后期中在自己定義的無限輪播控件中添加了底部弧形的實現(xiàn),在實現(xiàn)的過程中也遇到了一些問題,比較麻煩的就是繪制時弧形出現(xiàn)了鋸齒的問題。
實現(xiàn)弧形的主要代碼以及實現(xiàn)效果(帶有鋸齒的情況)
首先要感謝開源 感謝開源框架 https://github.com/florent37/ArcLayout ,弧形的實現(xiàn)效果是根據(jù)該框架而來,使用 path 來繪制弧形,首先就是要創(chuàng)建好 path 了。
1. 新建 path
1 private Path createClipPath() { 2 final Path path = new Path(); 3 path.moveTo(0, 0); 4 path.lineTo(0, height); 5 path.quadTo(width / 2, height - 2 * arcHeight, width, height); 6 path.lineTo(width, 0); 7 path.close(); 8 9 return path;10 }
2.測量計算
繪制弧形是根據(jù)輪播控件的寬度和高度而來的,所以需要先測量出輪播控件的寬度和高度,并且當(dāng)子 View 的位置和尺寸變化時,需要重新測量繪制。
1 @Override 2 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 3 super.onLayout(changed, left, top, right, bottom); 4 if (changed) { 5 calculateLayout(); 6 } 7 } 8 9 /**10 *calculate layout11 */12 private void calculateLayout() {13 height = getMeasuredHeight();14 width = getMeasuredWidth();15 if (width > 0 && height > 0) {16 17 clipPath = createClipPath();18 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && arcShape != ArcShape.inSide) {19 setOutlineProvider(new ViewOutlineProvider() {20 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)21 @Override22 public void getOutline(View view, Outline outline) {23 outline.setConvexPath(clipPath);24 }25 });26 }27 }28 }
3、繪制弧形
繪制圖形時,有一個控件是很重要的,那就是 Canvas 畫布,也是最后一步,在畫布上面繪制。
1 @Override2 protected void dispatchDraw(Canvas canvas) {3 canvas.save();4 5 canvas.clipPath(clipPath);6 super.dispatchDraw(canvas);7 8 canvas.restore();9 }
4、效果圖
運行代碼,可以看到效果,效果圖如下。
問題
底部的弧形雖然已經(jīng)繪制成功了,但是從效果圖中可以明顯看出弧形帶有鋸齒,效果并不好,再看下現(xiàn)在淘寶的效果,有點困擾了。
解決辦法
在網(wǎng)上查找了資料,也沒有發(fā)現(xiàn)什么好的辦法,最后在 Github 上面找到了答案 https://github.com/florent37/ArcLayout/issues/8。
解決方法并不難,但是需要引入另外一個繪圖工具 —— Paint,通過 Paint 來消除鋸齒,因為 Paint 本身就有自帶的消除鋸齒的方法 paint.setAntiAlias(true),當(dāng)然還需要設(shè)置下 Xfermode,不過和目前網(wǎng)上提供的方法有所不同了,看下面的代碼,修改在畫布 Canvas 中的繪制方法。
1 @Override 2 protected void dispatchDraw(Canvas canvas) { 3 Paint paint = new Paint(); 4 paint.setAntiAlias(true); 5 paint.setColor(Color.WHITE); 6 int saveCount = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG); 7 super.dispatchDraw(canvas); 8 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY)); 9 canvas.drawPath(clipPath, paint);10 canvas.restoreToCount(saveCount);11 paint.setXfermode(null);12 }
最終效果圖
修改代碼后運行,獲得最終效果,已經(jīng)明顯消除了鋸齒,效果優(yōu)美多了,弧形變得光滑了。