插值器、估值器,object怎么用
首先说说我对插值器和估值器的理解吧
- 插值器是用来计算动画执行变化率的。
- 估值器呢就是取到插值器的速率和我们设置的开始值和结束值进行计算,计算出每一帧动画需要的属性值。
插值器
通过源码可以发现,android下的所有的插值器实现了一个TimeInterpolator接口:
/**
* A time interpolator defines the rate of change of an animation. This allows animations
* to have non-linear motion, such as acceleration and deceleration.
*/
public interface TimeInterpolator {
/**
* Maps a value representing the elapsed fraction of an animation to a value that represents
* the interpolated fraction. This interpolated value is then multiplied by the change in
* value of an animation to derive the animated value at the current elapsed animation time.
*
* @param input A value between 0 and 1.0 indicating our current point
* in the animation where 0 represents the start and 1.0 represents
* the end
* @return The interpolation value. This value can be more than 1.0 for
* interpolators which overshoot their targets, or less than 0 for
* interpolators that undershoot their targets.
*/
float getInterpolation(float input);
}
传入input即动画执行到哪了,取值0~1之间的float类型。
返回值是计算好的float值。值可以小于0也可以大于0。
比如说我传入了0.5表示动画执行到一半,这时候如果是AccelerateInterpolator里面的计算方法的话,就给我们返回了0.5*0.5=0.25, 当然我们可以自己初始化时传入一个float来改变对input值进行多次幂运算:
public class AccelerateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
private final float mFactor;
private final double mDoubleFactor;
public AccelerateInterpolator() {
mFactor = 1.0f;
mDoubleFactor = 2.0;
}
/**
* Constructor
*
* @param factor Degree to which the animation should be eased. Seting
* factor to 1.0f produces a y=x^2 parabola. Increasing factor above
* 1.0f exaggerates the ease-in effect (i.e., it starts even
* slower and ends evens faster)
*/
public AccelerateInterpolator(float factor) {//指定几次幂
mFactor = factor;
mDoubleFactor = 2 * mFactor;
}
public AccelerateInterpolator(Context context, AttributeSet attrs) {
this(context.getResources(), context.getTheme(), attrs);
}
/** @hide */
public AccelerateInterpolator(Resources res, Theme theme, AttributeSet attrs) {
TypedArray a;
if (theme != null) {
a = theme.obtainStyledAttributes(attrs, R.styleable.AccelerateInterpolator, 0, 0);
} else {
a = res.obtainAttributes(attrs, R.styleable.AccelerateInterpolator);
}
mFactor = a.getFloat(R.styleable.AccelerateInterpolator_factor, 1.0f);
mDoubleFactor = 2 * mFactor;
setChangingConfiguration(a.getChangingConfigurations());
a.recycle();
}
public float getInterpolation(float input) {
if (mFactor == 1.0f) {
return input * input;
} else {
return (float)Math.pow(input, mDoubleFactor);
}
}
/** @hide */
@Override
public long createNativeInterpolator() {
return NativeInterpolatorFactoryHelper.createAccelerateInterpolator(mFactor);
}
}
在getInterpolation()种根据各种数学公式我们可以计算出各种返回值实现好看的动画
估值器
package android.animation;
/**
* Interface for use with the {@link ValueAnimator#setEvaluator(TypeEvaluator)} function. Evaluators
* allow developers to create animations on arbitrary property types, by allowing them to supply
* custom evaluators for types that are not automatically understood and used by the animation
* system.
*
* @see ValueAnimator#setEvaluator(TypeEvaluator)
*/
public interface TypeEvaluator<T> {
/**
* This function returns the result of linearly interpolating the start and end values, with
* <code>fraction</code> representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
* where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
* and <code>t</code> is <code>fraction</code>.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value.
* @param endValue The end value.
* @return A linear interpolation between the start and end values, given the
* <code>fraction</code> parameter.
*/
public T evaluate(float fraction, T startValue, T endValue);
}
我们前面讲了插值器计算变化率,但这个变化率还是不能用来设置给控件什么的。
而估值器则是把变化率转换成值,这个evaluate()传入的fraction就是我们从插值器和动画执行百分比一起计算出来的值,这个值可以大于0也可以小于0,startValue和endValue就是我们从ofInt()这种函数传进来的值,看下IntEvaluator:
/**
* This evaluator can be used to perform type interpolation between <code>int</code> values.
*/
public class IntEvaluator implements TypeEvaluator<Integer> {
/**
* This function returns the result of linearly interpolating the start and end values, with
* <code>fraction</code> representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
* where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
* and <code>t</code> is <code>fraction</code>.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value; should be of type <code>int</code> or
* <code>Integer</code>
* @param endValue The end value; should be of type <code>int</code> or <code>Integer</code>
* @return A linear interpolation between the start and end values, given the
* <code>fraction</code> parameter.
*/
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startInt = startValue;
return (int)(startInt + fraction * (endValue - startInt));
}
}
实际上就是拿到这三个值来计算动画执行到fration这一帧的属性值。
ofObject()
理解完插值器和估值器的作用了,那对于ofObject()怎么用就很简单了
object()顾名思义设置属性值为object类型,然而这个object()是到底什么类型呢,android系统是不知道的,所以需要我们自己设置估值器来返回我们要的类型,看个例子:参考别人写的
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun click(view: View) {
val tv = findViewById<MyTextView>(R.id.tv)
val holder = PropertyValuesHolder.ofObject(
"IntText",
IntEvaluator(),
1,
30
)
val animator = ObjectAnimator.ofPropertyValuesHolder(tv, holder)
animator.duration = 3000
animator.interpolator = LinearInterpolator()
animator.start()
}
}
class IntEvaluator : TypeEvaluator<Int>{
override fun evaluate(fraction: Float, startValue: Int?, endValue: Int?): Int {
val curInt = startValue!! + fraction * (endValue!! - startValue!!)
return curInt.toInt()
}
}
TextView里没有把text设置成Int函数,所以我们继承TextView写了一个
class MyTextView(context: Context?, attrs: AttributeSet?) :
TextView(context, attrs) {
fun setIntText(int : Int) {
text = int.toString()
}
}

咱们这里搞了个返回Int类型的简单估值器
我们在ofObject传入一个porpertyName=“IntText”,这是对应我们写的哪个setIntText()方法的,先记住住吧。
好了,这几节讲了api调用,但是工作原理咱们还不清楚呢,下节就是工作原理啦。
上篇
https://blog.csdn.net/weixin_43860530/article/details/105346998
下篇
https://blog.csdn.net/weixin_43860530/article/details/105364456

6433

被折叠的 条评论
为什么被折叠?



