標籤:
為了能清楚的看到這個效果,本人不惜幾次花費重金給眾群叼發放紅包,來查看紅包領取詳情介面的動畫效果,QQ效果
圖中我們可以看到,動畫處的頭像和文字是一起的,即同時並且是整體,注意,是整體進行縮放的,而且是隨手指移動來變換大小的,如果我們按照普通的布局方法,ImageView+TextView的方式,用安卓內建的普通動畫來實現是無法完成的,那好了,只能自訂View來實現了!
自訂view需要你對view的內部繪製機制有一定的瞭解,比如onMeasure,MeasureSpec.EXACTLY,MeasureSpec.AT_MOST,onDraw等等吧,我就不在詳細講解了,網上的介紹的文章非常多!如果你看過我之前的一篇文章:仿美團外賣,那麼本篇理解起來會更加容易!
好啦,先看下本篇實現的:
屢下思路,按之前仿美團外賣的動畫實現思路,根據滑動監聽對一個圖片的縮放還是比較簡單的,那又加了幾行文字後該怎麼辦呢?上面說過,動畫是整體的,所以圖片和文字不能在兩個View中實現,那就只能在一個view中嘍,畫完圖片畫文字唄,嗯,就是這樣!
首先,為了更容易實現效果,最頂層頭像所在紅色地區以及頭像需設定為固定高度,而寬度則可以設定固定值或match_parent!可能你會覺得如果寬高不一樣,那頭像是否會變形?答案是,如果你的自訂view裡測量寬高並重繪時沒做一些特殊操作,那變形是必然的!
先看一組代碼:
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); measuredWidth = w; measuredHeight = h; //將bitmap按測量寬高設定,Math.min(measuredWidth, measuredHeight)取寬高最小值 scalebitmap = Bitmap.createScaledBitmap(bitmap,Math.min(measuredWidth, measuredHeight),Math.min(measuredWidth, measuredHeight),true); }
通過onMeasure方法測量寬高後,在onSizeChanged可得到測量後的寬高值,
scalebitmap = Bitmap.createScaledBitmap(bitmap,Math.min(measuredWidth, measuredHeight),Math.min(measuredWidth, measuredHeight),true);
這句話的意思是將圖片的原bitmap按測量出來的寬高重建一個bitmap用於重繪,而
Math.min(measuredWidth, measuredHeight)
表示寬高按測量寬高中的最小值計算,比如我們在xml中設定自訂view 的寬:android:layout_width=”200dp”, 高:android:layout_height=”80dp”,那麼最終畫出的圖片大小為80x80dp,而整個view剩餘的右側部分就留給文字了(注意,最好將view的寬度設定為match_parent比較合適)!
再看onDraw部分代碼:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //畫圖片 canvas.scale(mCurrentProgress, mCurrentProgress,0, measuredHeight); canvas.drawBitmap(scalebitmap, 0, 0, mPaint); //Math.min(measuredWidth, measuredHeight)圖片寬高 //畫文字1,起始座標 x:為圖片寬度 y:50 mPaintText1.setTextSize(sizeText1*mCurrentProgress); canvas.drawText(text1, Math.min(measuredWidth, measuredHeight), 50, mPaintText1); //畫文字2,起始座標 x:為圖片寬度 y:圖片高度-50 mPaintText2.setTextSize(sizeText2*mCurrentProgress); canvas.drawText(text2, Math.min(measuredWidth, measuredHeight), Math.min(measuredWidth, measuredHeight)-50, mPaintText2); }
首先圖片及文字的縮放程度是根據mCurrentProgress這個值來決定的,圖片是否根據向canvas的scale方法傳入縮放比例mCurrentProgress而文字是根據自己設定的畫筆大小*比例值mCurrentProgress;我們整個布局的外層使用ScrollView不必再說,而mCurrentProgress則是根據監聽scrollview滑動距離與頭像所在區高度值相比得到的:
myScrollView.setScrollViewListener(new ScrollViewListener() { @Override public void onScrollChanged(MyScrollView scrollView, int x, int y,int oldx, int oldy) { //1.0f相當於一個縮放係數,越大隨手指縮放敏感度越低 if(y>0&&y<=height){ myView.setCurrentProgress(1-(float)(y*1.0f)/(float)height); myView.postInvalidate(); } } });
其次需要注意的點:
1.畫圖片
canvas.scale(mCurrentProgress, mCurrentProgress,0, measuredHeight);
後兩個參數表示設定一個縮放點(座標),再進行縮放時以此點為中心!
2.畫文字
文字1:
canvas.drawText(text1, Math.min(measuredWidth, measuredHeight), 50, mPaintText1);
中間兩個參數表示畫筆起點座標,x為圖片寬度,而y為50像素;
文字2:
canvas.drawText(text2, Math.min(measuredWidth, measuredHeight), Math.min(measuredWidth, measuredHeight)-50, mPaintText2);
x仍為圖片寬度,而y為圖片高度-50像素(注意圖片的寬高相同的),很容易理解吧!
當手指在不停的在螢幕上移動時,就會不停的調用myView.setCurrentProgress傳入progress,並調用postInvalidate()進行重繪,從而使view的大小跟隨手指移動縮放!
另外,大家可能要說,如果在真實項目中,頭像不可能是一張固定圖片,如果動態擷取,又該如何呢?其實很簡單了,在自訂view的init方法中有如下代碼:
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.head);
因此,我們在繪製前將網路擷取的圖片的bitmap傳進去不就可以了嗎?
當然,本篇文章所使用的方法只是一個思路,肯定不是最好的,大家集思廣益,多發散自己的思維,將自己的更好的實現方法分享出來,共同進步!
已知缺陷:在快速上滑或下滑離手後,view的縮放效果會出現誤差,待重新觸控螢幕幕移動後正常。(qq介面有相似問題)
目前本人並未尋找原因,小夥伴們,拿出你們的聰明才智,一起來解決問題吧!
ECdemo:http://download.csdn.net/detail/baiyuliang2013/9514509
安卓仿QQ紅包領取詳情介面動畫