模仿微信下拉眼睛view
發現了愛神的自定義view系列,我只想說一個字:凸(艸皿艸 ) !!相見恨晚啊,早看到就不會走這么多彎路了
另外相比之下我這完全是小兒科。。所以不說了,這篇是本系列完結篇....我要從零開始跟隨愛哥腳步去學自定義view了:愛哥自定義view專題
然后要說的就是 之前的博客都犯了很嚴重的錯誤,那就是不要在onDraw里new東西,不要在onDraw里new東西,不要在onDraw里new東西。重要的話說三遍。
上一篇介紹了 qq未讀消息提醒去除效果的簡化實現,不知道小伙伴們掌握的怎么樣了。
轉載請注明出處: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();
}
本篇難度較大,請讀者動手認真練習,文中坐標可根據個人喜好改變。
本項目地址:點擊打開鏈接 求star