寫在前面的話
這個時代,新物種正在生長,新邊疆正在延伸。做別人的小兵,還是做自己的將軍,你選。
前言
- 今天給大家帶來的是ValueAnimator的相關用法,下面先給大家看下效果圖。
效果圖
動畫介紹
這裏我們寫了兩個位移動畫,分別是城市交換動畫和日期位移動畫,下面我們將通過代碼詳細介紹下兩個動畫的具體實現,從而理解valueAnimator的相關使用。
城市交換動畫
- 左邊城市:startCityTextView
- 右邊城市:endCityTextView
- 首先獲取startCityTextView和endCityTextView的x座標,因爲是水平方向的移動。
- startX:左邊城市的橫座標
- endX:右邊城市的橫座標
private int startX;
private int endX;
private void getLocation() {
int[] startLocation = new int[2];
startCityTextView.getLocationOnScreen(startLocation);
int[] endLocation = new int[2];
endCityTextView.getLocationOnScreen(endLocation);
startX = startLocation[0];
endX = endLocation[0];
}
左邊城市動畫
- 移動距離
final int moveX = endX - startX + endCityTextView.getWidth() - startCityTextView.getWidth();
- 動畫代碼
ValueAnimator startCityAnimation = ValueAnimator.ofInt(0, moveX).setDuration(500);
startCityAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();
startCityTextView.layout(startX + value, startCityTextView.getTop(), startX + value + startCityTextView.getWidth(), startCityTextView.getBottom());
}
});
startCityAnimation.start();
右邊城市動畫
- 移動距離
int rightMoveX = endX - startX;
- 動畫代碼
ValueAnimator endCityAnimator = ValueAnimator.ofInt(0, rightMoveX).setDuration(500);
endCityAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();
endCityTextView.layout(endX - value, endCityTextView.getTop(), endX + endCityTextView.getWidth() - value, endCityTextView.getBottom());
}
});
endCityAnimator.start();
調換view位置
最後需要在動畫結束後調換view的位置, 使startCityTextView變爲endCityTextView,這樣下次動畫執行時位置座標才正確。
endCityAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
TextView flagTextView = startCityTextView;
startCityTextView = endCityTextView;
endCityTextView = flagTextView;
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
日期位移動畫
透明度動畫
- isSingleLine:判斷是點擊的單程還是往返
- 單程:透明度由1變到0,通過重寫ObjectAnimator的setEvaluator方法,其中fraction的變化是由0到1
- 往返:透明度從0變到1
ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(rightLayout, View.ALPHA, 0, 1.0f).setDuration(1000);
if (isSingleLine) {
alphaAnimator.setEvaluator(new TypeEvaluator<Float>() {
@Override
public Float evaluate(float fraction, Float startValue, Float endValue) {
return 1 - fraction;
}
});
}
alphaAnimator.start();
位移動畫
動畫分析:
- screenWidth 屏幕寬度
- 往返:把view從screenWidth+view.getWidth()的位置移動到screenWidth-view.getWidth的位置,移動距離:view.getWidth()
- 單程:把view移出到screenWidth和view.getWidth()之和的位置,移動距離:view.getWidth()
- 獲取屏幕寬度
private int getScreenWidth() {
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
return displayMetrics.widthPixels;
}
- 動畫代碼
ValueAnimator animator = ValueAnimator.ofFloat(0, rightLayout.getWidth()).setDuration(500);
animator.setEvaluator(isSingleLine ? new ATFlightEvaluator() : new FloatEvaluator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
int screenWidth = getScreenWidth();
rightLayout.layout(screenWidth - (int) value, rightLayout.getTop(), screenWidth + rightLayout.getWidth() - (int) value, rightLayout.getBottom());
}
});
animator.start();
- ATFlightEvalutor
這裏isSingleLine時我們設置其Evaluator爲我們自定義的ATFlightEvalutor,實現TypeEvaluator接口並重寫其evaluate方法,這樣我們獲取到動畫變化中的value值就是由view.getWidth()—>0變化的。
- startValue: 0
- endValue: view.getWidth()
- fraction: 動畫的變化率0—>1
- 其最後返回的值就是我們使用animation.getAnimatedValue()獲取的值。
public class ATFlightEvaluator implements TypeEvaluator<Float> {
@Override
public Float evaluate(float fraction, Float startValue, Float endValue) {
return endValue - fraction * (endValue - startValue);
}
}
總結
以上就是我們通過valueAnimator實現的兩個小實例,有興趣的童鞋可以研究下代碼,另外有不明白的地方可以在下面留言或者發郵件[email protected]。