編輯:關於Android編程
private Paint mPaint; private Path mPath; private PathMeasure mPathMeasure; private int mWidth,mHeight; private ValueAnimator valueAnimator; //用這個來接受ValueAnimator的返回值,代表整個動畫的進度 private float t;初始化畫筆
mPaint = new Paint(); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(15); mPaint.setColor(Color.WHITE); //設置畫筆為園筆 mPaint.setStrokeCap(Paint.Cap.ROUND); //抗鋸齒 mPaint.setAntiAlias(true);初始化Path和mPathMeasure
mPath = new Path(); RectF rect = new RectF(-150,-150,150,150); mPath.addArc(rect,-90,359.9f); mPathMeasure = new PathMeasure(mPath,false);初始化ValueAnimator
valueAnimator = ValueAnimator.ofFloat(0f,1f).setDuration(3000); valueAnimator.setRepeatCount(-1); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { t = (float) animation.getAnimatedValue(); invalidate(); } });
這裡的ValueAnimator設置的是一個時長3秒的動畫,再這3秒中,ValueAnimator會返回一個由0f-1f平滑的數字
ValueAnimator.ofFloat(0f,1f).setDuration(3000)
在這裡我們用t來接受返回值,同時刷新視圖
t = (float) animation.getAnimatedValue();
invalidate();
這裡可以看出t的值,有0到1,這裡就可以把t理解為我們這個動畫的進度
開始繪制
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(mWidth/2,mHeight/2);
Path dst = new Path();
mPathMeasure.getSegment(mPathMeasure.getLength()*t,mPathMeasure.getLength()*t+1,dst,true);
canvas.drawPath(dst,mPaint);
}
結果圖:
流程二
思路
我們設置讓t每間隔0.05就畫一個點,總共畫4個點,注意這裡getSegment()的最後一個要設置為true來保證畫出來的是多個點而不是一條線
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(mWidth/2,mHeight/2);
Path dst = new Path();
int num = (int) (t/0.05);
float s,y,x;
switch(num){
default:
case 3:
x = t-0.15f;
s = mPathMeasure.getLength();
y = s*x;
mPathMeasure.getSegment(y,y+1,dst,true);
case 2:
x = t-0.10f;
s = mPathMeasure.getLength();
y = s*x;
mPathMeasure.getSegment(y,y+1,dst,true);
case 1:
x = t-0.05f;
s = mPathMeasure.getLength();
y = s*x;
mPathMeasure.getSegment(y,y+1,dst,true);
case 0:
x = t;
s = mPathMeasure.getLength();
y = s*x;
mPathMeasure.getSegment(y,y+1,dst,true);
break;
}
canvas.drawPath(dst,mPaint);
}
結果圖
流程三
思路
我們先繪制出路程-時間的函數圖像
<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;">
函數為y = -x*x + 2*x,當x=1時,y=mPathMeasure.getLength();
設s = mPathMeasure.getLength();
最終我們套用函數:y = -s*x*x+2*s*x;
這裡的Y軸代表的是path的長度,X軸對應時間
所以把流程二中的y = s*x改成y = -s*x*x+2*s*x即可switch(num){
default:
case 3:
x = t-0.15f;
s = mPathMeasure.getLength();
y = -s*x*x+2*s*x;
mPathMeasure.getSegment(y,y+1,dst,true);
case 2:
x = t-0.10f;
s = mPathMeasure.getLength();
y = -s*x*x+2*s*x;
mPathMeasure.getSegment(y,y+1,dst,true);
case 1:
x = t-0.05f;
s = mPathMeasure.getLength();
y = -s*x*x+2*s*x;
mPathMeasure.getSegment(y,y+1,dst,true);
case 0:
x = t;
s = mPathMeasure.getLength();
y = -s*x*x+2*s*x;
mPathMeasure.getSegment(y,y+1,dst,true);
break;
}
canvas.drawPath(dst,mPaint);
結果圖
流程四
思路
雖然流程3中點與點的間距已經開始減少,不過這只是因為速度不同間距才改變的,我們的目的是讓這些點到最後合並為1個點,也就是說開始的時候每個點的X間距0.05,結束的時候要讓他們的X相同
目前點之間X的間距函數如下:
我們最後要讓當X=1時,他們的Y值相等,而且他們X的間距由0.05線性平滑到0
看函數圖像已經很清楚了,修改後代碼如下:
switch(num){
default:
case 3:
x = t-0.15f*(1-t);
s = mPathMeasure.getLength();
y = -s*x*x+2*s*x;
mPathMeasure.getSegment(y,y+1,dst,true);
case 2:
x = t-0.10f*(1-t);
s = mPathMeasure.getLength();
y = -s*x*x+2*s*x;
mPathMeasure.getSegment(y,y+1,dst,true);
case 1:
x = t-0.05f*(1-t);
s = mPathMeasure.getLength();
y = -s*x*x+2*s*x;
mPathMeasure.getSegment(y,y+1,dst,true);
case 0:
x = t;
s = mPathMeasure.getLength();
y = -s*x*x+2*s*x;
mPathMeasure.getSegment(y,y+1,dst,true);
break;
}
結果圖
流程五
思路
這裡已經完成了99.9%了,但細心的同學會發現,進度條每次轉動一圈聚成一個點後都會閃一下,這是因為重新開始動畫刷新視圖的原因,這裡的補救方法就是我們在動畫快結束的時候手動畫一個點
if(t>=0.95){
canvas.drawPoint(0,-150,mPaint);
}
這樣我們就完成了這個進度條
最後這裡附上源碼:
package com.example.zhangml.view;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by zhangml on 2016/9/12 0012.
*/
public class Win8Search extends View{
private Paint mPaint;
private Path mPath;
private PathMeasure mPathMeasure;
private int mWidth,mHeight;
private ValueAnimator valueAnimator;
//用這個來接受ValueAnimator的返回值,代表整個動畫的進度
private float t;
public Win8Search(Context context) {
super(context);
}
public Win8Search(Context context, AttributeSet attrs) {
super(context, attrs);
init();
valueAnimator.start();
}
private void init() {
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(15);
mPaint.setColor(Color.WHITE);
//設置畫筆為園筆
mPaint.setStrokeCap(Paint.Cap.ROUND);
//抗鋸齒
mPaint.setAntiAlias(true);
mPath = new Path();
RectF rect = new RectF(-150,-150,150,150);
mPath.addArc(rect,-90,359.9f);
mPathMeasure = new PathMeasure(mPath,false);
valueAnimator = ValueAnimator.ofFloat(0f,1f).setDuration(3000);
valueAnimator.setRepeatCount(-1);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
t = (float) animation.getAnimatedValue();
invalidate();
}
});
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(mWidth/2,mHeight/2);
Path dst = new Path();
if(t>=0.95){
canvas.drawPoint(0,-150,mPaint);
}
int num = (int) (t/0.05);
float s,y,x;
switch(num){
default:
case 3:
x = t-0.15f*(1-t);
s = mPathMeasure.getLength();
y = -s*x*x+2*s*x;
mPathMeasure.getSegment(y,y+1,dst,true);
case 2:
x = t-0.10f*(1-t);
s = mPathMeasure.getLength();
y = -s*x*x+2*s*x;
mPathMeasure.getSegment(y,y+1,dst,true);
case 1:
x = t-0.05f*(1-t);
s = mPathMeasure.getLength();
y = -s*x*x+2*s*x;
mPathMeasure.getSegment(y,y+1,dst,true);
case 0:
x = t;
s = mPathMeasure.getLength();
y = -s*x*x+2*s*x;
mPathMeasure.getSegment(y,y+1,dst,true);
break;
}
canvas.drawPath(dst,mPaint);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
}
}
希望這篇文章能夠給大家帶來幫助廢話少說直接在COCOS2D-X自帶的HelloCpp中添加代碼如下: #if (CC_TARGET_PLATFORM == CC_PLA
雖然索尼手機賣的不怎麼樣,但是有些東西還是做的挺好的,工業設計就不用說了,索尼的相冊的雙指任意縮放功能也是尤其炫酷。其桌面小部件滾動相冊我覺得也挺好的,比谷歌原生的相冊牆
屬性動畫是為了彌補之前兩種動畫模式的不足之處產生的(Android3.0之後才有的),特點是 真實對view的屬性進行改動,並且能支持自定義屬性動畫, 基本上能實現所有能
原文鏈接地址:http://socket.io/blog/native-socket-io-and-android/在本教程中我們將學習如何創建一個聊天客戶端用socke