首先按照老規(guī)矩妖滔,無(wú)圖無(wú)真相嘛谨设,先看看先:
是不是很像呢苛萎,那具體是實(shí)現(xiàn)是怎樣的呢诊县,即使概括的來(lái)說(shuō)就是
1.計(jì)算各個(gè)變量的值(記得是會(huì)隨整個(gè)View的大小變化而變化)讲弄。
2其次利用好canvas.translate()這個(gè)方法,計(jì)算好大小移動(dòng)canvas的原點(diǎn)依痊。
3最后就是調(diào)用api提供的各種方法畫(huà)圖就是了避除。這么說(shuō)是不是太過(guò)于簡(jiǎn)略了呢,好胸嘁,現(xiàn)在就來(lái)
看看那具體的吧瓶摆。首先看看xml有什么參數(shù)吧
<com.example.jack.besselcurve.BesselCurveView
android:id="@+id/besselCurveView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:layout_centerHorizontal="true"
app:besselColor="@color/besselColor"
app:besselColorText="@color/besselColorText"
app:friendAverageStep="6752"
app:averageStep="2603"
app:champion="Jack"
app:allStep="8765"
app:time="17:26"
app:ranking="15">
</com.example.jack.besselcurve.BesselCurveView>
各參數(shù)對(duì)應(yīng)的解釋如下:
//時(shí)間
private String time;
//所有步數(shù)
private int allStop;
//還有平均步數(shù)
private int friendAverageStep;
//平均步數(shù)
private int averageStep;
//排名
private String ranking;
//頭像
private Bitmap champion_icon;
//冠軍名字
private String champion;
接著代碼段初始化所有參數(shù):
TypedArray mTypedArray=context.getTheme().obtainStyledAttributes(attrs,R.styleable.BesselCurveView,defStyleAttr,0);
int numCount=mTypedArray.getIndexCount();
for(int i=0;i<numCount;i++){
int attr=mTypedArray.getIndex(i);
switch(attr){
case R.styleable.BesselCurveView_allStep:
allStop=mTypedArray.getInt(attr,0);
break;
case R.styleable.BesselCurveView_averageStep:
averageStep=mTypedArray.getInt(attr,0);
break;
case R.styleable.BesselCurveView_friendAverageStep:
friendAverageStep = mTypedArray.getInt(attr,0);
break;
case R.styleable.BesselCurveView_time:
time=mTypedArray.getString(attr);
break;
case R.styleable.BesselCurveView_ranking:
ranking=mTypedArray.getString(attr);
break;
case R.styleable.BesselCurveView_champion:
champion=mTypedArray.getString(attr);
break;
case R.styleable.BesselCurveView_besselColor:
mBesselCurveColor=mTypedArray.getColor(attr,Color.BLUE);
break;
case R.styleable.BesselCurveView_besselColorText:
besselColorText=mTypedArray.getColor(attr,Color.GRAY); break;
}
}
這些都是每個(gè)自定義都有的相當(dāng)于模板,來(lái)初始化參數(shù)性宏,都看的明白吧群井。接下來(lái)也很簡(jiǎn)單,就是初始化畫(huà)筆等變量毫胜,以便于后面看畫(huà)圖更簡(jiǎn)單:
public void initValue(){
animSet=new AnimatorSet();
//外圓的畫(huà)筆
mCirclePaint=new Paint(Paint.ANTI_ALIAS_FLAG);
mCirclePaint.setStyle(Paint.Style.STROKE);
mCirclePaint.setStrokeWidth(radius/10);
mCirclePaint.setStrokeJoin(Paint.Join.ROUND);
mCirclePaint.setStrokeCap(Paint.Cap.ROUND);
mCirclePaint.setAntiAlias(true);
//中間的文字的畫(huà)筆
mCenterTextPaint=new Paint();
mCenterTextPaint.setColor(mBesselCurveColor);
mCenterTextPaint.setTextSize(radius/5);
mCenterTextPaint.setAntiAlias(true);
//除中間之外的文字的畫(huà)筆
mTextPaint=new Paint();
mTextPaint.setAntiAlias(true);
//最低下的矩形
mBottomRectPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
mBottomRectPaint.setColor(mBesselCurveColor);
mBottomRectPaint.setAntiAlias(true);
//虛線的畫(huà)筆
mDottedLinePaint = new Paint();
mDottedLinePaint.setAntiAlias(true);
mDottedLinePaint.setStyle(Paint.Style.STROKE);
mDottedLinePaint.setStrokeWidth(2); mDottedLinePaint.setColor(mBesselCurveColor); mDottedLinePaint.setPathEffect(new DashPathEffect(new float[]{5,5},1)); //畫(huà)波浪線畫(huà)筆 WavylinesPaint=new Paint(); WavylinesPaint = new Paint(Paint.ANTI_ALIAS_FLAG); WavylinesPaint.setColor(wavyColor); WavylinesPaint.setStyle(Paint.Style.FILL_AND_STROKE); //虛線的畫(huà)線 mDottedLinePath=new Path();
//畫(huà)波浪線畫(huà)線
WavyLinePath=new Path();
//底下更多的畫(huà)線
morePath=new Path();
mWaveCount = (int) Math.round(widthView / mWaveLength + 1.5);
marginBottomText=radius/4;
}
好了书斜,最重要的初始化都差不多了,現(xiàn)在就來(lái)畫(huà)圖(畫(huà)畫(huà))吧先貼出所有畫(huà)的代碼然后再逐一講解吧:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.translate(widthView/2,(heightView*((float)2/3))/2);
//畫(huà)內(nèi)圓圈
mCirclePaint.setColor(besselColorText);
RectF mCircleRectF=new RectF(-radius,-radius,radius,radius);
canvas.drawArc(mCircleRectF,120,300,false,mCirclePaint);
//畫(huà)外圓圈
mCirclePaint.setColor(mBesselCurveColor);
canvas.drawArc(mCircleRectF,120,mCircleNum,false,mCirclePaint);
//畫(huà)中間的文字
Rect mCenterRect=new Rect(); String tempAllStop=mCenterNum+"";
mCenterTextPaint.getTextBounds(tempAllStop,0,tempAllStop.length(),mCenterRect);
int halfWidthText=(mCenterRect.right-mCenterRect.left)/2;
int halfHeightText=(mCenterRect.bottom-mCenterRect.top)/2;
canvas.drawText(tempAllStop,-halfWidthText,halfHeightText,mCenterTextPaint);
//畫(huà)上邊的文字
mTextPaint.setColor(besselColorText); mTextPaint.setTextSize(radius/6);
String tempFriendAverageStep=stringTemplate(R.string.besselTime,time);
Rect mTopRect=new Rect(); mTextPaint.getTextBounds(tempFriendAverageStep,0,tempFriendAverageStep.length(),mTopRect);
int halfTopWidthText=(mTopRect.right-mTopRect.left)/2;
canvas.drawText(tempFriendAverageStep,-halfTopWidthText,-(halfHeightText+marginText),mTextPaint);
//畫(huà)下邊的文字 String
tempAverageStep=stringTemplate(R.string.friendAverageStep,friendAverageStep+"");
Rect mBottomRect=new Rect();
mTextPaint.getTextBounds(tempAverageStep,0,tempAverageStep.length(),mBottomRect);
int halfBottomWidthText=(mBottomRect.right-mBottomRect.left)/2;
int mBottomHeightText=(mBottomRect.bottom-mBottomRect.top);
canvas.drawText(tempAverageStep,- halfBottomWidthText,mBottomHeightText+halfHeightText+marginText,mTextPaint);
//畫(huà)排名 Rect mNumRect=new Rect();
mCenterTextPaint.getTextBounds(ranking,0,ranking.length(),mNumRect);
int halfNum=(mNumRect.right-mNumRect.left)/2;
mCenterTextPaint.setTextSize(40); canvas.drawText(ranking,- halfNum,radius,mCenterTextPaint);
String rankingLeft=getContext().getResources().getString(R.string.ranking_left);
mTextPaint.getTextBounds(rankingLeft,0,rankingLeft.length(),mNumRect);
canvas.drawText(rankingLeft,-halfNum-(mNumRect.right- mNumRect.left)/2-20,radius,mTextPaint);
canvas.drawText(getContext().getResources().getString(R.string.ranking_right),halfNum+10,radius,mTextPaint);
canvas.restore();
//畫(huà)最近七天和平均運(yùn)動(dòng)
mTextPaint.setTextSize(radius/9); canvas.save(); canvas.translate(0,heightView*((float)2/3));
canvas.drawText(getContext().getResources().getString(R.string.nextSevenDay),marginLi neChart,0,mTextPaint);
Rect mPercentRect=new Rect();
String mPercentText=stringTemplate(R.string.averageStep,averageStep+"");
mTextPaint.getTextBounds(mPercentText,0,mPercentText.length(),mPercentRect);
canvas.drawText(mPercentText,widthView-marginLineChart-(mPercentRect.right- mPercentRect.left),0,mTextPaint);
//畫(huà)虛線
mDottedLinePath.moveTo(marginLineChart,marginBottomText);
mDottedLinePath.lineTo(widthView-marginLineChart,marginBottomText);
canvas.drawPath(mDottedLinePath,mDottedLinePaint);
//畫(huà)7天數(shù)據(jù)柱狀圖 mTextPaint.setTextSize(radius/9);
int lineWidth=(widthView-marginLineChart*2)/8;
mCalendar.setTime(new Date());
RectF mRecf=null;
if(mListStep.size()>0){
for(int i=mListStep.size();i>=1;i--){
if(mListStep.get(i-1)!=0){
int startX=marginLineChart+lineWidth*i-radius/23;
int endX=marginLineChart+lineWidth*i+radius/23;
if(mListStep.get(i-1)>mStandardStop){
//達(dá)標(biāo) mTextPaint.setColor(mBesselCurveColor);
int exceed=mListStep.get(i-1)-mStandardStop;
float standard=(float)
(mCircleRectHeight*Double.valueOf(exceed/Double.valueOf(mStandardStop)));
mRecf=new RectF(startX,marginBottomText-(standard>mCircleRectHeight?mCircleRectHeight:standard) ,endX,marginBottomText+mCircleRectHeight);
canvas.drawRoundRect(mRecf,50,50,mTextPaint);
}else{
//不達(dá)標(biāo)
mTextPaint.setColor(besselColorText);
float noStandard=(float)(mCircleRectHeight*Double.valueOf(mListStep.get(i-1)/Double.valueOf(mStandardStop)));
mRecf=new RectF(startX,marginBottomText,endX,marginBottomText+( noStandard>mCircleRectHeight?mCircleRectHeight:noStandard));
canvas.drawRoundRect(mRecf,50,50,mTextPaint);
}
}
//畫(huà)底下的日期
mTextPaint.setColor(besselColorText);
mCalendar.set(Calendar.DAY_OF_MONTH,mCalendar.get(Calendar.DAY_OF_MONTH)-1);
Rect rect =new Rect();
String number=stringTemplate(R.string.day,mCalendar.get(Calendar.DAY_OF_MONTH)+"");
mTextPaint.getTextBounds(number,0,number.length(),rect);
canvas.drawText(number,(marginLineChart+lineWidth*i)-(rect.right-rect.left)/2,marginBottomText+70,mTextPaint);
}
}
canvas.restore();
//畫(huà)波浪圖形
canvas.save();
float mWavyHeight=heightView*((float)4/5)+50;
canvas.translate(0,mWavyHeight);
WavyLinePath.reset();
WavyLinePath.moveTo(-mWaveLength+ mOffset,0);
int wHeight=radius/5;
for(int i=0;i<mWaveCount;i++){
WavyLinePath.quadTo((-mWaveLength*3/4)+(i*mWaveLength)+mOffset,wHeight,(-mWaveLength/2)+(i*mWaveLength)+mOffset,0);
WavyLinePath.quadTo((-mWaveLength/4)+(i * mWaveLength)+mOffset,- wHeight,i*mWaveLength+mOffset,0);
}
WavyLinePath.lineTo(widthView,heightView-mWavyHeight);
WavyLinePath.lineTo(0,heightView-mWavyHeight);
WavyLinePath.close();
canvas.drawPath(WavyLinePath,WavylinesPaint);
canvas.restore();
//畫(huà)最低的信息
float removeHeight=mWavyHeight+(radius/5);
canvas.translate(0,removeHeight);
float rectHeight=heightView-removeHeight;
//畫(huà)底下的矩形
RectF rect = new RectF(0,0,widthView,rectHeight);
canvas.drawRect(rect,mBottomRectPaint);
//畫(huà)頭像
int bitmap_icon_x=radius/5;
float centerHeight=rectHeight/2;
Bitmap bitmap_icon=getRoundCornerImage(champion_icon,50,radius/5,radius/5);
canvas.drawBitmap(bitmap_icon,bitmap_icon_x,centerHeight- bitmap_icon.getHeight()/2,null);
mTextPaint.setColor(Color.WHITE); mTextPaint.setTextSize(radius/8);
//畫(huà)冠軍文字
int champion_x=radius/2; Rect mNameRect=new Rect();
String championMame=stringTemplate(R.string.champion,champion);
mTextPaint.getTextBounds(championMame,0,championMame.length(),mNameRect);
canvas.drawText(championMame,champion_x,(rectHeight+(mNameRect.bottom-mNameRect.top))/2,mTextPaint);
//畫(huà)查看
String look=getContext().getResources().getString(R.string.check);
mTextPaint.getTextBounds(look,0,look.length(),mNameRect);
canvas.drawText(look,widthView-(radius*(float)2/3),(rectHeight+(mNameRect.bottom-mNameRect.top))/2,mTextPaint);
//畫(huà)更多圖像
float morePoint=(radius*(float)2/3)/2;
canvas.drawLine(widthView-morePoint,centerHeight-(mNameRect.bottom- mNameRect.top)/2, widthView-morePoint+15,centerHeight,mTextPaint);
canvas.drawLine(widthView-morePoint+15,centerHeight,widthView-morePoint, centerHeight+(mNameRect.bottom-mNameRect.top)/2,mTextPaint);
}
代碼是不是有點(diǎn)多呢,沒(méi)辦法畫(huà)的東西本身就有點(diǎn)多了。好了剛開(kāi)始我說(shuō)要移動(dòng)canvas的原點(diǎn)是不是,你看剛開(kāi)始就移動(dòng)了吧:
super.onDraw(canvas);
canvas.save();
canvas.translate(widthView/2,(heightView*((float)2/3))/2);
1惑淳、移動(dòng)原點(diǎn)到整個(gè)圓弧的中心,其中widthView是整個(gè)view的寬样屠,heightView是整個(gè)view的高,如下圖:
就在上圖的藍(lán)色點(diǎn)就是現(xiàn)在的原點(diǎn)。
然后在這原點(diǎn)里畫(huà)圓弧唄缺脉,代碼如下
//畫(huà)內(nèi)圓圈
mCirclePaint.setColor(besselColorText);
RectF mCircleRectF=new RectF(-radius,-radius,radius,radius);
canvas.drawArc(mCircleRectF,120,300,false,mCirclePaint);
//畫(huà)外圓圈
mCirclePaint.setColor(mBesselCurveColor);
canvas.drawArc(mCircleRectF,120,mCircleNum,false,mCirclePaint);
mCircleNum是為了實(shí)現(xiàn)動(dòng)畫(huà)效果的瞧哟,這后面會(huì)講,這樣圓弧就畫(huà)完了枪向。效果也是如上圖。
2.在中心點(diǎn)再畫(huà)今天的走的總路程咧党,代碼如下:
//畫(huà)中間的文字
Rect mCenterRect=new Rect();
String tempAllStop=mCenterNum+"";
mCenterTextPaint.getTextBounds(tempAllStop,0,tempAllStop.length(),mCenterRect);
int halfWidthText=(mCenterRect.right-mCenterRect.left)/2;
int halfHeightText=(mCenterRect.bottom-mCenterRect.top)/2;
canvas.drawText(tempAllStop,-halfWidthText,halfHeightText,mCenterTextPaint);
基本的實(shí)現(xiàn)思路是用Rect在這個(gè)類(lèi)計(jì)算出你要畫(huà)文字的大小秘蛔,然后在原點(diǎn)畫(huà),不過(guò),記得這里的x,y點(diǎn)是在原點(diǎn)的左下深员,具體詳解看這里寫(xiě)鏈接內(nèi)容
接這就是畫(huà)時(shí)間和好友平均步數(shù)负蠕,其實(shí)實(shí)現(xiàn)原理也是一樣的,只不過(guò)在上面的高度是
canvas.drawText(tempFriendAverageStep,-halfTopWidthText,-(halfHeightText+marginText),mTextPaint);
是中心總步數(shù)高度的一半再加間隔倦畅,而下面的是:
canvas.drawText(tempAverageStep,-halfBottomWidthText,mBottomHeightText+halfHeightText+marginText,mTextPaint);
是下面文字總的高度再加上中心總步數(shù)高度的一半再加間隔≌谔牵現(xiàn)在效果如下圖:
接著就是畫(huà)排名,首先還是套路:
Rect mNumRect=new Rect();
mCenterTextPaint.getTextBounds(ranking,0,ranking.length(),mNumRect);
int halfNum=(mNumRect.right-mNumRect.left)/2;
mCenterTextPaint.setTextSize(40);
canvas.drawText(ranking,-halfNum,radius,mCenterTextPaint);
計(jì)算出排名文字的大小叠赐,然后在中心原點(diǎn)x軸為排名文字的一半欲账,y軸問(wèn)為半徑畫(huà)出排名,效果圖如下:
接著就在排名的兩端畫(huà)文字就行了芭概,帶代碼如下:
String rankingLeft=getContext().getResources().getString(R.string.ranking_left);
mTextPaint.getTextBounds(rankingLeft,0,rankingLeft.length(),mNumRect);
canvas.drawText(rankingLeft,-halfNum-(mNumRect.right-mNumRect.left)/2-20,radius,mTextPaint);
canvas.drawText(getContext().getResources().getString(R.string.ranking_right),halfNum+10,radius,mTextPaint);
思路還是一樣赛不,就不說(shuō)了。此時(shí)效果
畫(huà)底下柱狀圖是罢洲,首先用canvas.restore();恢復(fù)原點(diǎn)到(0,0)的狀態(tài)踢故,再用canvas.translate(0,heightView*((float)2/3));把原點(diǎn)移動(dòng)到圓弧的下面,接著又可以繼續(xù)畫(huà),實(shí)現(xiàn)思路和前面一樣:
//畫(huà)最近七天和平均運(yùn)動(dòng)
mTextPaint.setTextSize(radius/9);
canvas.save(); canvas.translate(0,heightView*((float)2/3));
canvas.drawText(getContext().getResources().getString(R.string.nextSevenDay),marginLineChart,0,mTextPaint);
Rect mPercentRect=new Rect();
String mPercentText=stringTemplate(R.string.averageStep,averageStep+"");
mTextPaint.getTextBounds(mPercentText,0,mPercentText.length(),mPercentRect);
canvas.drawText(mPercentText,widthView-marginLineChart-(mPercentRect.right-mPercentRect.left),0,mTextPaint);
//畫(huà)虛線
mDottedLinePath.moveTo(marginLineChart,marginBottomText);
mDottedLinePath.lineTo(widthView-marginLineChart,marginBottomText);
canvas.drawPath(mDottedLinePath,mDottedLinePaint);
此時(shí)效果如下:
接下來(lái)畫(huà)柱狀圖惹苗,首先
int lineWidth=(widthView-marginLineChart*2)/8;
計(jì)算出每個(gè)點(diǎn)之間的間隔
if(mListStep.size()>0){
for(int i=mListStep.size();i>=1;i--){
if(mListStep.get(i-1)!=0){
//計(jì)算出起始點(diǎn)X和終點(diǎn)X的值
int startX=marginLineChart+lineWidth*i-radius/23;
int endX=marginLineChart+lineWidth*i+radius/23;
if(mListStep.get(i-1)>mStandardStop){
//達(dá)標(biāo) mTextPaint.setColor(mBesselCurveColor);
//超出的部分
int exceed=mListStep.get(i-1)-mStandardStop;
//算出柱體大小 float standard=(float) (mCircleRectHeight*Double.valueOf(exceed/Double.valueOf(mStandardStop)));
mRecf=new RectF(startX,marginBottomText-(standard>mCircleRectHeight?mCircleRectHeight:standard) ,endX,marginBottomText+mCircleRectHeight);
canvas.drawRoundRect(mRecf,50,50,mTextPaint);
}else{
//不達(dá)標(biāo)
mTextPaint.setColor(besselColorText);
//算出不達(dá)標(biāo)柱體的大小
float noStandard=(float)(mCircleRectHeight*Double.valueOf(mListStep.get(i-1)/Double.valueOf(mStandardStop)));
mRecf=new RectF(startX,marginBottomText,endX,marginBottomText+( noStandard>mCircleRectHeight?mCircleRectHeight:noStandard));
canvas.drawRoundRect(mRecf,50,50,mTextPaint);
}
}
//畫(huà)底下的日期
mTextPaint.setColor(besselColorText);
mCalendar.set(Calendar.DAY_OF_MONTH,mCalendar.get(Calendar.DAY_OF_MONTH)-1);
Rect rect =new Rect();
String number=stringTemplate(R.string.day,mCalendar.get(Calendar.DAY_OF_MONTH)+"");
mTextPaint.getTextBounds(number,0,number.length(),rect);
canvas.drawText(number,(marginLineChart+lineWidth*i)-(rect.right-rect.left)/2,marginBottomText+70,mTextPaint);
}
}
mStandardStop是達(dá)標(biāo)的數(shù)據(jù)殿较,當(dāng)數(shù)據(jù)小于mStandardStop就是不達(dá)標(biāo),所以柱狀圖就要畫(huà)在虛線的下面桩蓉,mCircleRectHeight是柱狀圖一半的高
float standard=(float)(mCircleRectHeight*Double.valueOf(exceed/Double.valueOf(mStandardStop)));
這句代碼是計(jì)算出下面圓柱體的具體大小淋纲,noStandard>mCircleRectHeight?mCircleRectHeight:noStandard
當(dāng),但柱狀圖大于mCircleRectHeight時(shí)就用mCircleRectHeight不然就根據(jù)計(jì)算的數(shù)值來(lái)触机。當(dāng)數(shù)據(jù)大于mStandardStop時(shí)帚戳,
int exceed=mListStep.get(i-1)-mStandardStop;float standard=(float)(mCircleRectHeight*Double.valueOf(exceed/Double.valueOf(mStandardStop)));
exceed是計(jì)算出超出的部分,再拿超出的部分算出具體的大小儡首,剩下的和小于的一樣片任,當(dāng)standard大于最大的mCircleRectHeight是就用mCircleRectHeight否則就用standard。底下日期是用Calendar得到前7天的日期再循環(huán)的畫(huà)上去蔬胯,思路和上面一樣不再贅述对供。此時(shí)效果如下:
接下來(lái)是畫(huà)波浪,畫(huà)波浪是用了貝塞爾曲線的方法畫(huà)的氛濒,如果不懂貝塞爾曲線請(qǐng)參考這里寫(xiě)鏈接內(nèi)容产场,這也是我學(xué)貝塞爾曲線參考的內(nèi)容。首先我們又把canvas恢復(fù)到原點(diǎn)canvas.restore();
再用float mWavyHeight=heightView*((float)4/5)+50; canvas.translate(0,mWavyHeight);
移動(dòng)這個(gè)位置舞竿,是為了適配京景。
WavyLinePath.reset();
WavyLinePath.moveTo(-mWaveLength+ mOffset,0);
int wHeight=radius/5; for(int i=0;i<mWaveCount;i++){
WavyLinePath.quadTo((-mWaveLength*3/4)+(i*mWaveLength)+mOffset,wHeight,(-mWaveLength/2)+(i*mWaveLength)+mOffset,0);
WavyLinePath.quadTo((-mWaveLength/4)+(i * mWaveLength)+mOffset,-wHeight,i*mWaveLength+mOffset,0);
}
WavyLinePath.lineTo(widthView,heightView-mWavyHeight);
WavyLinePath.lineTo(0,heightView-mWavyHeight);
WavyLinePath.close();
canvas.drawPath(WavyLinePath,WavylinesPaint);
WavyLinePath.quadTo就是貝塞爾曲線調(diào)的方法,for循環(huán)幾次使之形成波浪圖形骗奖,記得一樣要WavyLinePath.lineTo().不讓會(huì)出現(xiàn)底下有些地方會(huì)畫(huà)不到确徙。原理是向上定一個(gè)控制點(diǎn)有向下定一個(gè)控制點(diǎn)使之形成一個(gè)sin函數(shù)圖形醒串。具體請(qǐng)學(xué)貝塞爾曲線。此時(shí)效果圖:
最后就是畫(huà)底下的矩形和頭像和文字了鄙皇。最值得講的是頭像我一開(kāi)始的設(shè)想的傳Url的芜赌,不過(guò)這樣子又要做網(wǎng)絡(luò)方面的代碼工作,這樣子會(huì)破懷類(lèi)的功能單一性原則伴逸,所以最后我實(shí)在外部傳一個(gè)位圖缠沈,在位圖進(jìn)行處理使其圓角。剩下的只是畫(huà)文字而已错蝴,上面已經(jīng)講夠多了洲愤,就不在講了。
對(duì)了漱竖,最后還有一個(gè)剛開(kāi)始的動(dòng)畫(huà)效果禽篱。
public void startAnimator(){
ValueAnimator mCircleAminator=ValueAnimator.ofFloat(0f,300f);
mCircleAminator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) {
mCircleNum=(float)animation.getAnimatedValue(); postInvalidate();
}
});
ValueAnimator mCenterText=ValueAnimator.ofInt(0,allStop);
mCenterText.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) {
mCenterNum=(int)animation.getAnimatedValue(); postInvalidate();
} });
ValueAnimator mWavyAnimator = ValueAnimator.ofInt(0, mWaveLength);
mWavyAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) {
mOffset = (int) animation.getAnimatedValue(); postInvalidate();
} });
animSet.setDuration(2000);
animSet.playTogether(mCircleAminator,mCenterText,mWavyAnimator);
animSet.start();
}
//字符串拼接
public String stringTemplate(int template,String content){
return String.format(getContext().getResources().getString(template),content);
}
其實(shí)也簡(jiǎn)單通過(guò)設(shè)置ValueAnimator讓它在規(guī)定的時(shí)間內(nèi)產(chǎn)生數(shù)值的變化,再調(diào)用postInvalidate().對(duì)View的界面進(jìn)行刷新即可實(shí)現(xiàn)動(dòng)畫(huà)效果馍惹。
最后給源碼好好研究吧源碼只有好好看源碼才能學(xué)到更多東西躺率。
如果對(duì)你有幫助就請(qǐng)給我給星星或喜歡吧。