“啥是佩奇?” Android 開發者眼裡的佩奇
《啥是佩奇》可謂是年前的一大熱點,所謂熱點就是你在幹嘛,它都能進入你的視線。剛好有看到用Python畫佩奇的,所以就尋思著用Android也畫了一個。

佩奇完工已有些時日,一直想寫篇文章記錄下,奈何拖到現在。限於水平有限,不對的地方,還望斧正。
直接點,咱們先來看一下效果,然後再去想怎麼畫出來。

簡單分析下佩奇,會發現構圖基本由曲線構成的,還有部分使用了圓、橢圓、矩形等常規圖形。
常規圖形我們使用Canvas繪製,曲線部分我們使用Path繪製貝塞爾曲線。
所以這篇文章分為三個模組: 分別介紹Canvas的使用、Path基礎、Path繪製貝塞爾曲線。
1. Canvas回顧
Canvas的使用相對基礎一點,我們來一起通過API回顧下:

具體到每個API就不展開說明了,如有需要可以檢視末尾的參考文章,都有很詳細的介紹,這裡我們畫個鼻子做示例:

圖片有些卡頓,流程還是容易知曉的:
1.繪製一個傾斜的橢圓,進度變化,閉環時上色
2.繪製兩個小圓環,進度變化,閉環時上色
3.為了繪製方便,橢圓和小圓是同時繪製的
分析完成那就開擼吧,具體數值都是yy得來的,我們主要看一下流程步驟和api的使用:

細節註釋都有說明,至於繪製進度百分比,我們這裡使用的 ValueAnimator類。

當只要執行這一個動畫的時候,直接呼叫 animNose.start() 就可以了。
2. Path初識
The Path class encapsulates compound (multiple contour) geometric paths consisting of straight line segments, quadratic curves, and cubic curves. It can be drawn with canvas.drawPath(path, paint), either filled or stroked (based on the paint's Style), or it can be used for clipping or to draw text on a path.
簡單說就是:Path可以通過直線、二次、三次貝塞爾曲線,以及填充描邊模式,做出各種炫酷效果。
Path官方文件直通車
https://developer.android.com/reference/android/graphics/Path
我們還是來一起看一下API:




這裡依舊沒有展開來說,看著比較乾癟無趣,但應該會對Path的能力有所瞭解。
至於詳細使用,可以檢視精彩的參考文章:
Path從懵逼到精通(1)——基本操作
https://www.jianshu.com/p/b872b064d369
3. Path和貝塞爾曲線
3.1 我們先來假裝瞭解一下貝塞爾曲線:
以下內容摘抄自維基百科:
在數學的數值分析領域中,貝塞爾曲線(英語:Bézier curve,亦作“貝塞爾”)是計算機圖形學中相當重要的引數曲線。更高維度的廣泛化貝塞爾曲線就稱作貝茲曲面,其中貝茲三角是一種特殊的例項。
貝塞爾曲線於1962年,由法國工程師皮埃爾·貝茲(Pierre Bézier)所廣泛發表,他運用貝塞爾曲線來為汽車的主體進行設計。貝塞爾曲線最初由保爾·德·卡斯特里奧於1959年運用德卡斯特里奧演算法開發,以穩定數值的方法求出貝塞爾曲線。
一階貝塞爾曲線(線性曲線)


對於一階貝賽爾曲線,我們可以理解為在起點和終點形成的這條直線上,勻速移動的點。
二階貝塞爾曲線


為建構二次貝塞爾曲線,可以中介點Q0和Q1作為由0至1的t:
1.由P0至P1的連續點Q0,描述一條線性貝塞爾曲線。
2.由P1至P2的連續點Q1,描述一條線性貝塞爾曲線。
3.由Q0至Q1的連續點B(t),描述一條二次貝塞爾曲線。
也可以說是: P0Q0 : P1Q1 = P1Q1 : P1P2 = Q0B : Q0Q1 = t
三階貝塞爾曲線


對於三次曲線,可由線性貝塞爾曲線描述的中介點Q0、Q1、Q2,和由二次曲線描述的點R0、R1所建構。
我幫大家把更更高階的貝塞爾曲線省略了...如果你覺得還想繼續深入一下,可以點選原文檢視。
3.2 Path繪製貝塞爾曲線
Android是支援貝塞爾曲線的,但是隻支援到三階,我們來一起了解一下:

這裡我們來畫類似於口哨這麼個玩意:

這裡我們是分為兩部分進行繪製的,第一部分到拐點那裡,是個三階曲線;第二部分是個二階曲線。第一部分的終點就是第二部分的起點。
起點、終點、拐點座標都相對好確定,可是這些控制點的座標怎麼確定吶?
實際專案中我們可以請設計幫忙,通過ps給個大致估算,這裡只是跟著感覺試出來的,所以也就是個大致輪廓,不要介意。
程式碼比較簡單,就是座標點的資訊有點多:

靜態繪製這樣就完工了,可是我們怎麼才能實現動態繪製吶?
3.3 動態繪製貝塞爾曲線(TypeEvaluator估值器的使用)
為了獲取實時的座標,我們需要通過 TypeEvaluator 打造一個屬於我們自己的估值器。
首先我們需要建立一個自己的類,用於記錄各種點資訊和具體操作資訊:

再寫一個類用來記錄Path的相關操作,並且記錄到具體的ViewPoint中:

最後就是我們的關鍵點,通過實現TypeEvaluator介面,來打造我們自己的估值器,最終返回實時的座標。
我們通過泛型傳入ViewPoint類,並且複寫evaluate()方法。
evaluate() 方法共有三個引數,分別是:當前進度、起始資料和終點資料。
具體計算過程則是分清每一種操作類別,然後套計算公式即可。

具體使用如下:

執行下start()操作,就是一個動態繪製的豬頭了:
http://www.10tiao.com/img.do?url=https%3A//mmbiz.qpic.cn/mmbiz_gif/MOu2ZNAwZwNAdOIvzXzqwrKLfibr9MVpnbuYe3xmrIpic34GoP3I0YmjrpkQK7ffvbCtxWIbaZyFv3GjJicn21saA/640%3Fwx_fmt%3Dgif
至於讓所有的動畫連起來繪製,則使用AnimatorSet類,playSequentially()方法是將動畫集合按順序播放。
最後附上小編整理出來的Android相關的學習思維導圖,讓大家有個學習的方向。
Android進階

Android前沿技術

Flutter

移動架構師


需要這些安卓學習資料和麵試資料的大夥需要的關注+點贊+加群:185873940 免費獲取!
群內還有許多免費的關於高階安卓學習資料,包括高階UI、效能優化、架構師課程、 NDK、混合式開發:ReactNative+Weex等多個Android技術知識的架構視訊資料,還有職業生涯規劃及面試指導。