這句話我真的憋了很久。Android 工程師只要關注我,我就能讓你達到大師級水平,不是面試時的吹牛逼水平,不是自我欺騙的瞭解皮毛的水平,是真正的開發實力。之前我有這個自信,沒這個證據。但如今,證據我也有了。java
關注個人人都知道,我這三個多月來一直在網上分享關於 Android 自定義繪製的技術,而且在一週多前舉辦了一場線上的「仿寫酷應用」活動,讓個人粉絲仿寫即刻、薄荷健康、小米運動、Flipboard 這四個軟件中的幾個經典效果,來自我驗證一下這三個月來的學習成果。android
簡單地說,這事兒很成功(臉紅)。git
通過一週的投稿時間,共收到 97 份來自關注者的投稿(真的不少,出乎意料),並且作得都很棒。在四位原開發者的艱難篩選下,每一個效果選出了一位優勝者。下面就是這四位優勝者的做品以及來自各位原開發者對他們的點評。程序員
二話不說,先看結果。github
原效果:面試
仿寫效果:算法
仿得很細緻有沒有。並且,這個仿寫效果看似簡單,實際上是假象。它右邊的數字跳動,是一個字符一個字符跳動替換的,而不是整個字符串一塊兒被替換掉,這個須要對文字繪製的 API 有足夠的熟悉才能作到。編程
這位仿寫者叫劉金偉。在通知劉金偉成爲「被選中的人」後,我對他進行了一個簡短的微信採訪。關於此次仿寫的過程,劉金偉是這樣對我說的:canvas
到此次仿寫活動爲止,HenCoder專欄已經出了8篇View繪製相關的技術文章了,每篇文章認真閱讀以後我也根據例子進行實踐操做,學到的一些東西也在項目開發中得以應用,正如文章中所說,在自定義View相關方面更加自如了。微信
看到此次HenCoder的仿寫活動,就有點躍躍欲試,發現這幾個效果都挺不錯的,和朋友聊了聊以後就選了這個常常會用到的點贊功能進行實踐。這個點贊效果通過我分析發現雖然內部動畫挺多,可是所用到的技術點都是在HenCoder中講到過的,因此在簡單的分析以後就開始寫,大約花了大半天時間就基本完成了,整個過程也沒太多技術難點,作出來後還給朋友炫耀了一番。
最後再次由衷的感謝HenCoder專欄,爲了提高你們技術水平而作的事,很是敬佩。
不謝不謝,哈哈。
對他的做品進行點評的是即刻的 Android Leader 羅瓊。他對這份仿寫的評價彷佛還不錯:
仿寫效果的點評,主要針對如下幾點
- 對原創的還原程度
- 示例的完備程度(可測試性)
- 項目規範
- 代碼實現
對原創的還原程度
這位同窗仔細觀察了即刻點贊效果
- 使用的資源應該是反編譯即刻 apk 以後拿到的
- 實現了點贊和取消點贊兩種效果
- 實現了左邊圖片部分的動畫
- 實現了右邊數字部分的動畫
未實現的部分
- 點贊對 touch 操做的處理(只處理了 click 操做)
- 點贊效果在圖片上的先放大後縮小
- 散開的點的放大效果
- 總體動畫的細節優化
示例的完備程度
這個是作得比較好的
- 能夠直接設置具體數字,這樣方便作邊界條件(進位退位)的測試。
- 上傳了能夠直接安裝的 app-release.apk ,方便先安裝看效果。
- README 有對動畫實現的說明。
項目規範
- 沒有 .idea 這種不應上傳的文件夾
- .gitignore 也是專門修改過的
能夠優化的部分
- 對 android support 包的依賴,不要依賴 alpha 這種版本,儘可能依賴穩定版
- 代碼文件都須要進行格式化,包括 xml
- mdpi 的資源再也不須要了
- 自定義 View 的 attr 的命名,須要有本身的命名空間(前綴)
- 自定義 View 的變量命名不規範,一下子有 m ,一下子有下劃線
代碼實現
做者把圖片和文字寫在一個類裏面了,這樣的話不太靈活,即刻 app 如今在某些主題下的點贊效果不是大拇指,好比逝者這個主題就是蠟燭,因此建議圖片和文字仍是分紅兩個類來搞。
對點擊事件的防重處理好像有點問題,另外連續點擊是否直接對以前動畫進行 cancel 也須要斟酌一下。
總體的實現代碼上冗餘邏輯比較多,而且每個函數內部每一行語句並無徹底去考慮,如對 specMode 的 switch case ,沒有窮盡全部的可能值。
圖片這塊的實現,總體的思路是經過事先畫好各類元素,而後經過屬性動畫的方式,但自定義的屬性動畫的方法是經過反射調用的,整個類裏面並無顯示調用,對於> 此類不是很複雜的動畫,建議仍是用系統自帶的屬性比較好。
文字這塊的實現,涉及到偏移、顏色、以及分離出變化和不變的部分(做者對文字的解剖分析得很好),但代碼的複用程度不高。
整體而言,項目完成度比較高,恭喜得到本次仿寫即刻點贊效果的冠軍,不過真正商用的話仍是有很多須要考慮的,尤爲是代碼規範上須要增強,再好的實現和算法,若是代碼不夠規範,恐怕看得人也會比較累,但願再接再礪。
評價得好詳細啊,我在讀這份點評的過程當中屢次遇到「哇塞好細,若是是個人話這裏確定要被扣分了」的狀況。
依然是先上效果:
原效果:
仿寫效果:
以假亂真了有沒有?
這份仿寫的做者叫嚴積楷。他對仿寫過程的回顧是這樣的:
我以爲仿寫,首先就是要了解清楚仿寫對象的細節,因此仍是本身親自體驗一下比較好,因此就下載了薄荷健康APP,發現尺子UI已經改變了(這樣就提醒了我要作一個適合多變需求的控件),可是一些特性也是和效果圖差很少的:觸摸滑動後是有慣性滾動的光標保持在中間,不隨尺子滾動光標選中的刻度只會是0.1整點讓觸摸滑動、慣性滾動以後,尺子會回滾到最近的整點刻度,如最後滑動到66.5和66.6中間靠右,則回滾到66.6。
瞭解了特性以後,就是想着怎樣實現了:首先就是畫出刻度和數字,這裏是採用一會兒就畫出全部刻度的方法,而後經過滑動方法scrollBy()來移動畫面(不知道這樣系統會不會對尺子那些不在屏幕顯示的部分進行繪畫計算的,我當時是加上滑動以後,發現很能夠滑的流暢,因此就這樣了,如今想一想還能夠處理一下的)。觸摸控制方面,由於以前分析過GestureDetector,瞭解了它的實現,因此這裏就試着直接重寫onTouchEvent()和OverScroller配合實現慣性滑動。對於刻度的計算,這裏經過滑動位置getScrollX()來計算當前刻度,而又經過把滑動結束後的刻度四捨五入以後,計算對應的ScrollX來讓尺子最近的整0.1點刻度。對於光標的繪製,因爲這裏是採用了scrollBy()的方法移動畫面,因此也沒有找到一個好的方法讓光標不隨尺子移動,因此就外層加入一個ViewGroup重寫dispatchDraw()方法在這裏繪製(這個方法執行在onDraw()以後,在這裏繪製纔不會被尺子的刻度覆蓋掉)。
主要的實現思路就是這樣了,還有一些細節,如代碼封裝這些比較常見的就不詳細說了,你們能夠看代碼,已經寫好了註釋,歡迎指教小弟。
「歡迎指教小弟。」高仿到這種程度居然還求指教,這謙虛的態度莫非是討打?有人想當面指教他一下嗎?
對這份做品進行點評,我請到的是薄荷健康的 Android 工程師 loody。
還原度
99分,多一分怕你驕傲。
實現思路
- 背景繪製
頂部基準線+純色背景。- 刻度繪製,包括長、短刻度及長刻度下的文字繪製
這塊是整個捲尺最複雜的部分,整個捲尺有最大最小邊界,因此整個刻度的繪製會基於最大、最小值以及定義的最小刻度單位來從左往右依次繪製,同時要保證當前選中的位置位於屏幕中央。- 基準線繪製
位於屏幕中間、能夠有多種樣式、以上繪製必須按照順序依次繪製。- 手勢滑動處理、慣性滑動
經過監測 MotionEvent 裏的 ACTION_DOWN、ACTION_MOVE、ACTION_UP、ACTION_CANCEL 事件來監測滑動距離來進行重繪,若是知足Fling,則使用OverScroller來計算速度來進行慣性滑動。- 智能精準定位
滑動完以後須要進行精準定位,必須回到基準線最近的刻度,用做者的話就是滑動到66.5和66.6中間靠右,則回滾到66.6。優勢
整個實現的很是好,全部的要點都實現了,特別是精準定位體驗作得很棒,在拓展性方面,也定義了不少自定義屬性,同時也上傳到 Maven 倉庫,方便其餘人調用。
不足之處
- 背景和基準線的繪製和刻度的繪製進行了分離,其實不必,由於他們的繪製並無衝突;
- 在刻度繪製上,屏幕以外的刻度其實能夠不用繪製;
- 捲尺的小刻度模式能夠再豐富一些,通常兩個大刻度之間有10個小刻度,固然也有2個、5個狀況;
- 對外開放的初始化方法應該更豐富一些,由於不少時候咱們的邊界值並非固定的。
薄荷的捲尺效果要實現起來是有很是多的細節的。loody 要從幾十份仿寫中選出這一份,還要寫出這麼細緻的點評,別的我不想說,我只想對他說一句:苦了你了。另外也更想回頭對上面的仿寫者嚴積楷說一句:你太苦了!
原效果:
仿寫效果:
仿得也是超棒。這件仿寫做品的做者叫陳浩,他的仿寫過程回顧充滿了認真和辛酸:
以前沒有太多作UI的經驗,因此一開始我是比較樂觀的,但最後花了整整5個晚上才作完。
我編程屬於比較嚴謹(囉嗦)的那種,因此準備工做時我把gif下下來用電腦逐幀看了,還借了朋友的小米手環來看實際的動畫(最新版有點出入)。而後把動畫流程寫下來,沒有作什麼模塊規劃,就開始編程了。
最開始動手時我只有動畫參數可配置和要作動畫狀態機的這兩個想法,後面整個代碼結構都是在編寫的過程當中屢次重構產生的。畢竟代碼是程序員的第二張臉(我說的),給別人看的時候仍是想寫的更好一些。但這也存在一些過分設計的狀況,致使完成的時間變長了很多。好比,我看到那個轉動的煙花圓環線條不是一成不變的,因而天馬行空設計出來一套的動畫運動公式:這個線條是橢圓的一段圓弧,其圓心,寬和高的偏移都是隨機參數,變化量d由變化速度v決定,變化速度v由外力1.衰減常量力,2.速度平方成正比的阻力,3.定時觸發的隨機力決定(戲真多)。結果致使動畫參數調整就花太多時間,也改了好幾版才穩定下來。。
寫得好的地方的話,由於工做緣由會比較考慮封裝,可維護性,可拓展性這些,這些方面我以爲仍是作到位了的。
說實話,在發佈仿寫徵稿文的時候我就知道,確定每一個效果都有人能完成,但陳浩的這份做品仍是讓我有點意外:你仿得也太真了!但看了他的這份回顧,我以爲我知道爲何他寫得這麼好了。
我很高興請到了這個效果的原做者,來自小米運動團隊的卜冬旭來點評這份做品:
整體評價
至關不錯。。。(原本想這四個字完結點評了的,由於模仿的效果類似度很高了,並且僅憑一個gif圖,在很短的時間作出這樣的效果,真的挺厲害的。同時up主提供的代碼裏的註釋也很清晰,規範,能夠很容易理解實現的原理。可是秉着認(wu)真(ren)負(zi)責(di)的態度, 仍是來吹毛求疵一下。)
細節對比
這塊的動效是小米運動app首頁的效果。示例GIF圖中包含了2部分效果,一個是小米手環鏈接過程當中效果,就是一大堆雜亂的白色漸變的圓圈在轉,圓圈的起始位置有一個日後發散的粒子效果。另外一部分就是小米手環鏈接成功後的效果, 也就是幾個白色透明度不等的漸變的圓環疊加在一塊兒,最外圈層次漸變的光暈效果圍繞圓環轉動。
下面具體分析對比下這幾塊動畫效果.圓圈的疊加效果
我這邊用了8個圓圈,每一個圓圈的
centerX
,centerY
有微小的差異,半徑有微小的差異。經過SweepGradient
來設置它的漸變,從純白到20%左右透明度的白色,每一個圓圈canvas.rotate
的角度也有微小的差異。固然以上全部參數均可以本身任意調節,來達到良莠不齊的效果, 只要總體效果不離譜就能夠了。我對於其中一些參數用的都是random
, 這塊沒有個標準。雜而不亂, 達到這個效果就行. :D粒子效果
比較麻煩的就是這塊粒子效果。一方面要實現功能,一方面性能也要知足,不能卡頓。模仿的效果就這一塊有點小問題, 一個是半徑有點大了,而後透明度能夠稍微降的快一點, 再聚攏一點效果會更好。(壞笑.jpg) 這塊調起來是至關的麻煩。 這塊粒子產生在第一個效果中圓圈的最亮的地方,也就是透明度最低的地方。具體位置能夠從圖中看一下。
![]()
img 粒子產生的位置是豎着的線的位置, 也就是隨機在這條線上生成初始粒子。 發射的角度大概是左邊2個線之間。第一個不是水平線,這兩條線的角度能夠慢慢的調整,從而找到合適的效果。 須要注意一點的就是, 粒子發射的角度須要比較精細的控制, 具體點說就是由於產生粒子的位置不是一個點,而是一條很短的線,因此儘可能不要讓粒子發射的延長線在很短的位置相交, 如圖
。 ![]()
img 關於粒子發生器的原理這裏就不贅述了,我這裏是經過距離超過必定數就從新生成一個粒子來控制的,固然也能夠經過半徑大小或者透明度來控制。Up主是經過透明度來控制的,也是不要緊的。靠近發生器位置的粒子半徑稍微大一點,而後半徑是遞減的。透明度也是遞減的。至於性能問題,也不屬於這個文章的範圍內了。能夠看下up主代碼。
圓環效果
圓環主體是五個漸變的圓環疊加在一塊兒,其實不能算做是圓環,應該是一個圓環和4個橢圓環。 繪製的時候,第一個漸變的圓環正常繪製,後面的橢圓環經過
drawArc
來繪製。保證它們五個環的left
,right
,`bottom
同樣,top
參數爲依次遞增必定的大小。同時須要注意一點的就是顏色最深的圓環,也就是透明度最低的環,不是橢圓環放在最後繪製,這樣能夠蓋住其餘稍高透明度的環,這樣不會看出疊加部分由於用的SweapGradient
致使的疊加的效果。而是會以爲主體是一個整個系統,光暈是獨立系統。否則能比較清楚的看出五個環的疊加效果。多餘的效果
其實那個總體效果,帶有一點上下振動的這塊是由於程序的下拉上推致使的,不屬於這塊的動畫效果,沒想到也給作出來了。(捂臉.jpg)
這塊效果看着挺炫的,其實使用HenCoder裏繪圖的基礎知識就能夠實現,麻煩的地方就在於細節的調整, 可能調個參數就要從新跑一下程序, 仍是至關痛苦的。想了解完整的動畫效果,能夠從仿寫的代碼裏看到, 也能夠來這裏看。
最後居然被冬旭兄弟打了我一個猝不及防的廣告……
原效果:
仿寫效果:
這個效果可謂是人氣超高了。我在以前的幾篇文章或視頻中都展現過這個效果,但只是說「用我教的技術就能實現」,卻沒有展現過具體的實現代碼。不少人找我要實現,我也都沒給過,爲的就是這一天,讓個人讀者本身實現出來,我只幫你展現。
這個仿寫的做者叫賈元斌,它的仿寫過程回顧以下:
仿寫「翻頁效果(增強版)」這個動效的想法,源於凱哥講解幾何變換章節提到的一個動畫栗子,很炫酷,極大地激發了偶的好奇心。
作動畫的過程,其實就是一個典型的「發現問題,分析問題,解決問題」的過程。因此大概的流程就是,先拆解分析,動畫是怎麼「動」的,而後再去解決問題,想如何使用Android提供的Api實現「這麼動」。 把gif圖放在手機上一幀一幀地截屏,而後逐張觀察,能夠發現這個動畫是由三個部分組成的: - 開始動畫,一個Y軸三維旋轉-45度動效 - 中間動畫,比較複雜,圖片右半邊三維旋轉,同時三維旋轉的「轉軸」平面內旋轉了-270度,左半邊圖不變 - 結束動畫,一個繞Y軸三維旋轉30度動效 開始和結束的動畫比較簡單,camera旋轉就能實現,重點分析中間的動畫: 右半邊三維旋轉的時候,canvas先旋轉,再裁切,再使用camera執行三維動效,而後保存camera效果,最後再旋轉回來。問題分析清楚,具體到代碼,拿canvas和camera的幾何變換+範圍裁切,就能實現了。
須要注意的坑:camera執行幾何變換時,咱們會把canvas的中心點移動到原點,因此這個時候canvas再執行其餘變換(好比範圍裁切),要用移動後的座標系計算。 最後一點,不要忘記作糊臉校訂,否則圖片尺寸變大時,就無法看了…
賈元斌在最後提到的「糊臉修正」是我本身造的詞,我以爲好形象啊,佩服本身。
另外,一直找我要實現的,請到文末自取賈兄的源碼。
這個點評者我熟悉,我前同事,來自 Flipboard 的段建華(技術小黑屋),之前我在 Flipboard 的時候我倆挨着坐的。
整體點評
運行效果良好,思路比較清晰。總的來講不錯。
思路與實現
- 在readme文件中給出了具體的實現方案並進行逐步拆分,同時給出了須要的理論分析和一些注意事項
- 提供了在佈局文件中設置圖片資源的實現,同時也支持在代碼中設置。可擴展性較強
- 作到動畫的執行實現與View分離,便於在不修改代碼的狀況下,更改動畫的配置,好比duration和delay時間等
代碼質量
- 配合以必要的註釋,便於理解。
- MainActivity中handler.postDelayed已經位於UI線程,無需在進行runOnUiThread調用
- 對於degreeY等方法使用Keep來註解修飾,既解決了編譯器的報警提示也避免了一些由於Proguard優化刪除無用方法帶來的潛在的問題,這一點體現了做者很周全考慮。
其餘
- 祥雲圖標的Flipboard Logo很贊
- 替代的google_map提供了三種dpi對應的資源,+1
改進與完善
- MapView 類的javadoc寫成「整個動畫拆分紅了三部分」有些不妥,通常爲類的功能介紹
- 每個commit的提交信息都須要歸納修改的內容,不宜出現簡單的update來了事
- View命名成MapView,可能存在繼續優化改善的空間
- Repo的命名建議更加和參賽做品有關,這樣便於篩選人員更好的快速辨識並分發給對應的評委。
看了建華的評價,我最大的感覺就是,他果真仍是這麼認真,一些很細節的地方他也都提到了。另外多是出於謹慎考慮,建華對於這份仿寫實現和 Flipboard 的內部代碼實現沒有進行比對。而我做爲一個已經離職的員工,我就……固然也不會泄露前公司的源碼啦。但我要特別說明一下的是,賈元斌的仿寫代碼中的實現雖然和 Flipboard 的內部實現不徹底同樣,但執行效率和代碼可讀性都不比 Flipboard 的實現差。
至於 Flipboard 的內部實現究竟是怎樣的?我就不告訴你……
上期內容我說過,因爲贊助方爸爸 insight.io 的支持,此次活動的四位優勝者中,還會有一位特別優勝者,他得到的獎品和另外三位不同,他將得到一步 Google Clips 相機:
這位優勝者將經過微博投票得出,投票連接:vote.weibo.com/poll/138417…
幾位仿寫者的仿寫代碼連接在這裏。這裏貼的是 insight.io 從 github 同步的代碼庫,用 insight.io 來讀源碼超級爽(具體怎麼爽,你點開就知道了),真的感謝 insight.io 的在禮物支持以外還給予個人技術支持。
即刻仿寫: insight.io/github.com/…
關於仿寫者劉金偉:
github: github.com/arvinljw
簡書: www.jianshu.com/u/8fcc3372b…
薄荷健康仿寫: insight.io/github.com/…
關於仿寫者嚴積楷:
github: github.com/totond
CSDN: blog.csdn.net/totond
郵箱: yanzhikai_yjk@qq.com
小米運動仿寫: insight.io/github.com/…
關於仿寫者陳浩:
github: github.com/SickWorm
Flipboard 仿寫: insight.io/github.com/…
關於仿寫者賈元斌:
github: github.com/sunnyxibei
微博: weibo.com/812306989
微信: sun521xibei
我的博客: timeriver.com.cn/
想了解幾位點評者,想和他們一塊兒工做?趕快看這裏。
羅瓊給了我一份超長的文案,我嫌長想給他刪點,可又以爲這份文案寫得已經超級棒,哪一句都刪不得,因此乾脆把這份文案最重要的關鍵詞提取了出來,被這些關鍵詞吸引了的能夠點下面的連接進去看詳情:
即刻的關鍵詞:
流浪貓、400 平米、自帶 Gif 表情包文化、健身房、檯球桌、無人機、電玩設備、足球隊、男女比例平衡、年輕、一年兩次免費國內外純玩 Outing、La Marzocco咖啡機 + Volcan 豆(這個看不懂)、咖啡師、Herman Miller人體工學座椅、公費參加 Google IO & WWDC
好吧我只提取了「福利」部分的關鍵詞,由於我最關心這個……其實即刻團隊作的事情更有意思,不過篇幅有限就不給它展現的機會啦(任性臉),有興趣的能夠點連接去看詳情:
哦對了,工做地點上海。
冬旭兄比較委婉地把招聘廣告插進了點評的最後(就是上面那句「想了解完整的動畫效果,能夠從仿寫的代碼裏看到, 也能夠來這裏看」的「這裏」)。不過我仍是要在這裏再貼一次他們的招聘連接,讓須要的人更清楚地看到:
「華米科技」,又是一個米。你猜小米旗下到底有多少種米?
個人老同事建華給我發的「廣告」是這樣的:
這次仿寫的參考目標之一爲 Flipboard 的摺頁效果,Flipboard 中國團隊目前進行了有史以來最特別、動做最大的一次產品升級改版,推出全新產品——紅板報,它將帶來更對味的個性化內容推薦、更廣闊的全球化新聞視野、更生動的雜誌化瀏覽體驗。經過紅板報,要將全球最優質的新聞內容用最好看的方式呈現,精簡產品功能迴歸到閱讀最核心使命:新聞能夠很好看。
嗯,Flipboard 中國改成名紅板報以後,做爲開發者之一的建華很自豪,也很但願推薦給你們用。至於招聘連接……建華表示「什麼招聘連接?」
Flipboard 北京辦公室暫時沒有 Android 職位空缺,因此建華實際上是在給他本身打廣告(哈哈哈我寫了個好 App),你們快去打他呀。
關於招聘,loody 和建華同樣對我表示目前沒有需求,只是告訴我「能提到薄荷健康就最好了」。
只付出不求回報的好同志。好吧,那我就來負責他們的文案吧:
薄荷健康,真呀真健康,裝了薄荷健康,又瘦又健康。耶。
最後很是感謝四位點評者的幫助,此次活動的響應度比個人預期大不少,各位點評者光是審閱投稿就花了一天的時間,審完還要來幫我寫點評語,寫得短的還要被我打回去重寫……真的辛苦了,大家。謝謝!
另外,還要感謝 insight.io 的兩位聯合創始人李崇哲、趙扶搖,在物質和技術上給我提供支持,讓我這第一次本身主持的線上活動少了許多手忙腳亂。固然,也得感謝介紹我與 insight.io 相識的代碼家(怎麼哪兒都有你)。
到這期位置,HenCoder 的自定義 View 系列的繪製部分就結束了,從下期開始,就要開始佈局部分了。按照慣例,官方泄露一點截圖吧:
佈局部分因爲技術的概念比繪製要大得多,因此掌握起來也會難一些,這個各位作好思想準備吧。不過你依然能夠相信一點:就像以前的繪製部分同樣,雖然有不少人已經嘗試過經過看博客、看文檔、讀源碼的方式來學習 Android 的佈局(有不少甚至嘗試過屢次),最終都以「太難了實在學不會」了結,但只要你跟着我走,幾期內容以後,你會發現,一樣的技術,只要到 HenCoder 來學,它怎麼就變得那麼的簡單。
就像本文標題和開頭我說的,關注我,你就能達到大師級水平,這話我憋了很久,如今終於敢說了。由於,我作到了。