<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                在介紹本文動畫效果實現之前,先來介紹屬性動畫相關的幾個知識點。 1. ValueAnimator與ObjectAnimator。 1. Interpolator插值器與TypeEvaluator估值器。 在Android3.0之前,系統提供了兩種動畫效果實現方式,幀動畫frame-by-frame animation和補間動畫tweened animation。幀動畫就是類似電影播放一樣,將整部影片拆分成一片片的然后連貫起來播放。補間動畫則可以實現對view的縮放、平移、旋轉等操作。在3.0之后,出現了一種新的動畫模式稱為屬性動畫property animation。 **屬性動畫產生的原因** 屬性動畫的出現不是用來替代補間動畫的,而是用來解決補間動畫所不能夠完成的事件的。如果我們的需求超出了操控view的旋轉、縮放、平移等操作范圍,那么我們就需選擇屬性動畫去實現了。那么屬性動畫可以做到哪些補間動畫做不到的事情呢?下面列舉幾點,當然屬性動畫的功能很強大,不僅限于我列舉的幾點。 1. 屬性動畫可以做到對一個非view類進行動畫操作。 1. 屬性動畫可以做到真正的改變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的單個屬性值,同樣也可以同時修改多個屬性,下面介紹兩種 1.PropertyValuesHolder屬性值持有者 ~~~ PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 1); PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1); ObjectAnimator.ofPropertyValuesHolder( this, pvhLeft, pvhTop). ~~~ 2.提供一個不存在的屬性值 ~~~ 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方法呢,我們也可以做到修改這些屬性值,下面提供兩種實現方式: 1. 通過valueAnimation來實現,這個下面會講解。 1. 通過自己寫一個包裝類來實現。然后為該屬性提供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,內部沒有任何其他代碼。 1. AccelerateInterpolator 加速,開始時慢中間加速 1. DecelerateInterpolator 減速,開始時快然后減速 1. AccelerateDecelerateInterolator 先加速后減速,開始結束時慢,中間加速 1. AnticipateInterpolator 反向 ,先向相反方向改變一段再加速播放 1. AnticipateOvershootInterpolator 反向加回彈,先向相反方向改變,再加速播放,會超出目的值然后緩慢移動至目的值 1. BounceInterpolator 跳躍,快到目的值時值會跳躍,如目的值100,后面的值可能依次為85,77,70,80,90,100 1. CycleIinterpolator 循環,動畫循環一定次數,值的改變為一正弦函數:Math.sin(2 * mCycles * Math.PI * input) 1. LinearInterpolator 線性,線性均勻改變 1. OvershottInterpolator 回彈,最后超出目的值然后緩慢改變到目的值 1. TimeInterpolator 一個接口,允許你自定義interpolator,以上幾個都是實現了這個接口 TypeEvaluator:根據屬性的開始、結束值與TimeInterpolation計算出的因子計算出當前時間的屬性值,android提供了以下幾個evalutor: 1. IntEvaluator:屬性的值類型為int。 1. FloatEvaluator:屬性的值類型為float。 1. ArgbEvaluator:屬性的值類型為十六進制顏色值。 1. 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); } } ~~~ **實例** 接下來我們要實現的就是如下的 效果圖: ![這里寫圖片描述](https://box.kancloud.cn/2016-03-16_56e8caabf3192.jpg "") 在本例的實現中我們的重點也是在ValueAnimator和ObjectAnimator中讀者可以結合上述知識內容來消化本例的動畫技術。附上代碼: ~~~ 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<ShapeHolder> balls = new ArrayList<ShapeHolder>(); AnimatorSet animation = null; public MyAnimationView(Context context) { super(context); ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", RED, BLUE); colorAnim.setDuration(3000); colorAnim.setEvaluator(new ArgbEvaluator()); colorAnim.setRepeatCount(ValueAnimator.INFINITE); colorAnim.setRepeatMode(ValueAnimator.REVERSE); colorAnim.start(); } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() != MotionEvent.ACTION_DOWN && event.getAction() != MotionEvent.ACTION_MOVE) { return false; } // 初始化一個跳跳球 ShapeHolder newBall = initBouncingBall(event.getX(), event.getY()); float startY = newBall.getY(); float endY = getHeight() - 50; float h = (float)getHeight(); float eventY = event.getY(); int duration = (int)(500 * ((h - eventY)/h)); // 操作newBall的Y屬性值 ValueAnimator bounceAnim = ObjectAnimator.ofFloat(newBall, "y", startY, endY); bounceAnim.setDuration(duration); bounceAnim.setInterpolator(new AccelerateInterpolator()); ValueAnimator squashAnim1 = ObjectAnimator.ofFloat(newBall, "x", newBall.getX(),newBall.getX() - 25f); squashAnim1.setDuration(duration/4); squashAnim1.setRepeatCount(1); squashAnim1.setRepeatMode(ValueAnimator.REVERSE); squashAnim1.setInterpolator(new DecelerateInterpolator()); ValueAnimator squashAnim2 = ObjectAnimator.ofFloat(newBall, "width", newBall.getWidth(),newBall.getWidth() + 50); squashAnim2.setDuration(duration/4); squashAnim2.setRepeatCount(1); squashAnim2.setRepeatMode(ValueAnimator.REVERSE); squashAnim2.setInterpolator(new DecelerateInterpolator()); ValueAnimator stretchAnim1 = ObjectAnimator.ofFloat(newBall, "y", endY, endY + 25f); stretchAnim1.setDuration(duration/4); stretchAnim1.setRepeatCount(1); stretchAnim1.setInterpolator(new DecelerateInterpolator()); stretchAnim1.setRepeatMode(ValueAnimator.REVERSE); ValueAnimator stretchAnim2 = ObjectAnimator.ofFloat(newBall, "height",newBall.getHeight(), newBall.getHeight() - 25); stretchAnim2.setDuration(duration/4); stretchAnim2.setRepeatCount(1); stretchAnim2.setInterpolator(new DecelerateInterpolator()); stretchAnim2.setRepeatMode(ValueAnimator.REVERSE); ValueAnimator bounceBackAnim = ObjectAnimator.ofFloat(newBall, "y", endY, startY); bounceBackAnim.setDuration(duration); bounceBackAnim.setInterpolator(new DecelerateInterpolator()); AnimatorSet bouncer = new AnimatorSet(); bouncer.play(bounceAnim).before(squashAnim1); bouncer.play(squashAnim1).with(squashAnim2); bouncer.play(squashAnim1).with(stretchAnim1); bouncer.play(squashAnim1).with(stretchAnim2); bouncer.play(bounceBackAnim).after(stretchAnim2); ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); fadeAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { balls.remove(((ObjectAnimator)animation).getTarget()); } }); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(bouncer).before(fadeAnim); animatorSet.start(); return true; } private ShapeHolder initBouncingBall(float x, float y) { int red = (int)(Math.random() * 255); int green = (int)(Math.random() * 255); int blue = (int)(Math.random() * 255); int color = 0xff000000 | red << 16 | green << 8 | blue; int darkColor = 0xff000000 | red/4 << 16 | green/4 << 8 | blue/4; // 實例化一個圓形 OvalShape circle = new OvalShape(); circle.resize(50f, 50f); // 設置畫筆的形狀 ShapeDrawable drawable = new ShapeDrawable(circle); Paint paint = drawable.getPaint(); // 第一個,第二個參數表示漸變圓中心坐標,半徑,圓心顏色,圓邊緣顏色,渲染器平鋪模式 RadialGradient gradient = new RadialGradient(37.5f, 12.5f, 50f, color, darkColor, Shader.TileMode.CLAMP); // 給畫筆設置著色器 paint.setShader(gradient); ShapeHolder shapeHolder = new ShapeHolder(drawable); shapeHolder.setX(x - 25f); shapeHolder.setY(y - 25f); shapeHolder.setPaint(paint); balls.add(shapeHolder); return shapeHolder; } @Override protected void onDraw(Canvas canvas) { for (int i = 0; i < balls.size(); ++i) { ShapeHolder shapeHolder = balls.get(i); canvas.save(); canvas.translate(shapeHolder.getX(), shapeHolder.getY()); shapeHolder.getShape().draw(canvas); canvas.restore(); } } } } ~~~ ~~~ 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; } } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看