中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android?Canva如何實現漸變進度條

發布時間:2022-07-08 13:58:24 來源:億速云 閱讀:364 作者:iii 欄目:開發技術

本篇內容介紹了“Android Canva如何實現漸變進度條”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

前言

標題說漸變進度條是為了方便理解,這里本身的項目背景是一款表盤的分針。先上圖:

Android?Canva如何實現漸變進度條

表盤

周圈藍色的漸變條(分針)就是本次要實現的東西。

1、拆分

首先,熟悉Canvas的朋友應該知道它可以畫出各種形狀,但偏偏沒有一頭是圓的環形(這里不考慮使用path繪制)。
所以我們不得不把它拆分為2個形狀:圓環.

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分別是左上頂點的xy,剩下2個同理。

第二參數是開始角度。由于屏幕坐標系關系,默認x軸正方向(就是水平向右)為0度。

第三個參數是圓環掃過的角度,順時針為正。

第四個參數比較重要。這里為true則畫出來的是扇形(即連接圓心),為false畫出來的是圓弧。我們要畫的是圓環,自然填false.

第五個參數就是畫筆了,可以定義顏色粗細(即圓環寬度)等等。漸變問題稍后再說。這里要主要設置下畫筆的stylestroke,否則畫出來的只有邊框沒有填充。

下面是畫純色圓環的代碼:

/*為了便于說明,先定義幾個變量*/

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);

至此一個不是很好看的圓環就出來了~

Android?Canva如何實現漸變進度條

3、我要圓圓的頭

這個實現很簡單,只要在頭部畫一個直徑=寬度的圓即可。問題在于這個圓心坐標是多少呢?

Android?Canva如何實現漸變進度條

如圖,根據初等數學知識不難算出,圓弧上的小圓圓心坐標

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?Canva如何實現漸變進度條

看到頭部已經變成圓的了。

4、漸變來啦

可以使用Android提供的掃描渲染器SweepGradient實現需要的漸變,在畫圓弧canvas.drawArc之前加上下面代碼:

//先創建一個渲染器
SweepGradient mSweepGradient = new SweepGradient(canvas.getWidth() / 2,
        canvas.getHeight() / 2, //以圓弧中心作為掃描渲染的中心以便實現需要的效果
        mMinColors, //這是我定義好的顏色數組,包含2個顏色:#35C3D7、#2894DD
        null);
//把漸變設置到筆刷
mMinPaint.setShader(mSweepGradient);

Android?Canva如何實現漸變進度條

加上漸變

漸變效果是有了,但是漸變起始角度似乎有點問題,默認是從0度開始。而這里作為一個表盤,需要從-90°開始。可惜并沒有函數來直接指定起始角度。所以只好利用矩陣將整個漸變逆時針轉90°實現需要的效果。

在創建漸變后、設置到筆刷前加入下面代碼:

//旋轉漸變
Matrix matrix = new Matrix();
matrix.setRotate(-90f, canvas.getWidth() / 2, canvas.getHeight() / 2);
mSweepGradient.setLocalMatrix(matrix);

Android?Canva如何實現漸變進度條

調整漸變角度

OK,這樣漸變就差不多了。
但是小圓很突(nan)兀(kan),只需要把他設置漸變的最后一個顏色即可。
mMinCirclePaint.setColor(mMinColors[1]);

Android?Canva如何實現漸變進度條

適配小圓顏色

猛一看似乎沒問題了,但如果細看,發現小圓還是有一丟丟突兀。造成這種情況的原因是:圓環到了與小圓重合的時候其實還在漸變過程中,并不是等于漸變終止顏色。真正的漸變終止在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°開始漸變,第二個元素表示漸變提前結束,最后的那一塊是純色。這樣一來便可融為一體。

Android?Canva如何實現漸變進度條

適配漸變顏色

5、不能嚴絲合縫?逼死強迫癥

由于美工手抖或者奇葩的屏幕形狀,背景圖常常難以與代碼畫的東西完美契合。比如上圖中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));

Android?Canva如何實現漸變進度條

貼合素材

現在12點鐘位置相對來說已經貼合地不錯。此時一個很棘手很復雜的問題又來了:頭部的小圓沒有與圓環貼合準確。

6、治理調皮的小圓

上面那個圖因為偏移不是很嚴重或許還看不出來。那么請看看下面這個:

Android?Canva如何實現漸變進度條

夸張的偏移

造成這種錯位的本質原因是:經過微調后的矩形不再是正方形,我們的圓環也不再是正圓而是橢圓,但是小圓圈的位置還是按照正圓計算的,于是造成了的偏離。對癥下藥,把小圓位置的計算方法改成橢圓就ok了。
學過初等數學的應該知道,橢圓的計算比正圓復雜很多很多,上面的問題可以抽象成如下數學題目:

Android?Canva如何實現漸變進度條

已知圖上所有的字母,橢圓是矩形的內切橢圓,求橢圓上的點的坐標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);

Android?Canva如何實現漸變進度條

“Android Canva如何實現漸變進度條”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

老河口市| 白玉县| 兰州市| 新巴尔虎左旗| 安溪县| 乳山市| 谷城县| 巢湖市| 安阳县| 汾阳市| 永康市| 景宁| 舒城县| 若羌县| 武汉市| 贡嘎县| 颍上县| 博白县| 富平县| 任丘市| 定南县| 莒南县| 济源市| 乐平市| 平原县| 讷河市| 盐城市| 许昌县| 睢宁县| 屯留县| 宁蒗| 祁连县| 城口县| 中方县| 万安县| 呼和浩特市| 望城县| 玉龙| 垫江县| 广灵县| 灵山县|