Android 展开/收回动画效果思路与实现 |
您所在的位置:网站首页 › 折叠展开效果 › Android 展开/收回动画效果思路与实现 |
要实现什么效果?
逻辑大概流程如下: 为 ValueAnimator 设置动画的时长,以及对应属性的始 & 末值设置属性在 始 & 末值 间的变化逻辑 TimeInterpolator实现类:插值器-描述动画的变化速率TypeEvaluator实现类:估值器-描述 属性值 变化的具体数值 根据2中的逻辑更新当前值获取3中更新的值 ,修改目标属性值刷新视图重复4-5,直到 属性值 == 末值 动画工作的关键类 Java类说明ValueAnimator动画执行类,核心。负责动画的整体协调ObjectAnimator动画执行类TimeInterpolator时间插值(插值器接口),控制动画变化率TypeEvaluator类型估值(估值器接口),设置属性值计算方式,根据属性的始末值和插值计算出当前时间的属性值AnimatorSet动画集AnimatorInflater加载属性动画的XML文件 思路分析与实现代码
其中的@drawable/circleside 代码如下: 其实思路很简单,就是先将View的宽度设置为0,随着时间的增多逐渐把View的宽度设置为它应该有的宽度即可。 private ValueAnimator createDropAnimator(final View v, int start, int end) { ValueAnimator animator = ValueAnimator.ofInt(start, end); animator.addUpdateListener(arg0 -> { int value = (int) arg0.getAnimatedValue(); ViewGroup.LayoutParams layoutParams = v.getLayoutParams(); layoutParams.width = value; v.setLayoutParams(layoutParams); }); return animator; }首先我们构建一个ValueAnimator,添加了一个UpdateLisenter的方法,这个方法是在动画开始后返回值来让我们进行处理的,这个方法我们传入了三个参数分别是View,start,end,分别代表了我们创建的那个TextView,动画开始的宽度,最终的宽度。我们在updateListener里对view的宽度进行的修改。 private void show(View view, int tvWidth, long delay) { view.setVisibility(View.VISIBLE); ValueAnimator valueAnimator = createDropAnimator(view, 0, tvWidth); valueAnimator.setDuration(500); valueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { super.onAnimationStart(animation); } @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); Timer timer = new Timer(); TimerTask timerTask = new TimerTask() { @Override public void run() { runOnUiThread(() -> disMiss(view, tvWidth)); } }; timer.schedule(timerTask, delay); } }); valueAnimator.start(); }这个是触发动画的方法,第三行调用了上述的ValueAnimator的构建方法,从0到width的一个变化过程。在打开动画结束后我们又延时delay ms调用了dismiss方法来把view收起来。 private void disMiss(View view, int tvWidth) { ValueAnimator valueAnimator = createDropAnimator(view, tvWidth, 0); valueAnimator.setDuration(500); valueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { super.onAnimationStart(animation); } @Override public void onAnimationEnd(Animator animation) { view.setVisibility(View.GONE); } }); valueAnimator.start(); }dismiss方法的思路和show的差不多,只不过是从width到0的一个过程。 进过上述的3个方法我们的动画基本上已经完成了 要踩的坑 1. show()方法何时调用(动画)何时开始?如果你在onCreate里调用show方法,动画播放的过程是这样的。等你看见View的时候动画已经播放到一半了,为什么会这样?我们要了解Activity的生命周期。 onCreate和onStart调用之后我们还不能看见Activity的视图,所以调用之后动画已经绘制了一半了我们还没有看见。那我们放在onResume里再调用不就可以了吗?这样做可以,但是还是有问题,因为我们进入Activity时是有动画的,这个动画是和我们的动画一起执行的,所以还是会有可能看不全的(概率较小)。这里我们就要引入一个监听了,代码如下: ViewTreeObserver viewTreeObserver = getWindow().getDecorView().getViewTreeObserver(); viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { show(mTextView,tvWidth,1000); getWindow().getDecorView().getViewTreeObserver().removeOnPreDrawListener(this::onPreDraw); return true; } });这个方法监听了onDraw方法,在onDraw执行之前就会调用这个show方法保证我们的动画播放完全。 2.为什么横幅(View)有时候会闪一下?有时候View会闪,就是因为View本来就是VISIBLE的,动画开始的时候回突然把view的宽度置为0,所以会闪一下。如何解决这个问题呢?答案就一句话: 在XML里把View的可见性设置为INVISIBLE或者GONE 3.这个TVWidth(View的宽度)如何获得呢?众所周知,在OnCreate里是无法获取View的真实宽高的,那我们要如何解决这个问题呢?有人要说了,我百度了,用第一个问题里的监听方法就可以获取宽高。可是这个动画里你能获取到吗?答案是不能,第二个问题里我们已经把View的可见性设置为INVISIBLE或者GONE了,这两个方法View是不会绘制的,所以你根本无法获得View的宽高,那怎么解决呢?答案就是两个字: 计算 tvWidth = ScreenUtils.dip2px(this, (float) (paddingLeft + paddingRight)) + ScreenUtils.sp2px(this, (float) ( 17))*s.length();这里我提供了一个简单的思路,View的宽度就是paddingLeft + paddingRight + 字的宽度;看这个计算方法应该非常简单了。下面是ScreenUtils的三个方法: public static int dp2px(Context context, float dpValue) { float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5F); } public static int px2dp(Context context, float pxValue) { float scale = context.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5F); } public static int sp2px(Context context, float spValue) { final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; return (int) (spValue * fontScale + 0.5f); } 总结至此,我们已经实现了这个简单的展开收回动画,简单易懂,如果可以的话可以帮我 点个赞吗?如果有不懂的也可以在评论里问我,下次见拜拜! |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |