Android自定義view --Path 的高階用法之-搜尋按鈕動畫
關於Path之前寫的也很多了,例如path繪製線,path繪製一階,二階和三階貝塞爾路徑,這些都是path的基本用法。今天我要帶大家看的是Path 的高階用法,先上圖,再吹。
效果大致是這樣的。看著是不是挺好。話不多說,切入正題:
既然今天要談Path的高階用法,那就先來講一講(Path -- 中文 )就是“路徑”既然是路徑,從我們物件導向的想法的話,我們就容易想到 路徑 的長度,路徑的某一點等。想到這裡我們就引出今天 的主要 類--------PathMeasure,字面意思很容易理解--翻譯成 路徑測量。對這就是我們用來測量路徑的類。既然是一個類,我們就要看他集體有哪些方法和屬性。
1.構造方法:
方法名 | 釋義 |
---|---|
PathMeasure() | 建立一個空的PathMeasure |
PathMeasure(Path path, boolean forceClosed) | 建立 PathMeasure 並關聯一個指定的Path(Path需要已經建立完成)。 |
無引數就很容易理解就是直接建立物件,那有引數呢?
PathMeasure(Path path, boolean forceClosed) ;第一個引數 Path 咿 !這不就是我們的Path 了嗎。對既然是測量類,那就是要確定需要測量的那個路徑,那第二個引數呢?
第二個引數是用來確保 Path 閉合,如果設定為 true, 則不論之前Path是否閉合,都會自動閉合該 Path(如果Path可以閉合的話)。
2.方法:
返回值 | 方法名 | 釋義 |
---|---|---|
void | setPath(Path path, boolean forceClosed) | 關聯一個Path |
boolean | isClosed() | 是否閉合 |
float | getLength() | 獲取Path的長度 |
boolean | nextContour() | 跳轉到下一個輪廓 |
boolean | getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo) | 擷取片段 |
boolean | getPosTan(float distance, float[] pos, float[] tan) | 獲取指定長度的位置座標及該點切線值 |
boolean | getMatrix(float distance, Matrix matrix, int flags) | 獲取指定長度的位置座標及該點Matrix |
第一個那就是 setPath(Path path, boolean forceClosed)
這方法一看就知道設定path 路徑的,就是如果我們建立 PathMeasure,時用的是無參的構造方法時 ,這時候就要用此方法,告訴PathMeasure 當前需要測量的是哪一個path路徑。(個人喜歡用無參,比較靈活)。
第二個那就是getLength(),很容易理解就是 獲得 path 的總長度。
第三個:getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo),這個方法非常重要,擷取片段,擷取的結果就是,我們的path路徑。引數也很好理解。第一個是開始的距離,第二個是結束的距離(相對於起點==既然是起點,我們怎麼找他們的起點呢,其實就是我們繪製圖畫筆開始的哪一點)。第三個引數就是返回的路徑。第四個引數起始點是否使用 moveTo 用於保證擷取的 Path 第一個點位置不變。
第四個:getPosTan(float distance, float[] pos, float[] tan),這個也是非常重要的,為什麼呢?聽我解釋一下他的引數就知道了。第一個引數是距離(相對於繪製起點的路徑距離),第二個引數是距離起點的座標點,第三個引數返回的是正玄函式tan@角度。
對這些引數瞭解之後下面就來講解我們今天的例子:
首先我們先來個簡單的:例如
如圖這樣的分析過程:
1.首先繪製一個圓(藍色的),從45度開始繪製,注意圓的起點。
2.同圓心繪製大圓(輔助圓)用來輔助繪製藍色的線。
3.通過getPosTan(float distance, float[] pos, float[] tan)方法得到兩個圓的終點的座標。
4.利用lineTo(x,y)繪製線。就得到我們的搜尋圖形了。
5.接下來就是實時 擷取片段。getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo),擷取從距離0到getlength();這樣就產生了一個動態的效果了。
看程式碼:
關於畫筆,canvas畫布,valueanimator動畫,這些請看之前的部落格,都有詳細講解。
public class MySearch extends View { Paint paint; Path searchPath; //搜尋的圓 Path ciclePath; //外圓 //獲得寬高 int w; int h; //這是儲存擷取時,返回的座標點 float serpos[]; float cicpos[]; //測量 path 的類 PathMeasure measure; //動畫產生的實時資料 float value; public MySearch(Context context) { this(context,null); } public MySearch(Context context, @Nullable AttributeSet attrs) { this(context,attrs,0); } public MySearch(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //獲得螢幕的寬高 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); w = wm.getDefaultDisplay().getWidth(); h = wm.getDefaultDisplay().getHeight(); //初始化資料 serpos = new float[2]; cicpos = new float[2]; //畫筆 paint = new Paint(); paint.setStyle(Paint.Style.STROKE); paint.setDither(true); paint.setStrokeWidth(6); paint.setAntiAlias(true); //初始化路徑 initPath(); //初始化動畫 initAnimator(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //移動畫布的遠點到螢幕中心 canvas.translate(w/2,h/5); paint.setColor(Color.BLUE); //這是擷取方法返回的路徑 Path dra = new Path(); //解除硬體加速,不然沒效果 dra.reset(); dra.lineTo(0,0); //設定當前需要測量的path measure.setPath(searchPath,false); //開始擷取 boolean s = measure.getSegment(measure.getLength()*value,measure.getLength(),dra,true); //繪製路徑 canvas.drawPath(dra,paint); } /** * 初始化路徑 */ public void initPath(){ paint.setColor(Color.BLUE); //搜尋的圓 searchPath = new Path(); RectF rectF = new RectF(-50,-50,50,50); searchPath.addArc(rectF,45,359.9f); //輔助圓 ciclePath = new Path(); RectF rectF1 = new RectF(-100,-100,100,100); ciclePath.addArc(rectF1,45,359.9f); //測量類 measure = new PathMeasure(); measure.setPath(searchPath,false); //獲取座標 measure.getPosTan(0,serpos,null); measure.setPath(ciclePath,false); //獲取座標 measure.getPosTan(0,cicpos,null); //根據兩點座標繪製線 searchPath.lineTo(cicpos[0],cicpos[1]); } /** * 初始化動畫 */ public void initAnimator(){ ValueAnimator animator = ValueAnimator.ofFloat(0,1); animator.setDuration(2600); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { value = (float) animation.getAnimatedValue(); postInvalidate(); } }); animator.start(); } }
第一個圖大家學會了,去練習一下吧!
相關文章
- 【Android自定義View】繪圖之Path篇(二)AndroidView繪圖
- Android自定義View播放Gif動畫AndroidView動畫
- Android 自定義View之下雨動畫AndroidView動畫
- Android 自定義View:屬性動畫(六)AndroidView動畫
- Android 自定義 View 之 LeavesLoadingAndroidView
- Android自定義View之Canvas的使用AndroidViewCanvas
- LabVIEW的自定義按鈕View
- 【朝花夕拾】Android自定義View篇之(十一)View的滑動,彈性滑動與自定義PagerViewAndroidView
- Android進階——自定義View之雙向選擇SeekbarAndroidView
- Android自定義View之捲尺AndroidView
- Android進階:九、自定義View之手寫Loading動效AndroidView
- Android自定義View:View(二)AndroidView
- Android進階系列:八、自定義View之音訊抖動動效AndroidView音訊
- Android 自定義 View 實戰之 PuzzleViewAndroidView
- Android 自定義 View 之入門篇AndroidView
- Android自定義view之emoji鍵盤AndroidView
- Android 自定義View 滑動解鎖AndroidView
- [Android]多層波紋擴散動畫——自定義View繪製Android動畫View
- HenCoder Android 自定義 View 1-6: 屬性動畫(上手篇)AndroidView動畫
- Android自定義View整合AndroidView
- Android自定義View之定點寫文字AndroidView
- 使用自定義 View 繪製一個懸浮式可拖拽按鈕View
- Qt QMessageBox::information 自定義按鈕QTORM
- Android自定義View之Window、ViewRootImpl和View的三大流程AndroidView
- 自定義View事件之進階篇(四)-自定義Behavior實戰View事件
- Android自定義view之實現帶checkbox的SnackbarAndroidView
- Android自定義view-自繪ViewAndroidView
- Android開發進階——自定義View的使用及其原理探索AndroidView
- 如何自定義radio按鈕的樣式
- 【朝花夕拾】Android自定義View篇之(四)自定義View的三種實現方式及自定義屬性詳解AndroidView
- Android自定義View之區塊選擇器AndroidView
- Android自定義View之requestLayout方法和invalidate方法AndroidView
- Android自定義View之invalidate方法和postInvalidate方法AndroidView
- 【Android自定義View】繪圖之文字篇(三)AndroidView繪圖
- 重拾Android自定義ViewAndroidView
- Android自定義View:ViewGroup(三)AndroidView
- android自定義view(自定義數字鍵盤)AndroidView
- 【Android】 給我一個Path,還你一個動畫ViewAndroid動畫View
- iOS 自定義鍵盤字母按鈕iOS