<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
標題說漸變進度條是為了方便理解,這裡本身的專案背景是一款錶盤的分針。
先上圖:
錶盤
周圈藍色的漸變條(分針)就是本次要實現的東西。
首先,熟悉Canvas的朋友應該知道它可以畫出各種形狀,但偏偏沒有一頭是圓的環形(這裡不考慮使用path繪製)。
所以我們不得不把它拆分為2個形狀:圓環與圓.
繪製圓環有很多種方法,比如畫2個圓取補集之類的。這裡直接使用canvas.drawArc()函數來畫。
先看看函數原型:
void drawArc (RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
drawArc()有2個過載函數,此處只用到其一,另一個很是相似,只不過把oval引數換成了具體的4個值。
第一個引數是一個矩形,所繪製的圓環將會是此矩形的內切橢圓。如果給的是正方形那畫出來的就是正圓環了。RectF的建構函式有4個引數分別是left top right bottom,直接看字面意思不是很好理解。其實就是矩形左上和右下2個點的座標。left top分別是左上頂點的x和y,剩下2個同理。
第二引數是開始角度。由於螢幕座標系關係,預設x軸正方向(就是水平向右)為0度。
第三個引數是圓環掃過的角度,順時針為正。
第四個引數比較重要。這裡為true則畫出來的是扇形(即連線圓心),為false畫出來的是圓弧。我們要畫的是圓環,自然填false.
第五個引數就是畫筆了,可以定義顏色粗細(即圓環寬度)等等。漸變問題稍後再說。這裡要主要設定下畫筆的style為stroke,否則畫出來的只有邊框沒有填充。
下面是畫純色圓環的程式碼:
/*為了便於說明,先定義幾個變數*/ float mMinOvalR; //圓環外接矩形邊長的一半 float mMinWidth; //圓環寬度 float mMinOffsetY; //外接矩形top屬性向上的偏移(這個下文會解釋) float degree = 315; //圓弧掃過的角度 //建立畫筆: mMinPaint = new Paint(); mMinPaint.setColor(Color.BLUE); //先隨便給個顏色 mMinPaint.setAntiAlias(true); //啟用抗鋸齒 mMinPaint.setDither(true); //啟用抗顏色抖動(可以讓漸變更平緩) mMinPaint.setStyle(Paint.Style.STROKE); mMinPaint.setStrokeWidth(mMinWidth); //設定寬度 //外接矩形 //由於手錶螢幕是正圓,所以canvas正好是正方形,於是可以用下面方法算出矩形頂點座標。 RectF rect = new RectF(canvas.getWidth() / 2 - mMinOvalR, canvas.getHeight() / 2 - mMinOvalR, canvas.getWidth() - (canvas.getWidth() / 2 - mMinOvalR), canvas.getHeight() - (canvas.getHeight() / 2 - mMinOvalR)); //畫弧 canvas.drawArc(rect, -90, degree, false, mMinPaint);
至此一個不是很好看的圓環就出來了~
這個實現很簡單,只要在頭部畫一個直徑=寬度的圓即可。問題在於這個圓心座標是多少呢?
如圖,根據初等數學知識不難算出,圓弧上的小圓圓心座標
x = rect.left + rect.width() / 2f + mMinOvalR * Math.cos(α)
y = rect.top + rect.height() / 2f + mMinOvalR * Math.sin(α)
於是可以畫出圓圓的頭部:
//定義頭部畫筆 mMinCirclePaint = new Paint(); mMinCirclePaint.setColor(Color.BLUE); mMinCirclePaint.setAntiAlias(true); degree -= 90; //抵消螢幕座標系差異 degree = (float) (Math.PI / 180f * degree); //換成弧度 canvas.drawCircle((float) (rect.left + rect.width() / 2f + mMinOvalR * Math.cos(degree)), //圓心x (float) (rect.top + rect.height() / 2f + mMinOvalR * Math.sin(degree)), //圓心y mMinWidth / 2f, //半徑 mMinCirclePaint);
看到頭部已經變成圓的了。
可以使用Android提供的掃描渲染器SweepGradient實現需要的漸變
關於SweepGradient可以參考 https://www.jb51.net/article/252972.htm
在畫圓弧canvas.drawArc之前加上下面程式碼:
//先建立一個渲染器 SweepGradient mSweepGradient = new SweepGradient(canvas.getWidth() / 2, canvas.getHeight() / 2, //以圓弧中心作為掃描渲染的中心以便實現需要的效果 mMinColors, //這是我定義好的顏色陣列,包含2個顏色:#35C3D7、#2894DD null); //把漸變設定到筆刷 mMinPaint.setShader(mSweepGradient);
加上漸變
漸變效果是有了,但是漸變起始角度似乎有點問題,預設是從0度開始。而這裡作為一個錶盤,需要從-90°開始。可惜並沒有函數來直接指定起始角度。所以只好利用矩陣將整個漸變逆時針轉90°實現需要的效果。
在建立漸變後、設定到筆刷前加入下面程式碼:
//旋轉漸變 Matrix matrix = new Matrix(); matrix.setRotate(-90f, canvas.getWidth() / 2, canvas.getHeight() / 2); mSweepGradient.setLocalMatrix(matrix);
調整漸變角度
OK,這樣漸變就差不多了。
但是小圓很突(nan)兀(kan),只需要把他設定漸變的最後一個顏色即可。
mMinCirclePaint.setColor(mMinColors[1]);
適配小圓顏色
猛一看似乎沒問題了,但如果細看,發現小圓還是有一丟丟突兀。造成這種情況的原因是:圓環到了與小圓重合的時候其實還在漸變過程中,並不是等於漸變終止顏色。真正的漸變終止在360°處(即繞一整圈)。解決方案有2種
一:讓小圓也進行漸變。
二:讓圓環的漸變提前結束。
方法一太複雜,由於小圓不是很大,這裡直接用
方法二就好。
那麼如何控制漸變的位置呢?這就要用到構造漸變器的最後一個引數啦~
最後一個引數是float陣列,元素個數與顏色個數相同。每個元素的取值範圍都是[0,1]用於表示在圓環的位置,0對應0°(起始),1對應360°(結束),且必須單調遞增。每個元素控制著對應顏色往下一顏色漸變的起始位置。若此顏色之前/之後沒有顏色,則顯示純色。
這麼說有點抽象,來看個例子:
假設當前是白→黑漸變。最後一個引數是{ 0.25f, 0.5f }
那麼實際效果是0°90°是純白色,90°180°是漸變過程,180°~360°是純黑色。
這樣是不是可以理解了?
於是掃描漸變器可以這樣建立:
//建立漸變 SweepGradient mSweepGradient = new SweepGradient(canvas.getWidth() / 2, canvas.getHeight() / 2, mMinColors, new float[]{0f, degree / 360f - 0.017f}); // 從圖肉眼不難觀察出半個小圓大概佔了6°的範圍(刻度一格是6°) // 6 / 360 = 0.017 //第一個元素為0表示從0°開始漸變,第二個元素表示漸變提前結束,最後的那一塊是純色。這樣一來便可融為一體。
適配漸變顏色
至此,一個較為完美的漸變環就完成了 真是不容易啊 -.-
想做個進度圈或者Loading動畫的朋友們到此就足夠了。
但是!!!如果你和我一樣做的是錶盤,請繼續往下看。
由於美工手抖或者奇葩的螢幕形狀,背景圖常常難以與程式碼畫的東西完美契合。比如上圖中12與10的位置,明顯偏差了。妄圖讓美工搞定這個問題只能做夢想想,最後這鍋還得程式猿背。
表面上似乎很簡單,只需要修改下圓環的外接矩形RectF即可:
//外切矩形 //在原來基礎上加上了偏移畫素mMinOffsetY用來貼合背景 RectF rect = new RectF(canvas.getWidth() / 2 - mMinOvalR-mMinOffsetY, canvas.getHeight() / 2 - mMinOvalR-mMinOffsetY, canvas.getWidth() - (canvas.getWidth() / 2 - mMinOvalR), canvas.getHeight() - (canvas.getHeight() / 2 - mMinOvalR));
貼合素材
現在12點鐘位置相對來說已經貼合地不錯。此時一個很棘手很複雜的問題又來了:頭部的小圓沒有與圓環貼合準確。
上面那個圖因為偏移不是很嚴重或許還看不出來。那麼請看看下面這個:
誇張的偏移
造成這種錯位的本質原因是:經過微調後的矩形不再是正方形,我們的圓環也不再是正圓而是橢圓,但是小圓圈的位置還是按照正圓計算的,於是造成了的偏離。對症下藥,把小圓位置的計算方法改成橢圓就ok了。
學過初等數學的應該知道,橢圓的計算比正圓複雜很多很多,上面的問題可以抽象成如下數學題目:
已知圖上所有的字母,橢圓是矩形的內切橢圓,求橢圓上的點的座標xy與α的關係。
座標系不允許變換。
最後要寫成x=f(α); y=g(α)的形式
過程我就不寫啦,直接上答案:
x = b + c / 2 * (cosα + 1)
y = a - d / 2 * (sinα - 1)
修正一下畫頭部小圓的程式碼:
//頭部圓 mMinCirclePaint.setColor(isInAmbientMode() ? mMinShimmerColors[1] : mMinColors[1]); degree = 90f - degree; //抵消螢幕座標系差異 degree = (float) (Math.PI / 180f * degree); float a = rect.top, b = rect.left, c = rect.width(), d = rect.height(); canvas.drawCircle((float) (b + c / 2f * (Math.cos(degree) + 1)), (float) (a + -1 * d / 2f * (Math.sin(degree) - 1)), mMinWidth / 2f, mMinCirclePaint);
最終成品
OK,基本上完美了。
以上就是Android Canva實現漸變進度條的詳細內容,更多關於Android Canva漸變進度條的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45