模仿微信下拉眼睛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