前几天的博客中,一直在说视图动画和属性动画,当然除了这些之外,也稍微介绍来了一下关于动画插值器的相关内容,但是插值器跟估值器是有很大的不同的!!!不信?那就继续往下看吧!!!首先借用前几篇博客中的例子,我们来看一下插值器是如何工作的!
还是使用ScaleAnimation动画,这里只给出主要源码,详细源码有兴趣的可以自己看一下!!!
ScaleAnimation.java
protected void applyTransformation(float interpolatedTime, Transformation t) {
float sx = 1.0f;
float sy = 1.0f;
float scale = getScaleFactor();
if (mFromX != 1.0f || mToX != 1.0f) {
sx = mFromX + ((mToX - mFromX) * interpolatedTime);
}
if (mFromY != 1.0f || mToY != 1.0f) {
sy = mFromY + ((mToY - mFromY) * interpolatedTime);
}
if (mPivotX == 0 && mPivotY == 0) {
t.getMatrix().setScale(sx, sy);
} else {
t.getMatrix().setScale(sx, sy, scale * mPivotX, scale * mPivotY);
}
}
看一个最简单的插值器,线性插值器:
LinearInterpolator.java:
LinearInterpolator
public float getInterpolation(float input) {
return input;
}
其中在ScaleAnimation的代码中,interpolatorTime的值就是插值器中getInterpolation方法的返回值,动画根据插值器的返回值对Scale属性进行处理,是不是感觉很相似!!!
在源码中通过一些简单的计算,计算出sx和sy的值,这里的值不就是代表动画的水平和垂直方向的缩放倍数吗,最后通过矩阵实现。
这里的计算在属性动画中就是通过估值器实现,估值器就是根据插值器返回的动画进度,计算出当前动画的value值,并通过相应的属性设置方法进行设置,或者通过接口进行返回,如果你还不信的话,我们就看一下,FloatEvalutor的实现方法!!!
public Float evaluate(float fraction, Number startValue, Number endValue) {
float startFloat = startValue.floatValue();
return startFloat + fraction * (endValue.floatValue() - startFloat);
}
看到了吗?是不是感觉很简单,跟上面ScaleAnimation中的计算过程是不是一模一样!!!相信看到这里你也就明白估值器在属性动画中的作用了吧(别跟我说你还不清楚呀)!!
是不是感觉估值器很简单,OK,我们现在来自定义一个估值器,只属于我们自己的估值器,嗯,就真的只是自己的!!!
在使用自定义估值器的时候,需要View的属性具有get和set方法,而且在使用估值器的时候,最需要关注的就是估值器返回值的类型,这个类型必须与view属性值得类型相同,不然应该会抛出异常!!!
先看一下效果图吧:
看一下主布局文件吧:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.evalutordemo.MainActivity">
<com.example.evalutordemo.CustomTextView
android:id="@+id/tv"
android:layout_width="200dp"
android:layout_height="40dp"
/>
<Button
android:text="@string/start_animator"
android:textAllCaps="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/tv"
android:onClick="startAnimator"/>
</RelativeLayout>
自定义View文件:
package com.example.evalutordemo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
/**
* Created by Administrator on 2017/3/25 0025.
*/
public class CustomTextView extends View {
private Character mText = '*';
private Paint p;
private Rect text;
private Rect canvasRect;
public CustomTextView(Context context) {
this(context,null);
}
public CustomTextView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr,0);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
p = new Paint();
p.setColor(Color.RED);
p.setTextSize(48);
p.setTextAlign(Paint.Align.LEFT);
text = new Rect();
canvasRect = new Rect();
}
public Character getText1(){
char value = mText;
return new Character(value);
}
public void setText1(Character c){
mText = c;
invalidate();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
canvasRect.left = getPaddingLeft();
canvasRect.top = getPaddingTop();
canvasRect.right = getWidth()-getPaddingRight();
canvasRect.bottom = getHeight()-getPaddingBottom();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
p.setColor(Color.RED);
p.getTextBounds(mText.toString(),0,mText.toString().length(),text);
canvas.drawRect(canvasRect,p);
p.setColor(Color.BLACK);
canvas.drawText(mText.toString(),(canvasRect.width()-text.width())/2+getPaddingLeft(),canvasRect.bottom-(canvasRect.height()-text.height())/2,p);
}
}
Activity文件:
package com.example.evalutordemo;
import android.animation.FloatEvaluator;
import android.animation.IntEvaluator;
import android.animation.ValueAnimator;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private ValueAnimator valueAnimator;
private CustomTextView tv;
private IntEvaluator intEvaluator;
private FloatEvaluator floatEvaluator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (CustomTextView)findViewById(R.id.tv);
valueAnimator = new ValueAnimator();
valueAnimator.setObjectValues(new Character('A'),new Character('Z'));
valueAnimator.setEvaluator(new CharEvalutor());
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setTarget(tv);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
char value = (char) animation.getAnimatedValue();
tv.setText1(value);
}
});
valueAnimator.setDuration(25000);
}
public void startAnimator(View view){
valueAnimator.start();
}
}
在自定义View中我们设置了一个 mText 属性,类型为Character,所以我们在自定义Evalutor的时候,里面的类型也需要设置为Character。还是看一下代码吧:
package com.example.evalutordemo;
import android.animation.TypeEvaluator;
import android.text.style.CharacterStyle;
/**
* Created by Administrator on 2017/3/25 0025.
*/
public class CharEvalutor implements TypeEvaluator<Character> {
@Override
public Character evaluate(float fraction, Character startValue, Character endValue) {
char value = (char) (startValue+(endValue-startValue)*fraction);
return value;
}
}
看到这个自定义估值器是不是感觉很简单,估值器虽然存在差异,但是差异应该是不会很大的,好了,关于插值器的内容就介绍到这里吧,以后遇到新的内容在进行补充吧!!
这是我的微信公众号,如果可以的话,希望您可以帮忙关注一下,这将是对我最大的鼓励了,谢谢!!