Android自定義view Path 的高級(jí)用法之搜索按鈕動(dòng)畫(huà)
關(guān)于Path之前寫(xiě)的也很多了,例如path繪制線,path繪制一階,二階和三階貝塞爾路徑,這些都是path的基本用法。今天我要帶大家看的是Path 的高級(jí)用法,先上圖,再吹。

效果大致是這樣的??粗遣皇峭谩T挷欢嗾f(shuō),切入正題:
既然今天要談Path的高級(jí)用法,那就先來(lái)講一講(Path -- 中文 )就是“路徑”既然是路徑,從我們面向?qū)ο蟮南敕ǖ脑?,我們就容易想?路徑 的長(zhǎng)度,路徑的某一點(diǎn)等。想到這里我們就引出今天 的主要 類--------PathMeasure,字面意思很容易理解--翻譯成 路徑測(cè)量。對(duì)這就是我們用來(lái)測(cè)量路徑的類。既然是一個(gè)類,我們就要看他集體有哪些方法和屬性。
1.構(gòu)造方法:
一個(gè)是有參數(shù),一個(gè)無(wú)參數(shù)。
無(wú)參數(shù)就很容易理解就是直接創(chuàng)建對(duì)象,那有參數(shù)呢?
PathMeasure(Path path, boolean forceClosed) ;第一個(gè)參數(shù) Path 咿 !這不就是我們的Path 了嗎。對(duì)既然是測(cè)量類,那就是要確定需要測(cè)量的那個(gè)路徑,那第二個(gè)參數(shù)呢?
第二個(gè)參數(shù)是用來(lái)確保 Path 閉合,如果設(shè)置為 true, 則不論之前Path是否閉合,都會(huì)自動(dòng)閉合該 Path(如果Path可以閉合的話)。
2.方法:
這方法還挺多,都是干啥的呢?就找?guī)讉€(gè)重要的,常用的講講:
第一個(gè)那就是 setPath(Path path, boolean forceClosed)
這方法一看就知道設(shè)置path 路徑的,就是如果我們創(chuàng)建 PathMeasure,時(shí)用的是無(wú)參的構(gòu)造方法時(shí) ,這時(shí)候就要用此方法,告訴PathMeasure 當(dāng)前需要測(cè)量的是哪一個(gè)path路徑。(個(gè)人喜歡用無(wú)參,比較靈活)。
第二個(gè)那就是getLength(),很容易理解就是 獲得 path 的總長(zhǎng)度。
第三個(gè):getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo),這個(gè)方法非常重要,截取片段,截取的結(jié)果就是,我們的path路徑。參數(shù)也很好理解。第一個(gè)是開(kāi)始的距離,第二個(gè)是結(jié)束的距離(相對(duì)于起點(diǎn)==既然是起點(diǎn),我們?cè)趺凑宜麄兊钠瘘c(diǎn)呢,其實(shí)就是我們繪制圖畫(huà)筆開(kāi)始的哪一點(diǎn))。第三個(gè)參數(shù)就是返回的路徑。第四個(gè)參數(shù)起始點(diǎn)是否使用 moveTo 用于保證截取的 Path 第一個(gè)點(diǎn)位置不變。
第四個(gè):getPosTan(float distance, float[] pos, float[] tan),這個(gè)也是非常重要的,為什么呢?聽(tīng)我解釋一下他的參數(shù)就知道了。第一個(gè)參數(shù)是距離(相對(duì)于繪制起點(diǎn)的路徑距離),第二個(gè)參數(shù)是距離起點(diǎn)的坐標(biāo)點(diǎn),第三個(gè)參數(shù)返回的是正玄函數(shù)tan@角度。
對(duì)這些參數(shù)了解之后下面就來(lái)講解我們今天的例子:
首先我們先來(lái)個(gè)簡(jiǎn)單的:例如

如圖這樣的分析過(guò)程:

1.首先繪制一個(gè)圓(藍(lán)色的),從45度開(kāi)始繪制,注意圓的起點(diǎn)。
2.同圓心繪制大圓(輔助圓)用來(lái)輔助繪制藍(lán)色的線。
3.通過(guò)getPosTan(float distance, float[] pos, float[] tan)方法得到兩個(gè)圓的終點(diǎn)的坐標(biāo)。
4.利用lineTo(x,y)繪制線。就得到我們的搜索圖形了。
5.接下來(lái)就是實(shí)時(shí) 截取片段。getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo),截取從距離0到getlength();這樣就產(chǎn)生了一個(gè)動(dòng)態(tài)的效果了。
看代碼:
關(guān)于畫(huà)筆,canvas畫(huà)布,valueanimator動(dòng)畫(huà),這些請(qǐng)看之前的博客,都有詳細(xì)講解。
public class MySearch extends View {
Paint paint;
Path searchPath; //搜索的圓
Path ciclePath; //外圓
//獲得寬高
int w;
int h;
//這是保存截取時(shí),返回的坐標(biāo)點(diǎn)
float serpos[];
float cicpos[];
//測(cè)量 path 的類
PathMeasure measure;
//動(dòng)畫(huà)產(chǎn)生的實(shí)時(shí)數(shù)據(jù)
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();
//初始化數(shù)據(jù)
serpos = new float[2];
cicpos = new float[2];
//畫(huà)筆
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setDither(true);
paint.setStrokeWidth(6);
paint.setAntiAlias(true);
//初始化路徑
initPath();
//初始化動(dòng)畫(huà)
initAnimator();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//移動(dòng)畫(huà)布的遠(yuǎn)點(diǎn)到屏幕中心
canvas.translate(w/2,h/5);
paint.setColor(Color.BLUE);
//這是截取方法返回的路徑
Path dra = new Path();
//解除硬件加速,不然沒(méi)效果
dra.reset();
dra.lineTo(0,0);
//設(shè)置當(dāng)前需要測(cè)量的path
measure.setPath(searchPath,false);
//開(kāi)始截取
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);
//測(cè)量類
measure = new PathMeasure();
measure.setPath(searchPath,false);
//獲取坐標(biāo)
measure.getPosTan(0,serpos,null);
measure.setPath(ciclePath,false);
//獲取坐標(biāo)
measure.getPosTan(0,cicpos,null);
//根據(jù)兩點(diǎn)坐標(biāo)繪制線
searchPath.lineTo(cicpos[0],cicpos[1]);
}
/**
* 初始化動(dòng)畫(huà)
*/
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();
}
}
第一個(gè)圖大家學(xué)會(huì)了,去練習(xí)一下吧!
相關(guān)文章
Android如何實(shí)現(xiàn)掃描和生成二維碼
這篇文章主要為大家詳細(xì)介紹了Android如何實(shí)現(xiàn)掃描和生成二維碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05
Android Studio 3.0上分析內(nèi)存泄漏的原因
本篇文章主要介紹了Android Studio 3.0上分析內(nèi)存泄漏的原因,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11
Android中activity處理返回結(jié)果的實(shí)現(xiàn)方式
這篇文章主要介紹了Android中activity處理返回結(jié)果的實(shí)現(xiàn)方式,為了實(shí)現(xiàn)這個(gè)功能,Android提供了一個(gè)機(jī)制,跳轉(zhuǎn)到其他activity時(shí),再返回,可以接受到其他activity返回的值,無(wú)需再start新的當(dāng)前activity。需要的朋友可以參考下2016-12-12
Android實(shí)現(xiàn)監(jiān)聽(tīng)電話呼叫狀態(tài)的方法
這篇文章主要介紹了Android實(shí)現(xiàn)監(jiān)聽(tīng)電話呼叫狀態(tài)的方法,涉及Android權(quán)限控制及電話狀態(tài)監(jiān)聽(tīng)的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10
Android自定View流式布局根據(jù)文字?jǐn)?shù)量換行
這篇文章主要為大家詳細(xì)介紹了Android自定View流式布局,根據(jù)文字?jǐn)?shù)量換行,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12
Android實(shí)現(xiàn)的仿淘寶購(gòu)物車demo示例
這篇文章主要介紹了Android實(shí)現(xiàn)的仿淘寶購(gòu)物車demo示例,結(jié)合實(shí)例形式分析了Android購(gòu)物車的功能、布局及邏輯實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-07-07
Android開(kāi)發(fā)之Notification手機(jī)狀態(tài)欄通知用法實(shí)例分析
這篇文章主要介紹了Android開(kāi)發(fā)之Notification手機(jī)狀態(tài)欄通知用法,結(jié)合實(shí)例形式分析了Android Notification手機(jī)狀態(tài)欄通知的常見(jiàn)函數(shù)、功能及使用技巧,需要的朋友可以參考下2019-03-03
Flutter中嵌入Android 原生TextView實(shí)例教程
這篇文章主要給大家介紹了關(guān)于Flutter中嵌入Android 原生TextView的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Android自定義View實(shí)現(xiàn)雪花特效
這篇文章主要為大家詳細(xì)介紹了Android自定義View實(shí)現(xiàn)雪花特效,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02
Flutter利用ORM框架管理數(shù)據(jù)庫(kù)詳解
使用?ORM?框架最大的好處是簡(jiǎn)化了數(shù)據(jù)庫(kù)維護(hù)的代碼量,使得我們可以專注于業(yè)務(wù)代碼實(shí)現(xiàn)。本篇,我們看看如何使用ORM框架管理數(shù)據(jù)庫(kù)版本遷移,需要的可以參考一下2023-04-04

