發現了愛神的自定義view系列,我只想說一個字:凸(艸皿艸 ) !!相見恨晚啊,早看到就不會走這么多彎路了
另外相比之下我這完全是小兒科。。所以不說了,這篇是本系列完結篇....我要從零開始跟隨愛哥腳步去學自定義view了:[愛哥自定義view專題](http://blog.csdn.net/column/details/androidcustomview.html)
然后要說的就是 ?之前的博客都犯了很嚴重的錯誤,那就是不要在onDraw里new東西,不要在onDraw里new東西,不要在onDraw里new東西。重要的話說三遍。
上一篇介紹了[ qq未讀消息提醒去除效果的簡化實現](http://blog.csdn.net/wingichoy/article/details/50503630),不知道小伙伴們掌握的怎么樣了。
轉載請注明出處:http://write.blog.csdn.net/postedit/50503858
今天帶給大家一個很熟悉的東西,當當當當,就是微信下拉眼睛的實現了。 先看效果圖:

自評相似度 ?80% ?哈哈= ?= 。
用我們一貫的方法來剖析這個view。
首先 從內到外:
1.內部其實是兩段弧,只不過在改變畫筆的寬度。
2.中間是個圓,一直在改變透明度。
3.最外面是兩條貝塞爾曲線(重點加難點)。
首先來畫靜態的眼睛。按照順序,相信你已經輕車熟路:
~~~
mPaint.setStrokeWidth(10);
canvas.drawArc(mRectF, 180, 10, false, mPaint);
canvas.drawArc(mRectF, 205, 25, false, mPaint);
//畫圓圈
mPaint.setStrokeWidth(2);
canvas.drawCircle(225, 225, 40, mPaint);
canvas.drawPath(mPath, mPaint);
~~~
這樣就畫出了眼珠的靜態部分,然后根據我們的percent大法,分三個階段**:1.弧變粗 ?2.圓圈透明度改變 ?3.貝塞爾區限 起點,終點,輔助點改變**。
那么將這三個階段用同一個percent來控制 ?0-33為1階段 ?33-66為2階段 66-100為3階段:
意外收獲:當setStrokeWidth 為0時,實際上不是0.
~~~
if(mPercent<33) {//如果為1階段,改變畫筆的大小
float stroke = mPercent/3f; //用0-33 來控制0-10的變化 計算的方法
Log.e("wing","st" + stroke);
if(stroke == 0.0){ //如果為0 則不繪制,這里用背景色解決
mPaint.setColor(Color.BLACK);
}else {
mPaint.setColor(Color.GRAY);
}
mPaint.setStrokeWidth(stroke);
canvas.drawArc(mRectF, 180, 10, false, mPaint);
canvas.drawArc(mRectF, 205, 25, false, mPaint);
}else if(mPercent < 66) { //如果為2階段 則畫靜態的1階段
//畫內部
mPaint.setStrokeWidth(10);
canvas.drawArc(mRectF, 180, 10, false, mPaint);
canvas.drawArc(mRectF, 205, 25, false, mPaint);
//畫圓圈
mPaint.setStrokeWidth(2);
int alpha = (int) ((mPercent - 33f) / 33f * 255);//根據百分比去動態控制透明度的值、
mPaint.setAlpha(alpha);
canvas.drawCircle(225, 225, 40, mPaint);
}else
~~~
以上都沒什么好說的,現在來說最難的第三階段(搞了我好久)
第三階段全局用一個percent參數,由 66-100演變來的
~~~
float percent = (mPercent-66)*3f/100;
~~~
然后觀察曲線的動態變化,是從頂點開始像兩側繪制、這時候很容易想到 根據百分比動態改變起點,終點的值,代碼如下:
~~~
float mStartX = 225 -(225-115)*percent;
float mEndX = 225+ (335-225)*percent;
mTopPath.moveTo(mStartX ,175+(225-175)*percent);
// Log.e("wing","start:"+(225 -(225-145)*percent) + " y:"+125+(225-125)*percent);
mTopPath.quadTo(225, 175, mEndX, 175+(225-175)*percent );
canvas.drawPath(mTopPath, mPaint);
~~~
然后你會驚奇的發現如下效果:

這是因為只改變了起終點,并沒有改變輔助點的Y軸。那么輔助點到底應該怎么去改變呢,來看一張圖:

根據之前在 ?模仿360內存清理效果的研究里發現, ?在輔助點x為線段一半的情況下, 弧的切點y軸也為輔助點y的一半。 所以得出 輔助點的Y變化應為:
175-50*percent
然后來改寫貝塞爾曲線繪制代碼:
~~~
float mStartX = 225 -(225-115)*percent;//貝塞爾區限的開始x坐標
float mEndX = 225+ (335-225)*percent;//貝塞爾區限的結束x坐標
mTopPath.moveTo(mStartX ,175+(225-175)*percent);
// Log.e("wing","start:"+(225 -(225-145)*percent) + " y:"+125+(225-125)*percent);
mTopPath.quadTo(225, 175-50*percent, mEndX, 175+(225-175)*percent );//輔助點的Y坐標動態改變
canvas.drawPath(mTopPath, mPaint);
mTopPath.reset();
//
// //畫靜態下邊線
//// mPath.moveTo(145, 225);
//// mPath.quadTo(225, 325, 305, 225);
//// canvas.drawPath(mPath, mPaint);
//
mPath.moveTo(mStartX ,275-(275-225)*percent);
mPath.quadTo(225, 275+50*percent, mEndX , 275-(275-225)*percent );
canvas.drawPath(mPath,mPaint);
mPath.reset();
~~~
最后 給他一個setPercent方法:
~~~
public void setPercent(int percent){
mPercent = percent;
invalidate();
}
~~~
然后在MainActivity內 用seekbar動態改變他的percent值 即可達到我們想要的效果。
本篇難度較大,請讀者動手認真練習,文中坐標可根據個人喜好改變。
本項目地址:[點擊打開鏈接](https://github.com/githubwing/WeChatEye)? ? ? 求star
- 前言
- android自定義viewgroup初步之一----抽屜菜單
- Android 自定義view --圓形百分比(進度條)
- Android 自定義View -- 簡約的折線圖
- 新手自定義view練習實例之(一) 泡泡彈窗
- 新手自定義view練習實例之(二) 波浪view
- 手把手帶你畫一個 時尚儀表盤 Android 自定義View
- 手把手帶你畫一個動態錯誤提示 Android自定義view
- 手把手帶你做一個超炫酷loading成功動畫view Android自定義view
- 關于Android自定義view 你所需要知道的基本函數
- Android自定義view進階-- 神奇的貝塞爾曲線
- wing帶你玩轉自定義view系列(1) 仿360內存清理效果
- wing帶你玩轉自定義view系列(2) 簡單模仿qq未讀消息去除效果
- wing帶你玩轉自定義view系列(3)模仿微信下拉眼睛
- 手把手教你畫一個 逼格滿滿圓形水波紋loadingview Android
- 有坑?? 為何wing墜入PorterDuffXferMode的萬丈深淵(PorterDuffXferMode深入試驗)
- 手把手帶你畫一個漂亮蜂窩view Android自定義view
- 一個炫字都不夠??!!!手把手帶你打造3D自定義view
- 恭喜發財! -- 手把手教你仿造一個qq下拉搶紅包 Android自定義view