Android 包含过渡框架,它使开发者能够轻松地为两个视图层次结构之间的变化设置动画。该框架通过随时间更改视图的某些属性值,在运行时为视图设置动画。该框架包括用于常见效果的内置动画,并允许开发者创建自定义动画和过渡生命周期回调。本项目基于此实现了一个过渡按钮。
transitionButton = findViewById(R.id.transition_button);transitionButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {transitionButton.startAnimation();
public void startAnimation() {currentState = State.PROGRESS;isMorphingInProgress = true;initialWidth = getWidth();initialHeight = getHeight();initialText = getText().toString();setText(null);setClickable(false);startWidthAnimation(initialHeight, new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {super.onAnimationCancel(animation);isMorphingInProgress = false;}});}
private void startWidthAnimation(int to, AnimatorListenerAdapter onAnimationEnd) {startWidthAnimation(getWidth(), to, onAnimationEnd);}private void startWidthAnimation(int from, int to, AnimatorListenerAdapter onAnimationEnd) {ValueAnimator widthAnimation = ValueAnimator.ofInt(from, to);widthAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {int val = (Integer) valueAnimator.getAnimatedValue();ViewGroup.LayoutParams layoutParams = getLayoutParams();layoutParams.width = val;setLayoutParams(layoutParams);}});AnimatorSet animatorSet = new AnimatorSet();animatorSet.setDuration(WIDTH_ANIMATION_DURATION);animatorSet.playTogether(widthAnimation);if (onAnimationEnd != null)animatorSet.addListener(onAnimationEnd);animatorSet.start();}
ValueAnimator.ofInt():由于值的变化手动对对象的属性赋值导致对象的属性发生改变,从而实现动画效果,也就是说ValueAnimator只关心数值如何发生改变的过程
setDuration(WIDTH_ANIMATION_DURATION):设置每个内部子动画的时长,默认每个子动画使用自己默认的时长,如果AnimatorSet设置了时长,子动画将继承这个时长,而子动画自己设置的duration将失效
playTogether(Animator… items):添加一组动画,播放顺序为一起播放
transitionButton = findViewById(R.id.transition_button);transitionButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {transitionButton.startAnimation();final Handler handler = new Handler();handler.postDelayed(new Runnable() {@Overridepublic void run() {boolean isSuccessful = true;if (isSuccessful) {transitionButton.stopAnimation(TransitionButton.StopAnimationStyle.EXPAND, new TransitionButton.OnAnimationStopEndListener() {@Overridepublic void onAnimationStopEnd() {Intent intent = new Intent(getBaseContext(), NewActivity.class);intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);startActivity(intent);}});}
case EXPAND:currentState = State.TRANSITION;startScaleAnimation(new AnimationListenerAdapter() {@Overridepublic void onAnimationEnd(Animation animation) {super.onAnimationEnd(animation);if (onAnimationStopEndListener != null)onAnimationStopEndListener.onAnimationStopEnd();}});break;
private void startScaleAnimation(Animation.AnimationListener animationListener) {float ts = (float) (WindowUtils.getHeight(getContext()) / getHeight() * 2.1);Animation anim = new ScaleAnimation(1f, ts,1, ts,Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);anim.setDuration(SCALE_ANIMATION_DURATION);anim.setFillAfter(true);anim.setAnimationListener(animationListener);startAnimation(anim);}
Animation.RELATIVE_TO_SELF, 0.5f:X轴移动的结束位置
setDuration(long durationMillis):设置动画持续事件(单位:毫秒)
setFillAfter(boolean fillAfter):如果fillAfter设为true,则动画执行后,控件将停留在动画结束的状态
setAnimationListener(animationListener):监听动画执行
startAnimation(anim):动画开始执行
else {transitionButton.stopAnimation(TransitionButton.StopAnimationStyle.SHAKE, null);}}}, 2000);}
public void stopAnimation(StopAnimationStyle stopAnimationStyle, final OnAnimationStopEndListener onAnimationStopEndListener) {switch (stopAnimationStyle) {case SHAKE:currentState = State.ERROR;startWidthAnimation(initialWidth, new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {setText(initialText);startShakeAnimation(new AnimationListenerAdapter() {@Overridepublic void onAnimationEnd(Animation animation) {currentState = State.IDLE;setClickable(true);if (onAnimationStopEndListener != null)onAnimationStopEndListener.onAnimationStopEnd();}});}});break;
private void startWidthAnimation(int to, AnimatorListenerAdapter onAnimationEnd) {startWidthAnimation(getWidth(), to, onAnimationEnd);}private void startWidthAnimation(int from, int to, AnimatorListenerAdapter onAnimationEnd) {ValueAnimator widthAnimation = ValueAnimator.ofInt(from, to);widthAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {int val = (Integer) valueAnimator.getAnimatedValue();ViewGroup.LayoutParams layoutParams = getLayoutParams();layoutParams.width = val;setLayoutParams(layoutParams);}});AnimatorSet animatorSet = new AnimatorSet();animatorSet.setDuration(WIDTH_ANIMATION_DURATION);animatorSet.playTogether(widthAnimation);if (onAnimationEnd != null)animatorSet.addListener(onAnimationEnd);animatorSet.start();}
private void startShakeAnimation(Animation.AnimationListener animationListener) {TranslateAnimation shake = new TranslateAnimation(0, 15, 0, 0);shake.setDuration(SHAKE_ANIMATION_DURATION);shake.setInterpolator(new CycleInterpolator(4));shake.setAnimationListener(animationListener);startAnimation(shake);}
setDuration(long durationMillis):设置动画持续事件(单位:毫秒)
setAnimationListener(animationListener):监听动画执行
setInterpolator(Interpolator i):设置动画的变化速度
startAnimation(anim):动画开始执行
作者:李海
原文链接:https://blog.csdn.net/Racdex/article/details/128112563?spm=1001.2014.3001.5502