2014年10月16日 星期四

Android 開發 (六十九)DrawerArrowDrawable

我想用過 material design L 的人都看過以下的ui



但是有人想過這個功能要怎麼完成嗎?

前幾天看到ChrisRenke po出了一篇完整分析的文章,他的做法令人非常的驚豔(至少我是如此XD)

接下來我們就來介紹他是如何完成的

首先他針對menu上的三條線做了分析,
from chrisrenke

以上這張,有三個顏色,紅,藍,菊,分別代表著上,中,下,三條線,
所以這張圖可以完整地看出三條線的移動路徑,不過非常的雜亂,所以作者經過整理之後
變成了下面這張圖

from chrisrenke

這張圖其實就是在說明,線實際運作的軌跡,我們可以用下面這張圖來進一步說明,
from chrisrenke

上面較長的黑色橫線就是一開始最上面的那條線,然後結束之後會抵達,斜約45度角的線,
實際上的樣子會是如下圖



一開始是走藍色的路徑,當數值大於0.5的時候就會走黑色的路徑
我想這樣大家應該比較看得懂,他的路徑是怎麼走的了,
既然我們已經了解了他實做的方式,接下來我們就需要在我們的android中實做出來,

首先,我們必須實做上面的兩個圓弧,
so....我們可以利用 path 來完成這個功能,

也就是如下的程式


first = new Path();
first.moveTo(5.042f, 20f);
first.rCubicTo(8.125f, -16.317f, 39.753f, -27.851f, 55.49f, -2.765f);
second = new Path();
second.moveTo(60.531f, 17.235f);
second.rCubicTo(11.301f, 18.015f, -3.699f, 46.083f, -23.725f, 43.456f);
scalePath(first, density);
scalePath(second, density);
joinedA = new JoinedPath(first, second);
first = new Path();
first.moveTo(64.959f, 20f);
first.rCubicTo(4.457f, 16.75f, 1.512f, 37.982f, -22.557f, 42.699f);
second = new Path();
second.moveTo(42.402f, 62.699f);
second.cubicTo(18.333f, 67.418f, 8.807f, 45.646f, 8.807f, 32.823f);
scalePath(first, density);
scalePath(second, density);
joinedB = new JoinedPath(first, second);
topLine = new BridgingLine(joinedA, joinedB);

上面的四個path就代表著藍色黑色弧形,JoinedPath其實只是要方便參照,當值<0.5時參照
JoinedPath的first Path當>0.5時參照second Path,
而其中最關鍵的技巧就是,measureFirst.getPosTan(lengthFirst * parameter, coords, null);
利用這個當 <0.5時,就會去參考 JoinedA的 first Path  與  JoinedB的 first Path的第一個點,

也就是上圖的兩個藍色圓弧的第一個點,也就是橫線時的起始點,
當完成了第一條線,剩下的兩條線也是相同的邏輯,在這裡就不再多提

只能說想出這個解法的人真的很厲害,相信他花了很多時間才完成這個功能,不過同時
我們也從他的這個方法中學到如何利用path以及param的改變,來改變view.

真的是獲益良多!!~  最後歡迎有興趣的各位可以去參考他的source code

http://chrisrenke.com/drawerarrowdrawable/
https://github.com/ChrisRenke/DrawerArrowDrawable

沒有留言:

張貼留言