編輯:關於Android編程
在介紹本文動畫效果實現之前,先來介紹屬性動畫相關的幾個知識點。
ValueAnimator與ObjectAnimator。 Interpolator插值器與TypeEvaluator估值器。在Android3.0之前,系統提供了兩種動畫效果實現方式,幀動畫frame-by-frame animation和補間動畫tweened animation。幀動畫就是類似電影播放一樣,將整部影片拆分成一片片的然後連貫起來播放。補間動畫則可以實現對view的縮放、平移、旋轉等操作。在3.0之後,出現了一種新的動畫模式稱為屬性動畫property animation。
屬性動畫產生的原因
屬性動畫的出現不是用來替代補間動畫的,而是用來解決補間動畫所不能夠完成的事件的。如果我們的需求超出了操控view的旋轉、縮放、平移等操作范圍,那麼我們就需選擇屬性動畫去實現了。那麼屬性動畫可以做到哪些補間動畫做不到的事情呢?下面列舉幾點,當然屬性動畫的功能很強大,不僅限於我列舉的幾點。
屬性動畫可以做到對一個非view類進行動畫操作。屬性動畫可以做到真正的改變view對象的屬性值。而補間動畫只是改變了view的動畫效果。ValueAnimator與ObjectAnimator
ObjectAnimator是屬性動畫中最總要的執行類,ObjectAnimator可以操作某個對象的屬性值,但是這個屬性值必須要有get和set方法,同時也可以設置view的執行線路,通過插值器來控制。
舉個簡單的例子:
ObjectAnimator
.ofFloat(view, "rotationY", 0.0F, 360.0F)
.setDuration(500)
.start();
其可操作的屬性有x/y;scaleX/scaleY;rotationX/ rotationY;transitionX/ transitionY等。
上面的例子是修改view的單個屬性值,同樣也可以同時修改多個屬性,下面介紹兩種
PropertyValuesHolder屬性值持有者
PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 1);
PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1);
ObjectAnimator.ofPropertyValuesHolder( this, pvhLeft, pvhTop).
提供一個不存在的屬性值
ObjectAnimator anim = ObjectAnimator.ofFloat(view, "long", 1.0F, 0.0F).setDuration(500);
anim.start();
anim.UpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float cVal = (Float) animation.getAnimatedValue();
view.setAlpha(cVal);
view.setScaleX(cVal);
view.setScaleY(cVal);
}
});
上面提到的都是修改對象已有的setter和getter方法的屬性值。那麼如果對象沒有為某個屬性提供提供setter和getter方法呢,我們也可以做到修改這些屬性值,下面提供兩種實現方式:
通過valueAnimation來實現,這個下面會講解。通過自己寫一個包裝類來實現。然後為該屬性提供setter和getter方法。
class ViewWrapper{
private View mView;
public int getWidth(){
return mView.getLayoutParams().width;
}
}
ValueAnimator包含Property Animation動畫的所有核心功能,如動畫時間,開始、結束屬性值,相應時間屬性值計算方法等。
屬性動畫的應用有兩個步驟:
1、計算屬性的值。2、根據屬性值執行相應的動作。
ValueAnimator只是完成了第一步驟,而要完成第二步還要借助於ValueAnimator.onUpdateListener接口,在此方法中可以通過ValueAnimator對象的getAnimatedValue()函數可以得到當前的屬性值。
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.addUpdateListener(new AnimatorUpdateListener () {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.i("update", ((Float)animation.getAnimatedValue()).toString());
// 此處可以根據getAnimatedValue獲取到的屬性值改變view相關的屬性從而執行某些動作
}
});
animation.setInterpolator(new CycleInterpolator(3));
animation.start();
Time Interpolator插值器與TypeEvaluator估值器
Time interplator:定義了屬性值變化的方式,如線性均勻改變,開始慢然後逐漸快等。在Property Animation中是TimeInterplator,在View Animation中是Interplator,這兩個是一樣的,在3.0之前只有Interplator,3.0之後實現代碼轉移至了TimeInterplator。Interplator繼承自TimeInterplator,內部沒有任何其他代碼。
AccelerateInterpolator 加速,開始時慢中間加速 DecelerateInterpolator 減速,開始時快然後減速 AccelerateDecelerateInterolator 先加速後減速,開始結束時慢,中間加速 AnticipateInterpolator 反向 ,先向相反方向改變一段再加速播放 AnticipateOvershootInterpolator 反向加回彈,先向相反方向改變,再加速播放,會超出目的值然後緩慢移動至目的值 BounceInterpolator 跳躍,快到目的值時值會跳躍,如目的值100,後面的值可能依次為85,77,70,80,90,100 CycleIinterpolator 循環,動畫循環一定次數,值的改變為一正弦函數:Math.sin(2 * mCycles * Math.PI * input) LinearInterpolator 線性,線性均勻改變 OvershottInterpolator 回彈,最後超出目的值然後緩慢改變到目的值 TimeInterpolator 一個接口,允許你自定義interpolator,以上幾個都是實現了這個接口TypeEvaluator:根據屬性的開始、結束值與TimeInterpolation計算出的因子計算出當前時間的屬性值,android提供了以下幾個evalutor:
IntEvaluator:屬性的值類型為int。 FloatEvaluator:屬性的值類型為float。 ArgbEvaluator:屬性的值類型為十六進制顏色值。 TypeEvaluator:一個接口,可以通過實現該接口自定義Evaluator。當然我們也可以自己定義估值器,如下:
public class FloatEvaluator implements TypeEvaluator {
public Object evaluate(float fraction, Object startValue, Object endValue) {
float startFloat = ((Number) startValue).floatValue();
return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
}
}
實例
接下來我們要實現的就是如下的 效果圖:
在本例的實現中我們的重點也是在ValueAnimator和ObjectAnimator中讀者可以結合上述知識內容來消化本例的動畫技術。附上代碼:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;">
package com.example.custom.animation;
import java.util.ArrayList;
import com.example.custom.R;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.LinearLayout;
public class BouncingBalls extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bouncing_balls);
LinearLayout container = (LinearLayout) findViewById(R.id.container);
container.addView(new MyAnimationView(this));
}
public class MyAnimationView extends View {
private static final int RED = 0xffFF8080;
private static final int BLUE = 0xff8080FF;
public final ArrayList
package com.example.custom.animation;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.Shape;
import android.view.View;
public class ShapeHolder {
private float x = 0, y = 0;
private int color;
private float alpha = 1f;
private Paint paint;
private ShapeDrawable shape;
private RadialGradient gradient;
public void setPaint(Paint value) {
paint = value;
}
public Paint getPaint() {
return paint;
}
public void setX(float value) {
x = value;
}
public float getX() {
return x;
}
public void setY(float value) {
y = value;
}
public float getY() {
return y;
}
public void setShape(ShapeDrawable value) {
shape = value;
}
public ShapeDrawable getShape() {
return shape;
}
public int getColor() {
return color;
}
public void setColor(int value) {
shape.getPaint().setColor(value);
color = value;
}
public void setGradient(RadialGradient value) {
gradient = value;
}
public RadialGradient getGradient() {
return gradient;
}
public void setAlpha(float alpha) {
this.alpha = alpha;
shape.setAlpha((int)((alpha * 255f) + .5f));
}
public float getWidth() {
return shape.getShape().getWidth();
}
public void setWidth(float width) {
Shape s = shape.getShape();
s.resize(width, s.getHeight());
}
public float getHeight() {
return shape.getShape().getHeight();
}
public void setHeight(float height) {
Shape s = shape.getShape();
s.resize(s.getWidth(), height);
}
public ShapeHolder(ShapeDrawable s) {
shape = s;
}
}
Volley框架的學習馬上就可以“殺青”了,哈哈,有木有點小激動呢,之所以將這個框架分成三篇來寫,而且涉及的細節比較多,是因為考慮到後面還要學習
隨著時間的推移現在的軟件要求顯示的內容越來越多,所以要在小的屏幕上能夠更好的顯示更多的內容,首先我們會想到底部菜單欄,但是有時候想網易新聞要顯示的內容太多,而且又想在主頁
本文實例講述了Android編程實現讀取手機聯系人、撥號、發送短信及長按菜單操作方法。分享給大家供大家參考,具體如下:1.Andrid項目結構圖↓主要操作圖中紅色方框內的
筆者之前已經寫過了一些自定義View的文章,在此對其也就不從頭說起了,如有興趣的讀者可以看一下筆者的前兩篇文章。筆者之前的文章中僅僅介紹了如何使用自定義View以及為什麼