IM项目接近尾声,现阶段大部分时间都是测试和处理bug以及优化用户体验,记录一下中间由于切换动画造成的一些坑吧,有时候真的是出的一脸懵逼。
遇到的坑:
切换动画一部分手机生效,一部分未生效
windowIsTranslucent 设置为true 在华为(不知道还存不存在其他)导致连续点击回到桌面问题 或者多任务切换栏
windowIsTranslucent 设置为true 后会导致Activity的onRestart()方法没有调用
接下来是我实现过程以及踩坑记录:
由于各个厂商页面切换动画不一致,所以就想把他给整成一致的,最先想到了设置theme,于是就仿着微信的切换动画撸了4个动画:slide_in_from_right,slide_out_to_left,slide_in_from_left,slide_out_to_right,顾名思义分别是从右侧滑入,从左侧滑出,从左侧滑出,从右侧滑出。
slide_in_from_right
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fromXDelta="100%p"
android:interpolator="@android:anim/decelerate_interpolator"
android:toXDelta="0%p" />
</set>
slide_out_to_left
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fromXDelta="0%p"
android:toXDelta="-30%p" />
</set>
slide_in_from_left
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fromXDelta="-30%p"
android:toXDelta="0%p" />
</set>
slide_out_to_right
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fromXDelta="0%p"
android:interpolator="@android:anim/decelerate_interpolator"
android:toXDelta="100%p"
/>
</set>
这里解释下从右侧滑入滑出多加了的属性:
- android:interpolator="@android:anim/accelerate_interpolator"
设置动画为加速动画(动画播放中越来越快) - android:interpolator="@android:anim/decelerate_interpolator"
设置动画为减速动画(动画播放中越来越慢) - android:interpolator="@android:anim/accelerate_decelerate_interpolator"
设置动画为先加速在减速(开始速度最快 逐渐减慢) - android:interpolator="@android:anim/anticipate_interpolator"
先反向执行一段,然后再加速反向回来(相当于我们弹簧,先反向压缩一小段,然后在加速弹出) - android:interpolator="@android:anim/anticipate_overshoot_interpolator"
同上先反向一段,然后加速反向回来,执行完毕自带回弹效果(更形象的弹簧效果) - android:interpolator="@android:anim/bounce_interpolator"
执行完毕之后会回弹跳跃几段(相当于我们高空掉下一颗皮球,到地面是会跳动几下) - android:interpolator="@android:anim/cycle_interpolator"
循环,动画循环一定次数,值的改变为一正弦函数:Math.sin(2* mCycles* Math.PI* input) - android:interpolator="@android:anim/linear_interpolator" 线性均匀改变
- android:interpolator="@android:anim/overshoot_interpolator"
加速执行,结束之后回弹
我动画中从左侧滑入滑出写的是-30%p到0%p而不是-100%p到0%p是因为我发现后者在前后页面颜色差距过大时的切换感觉不好,仔细看了下微信给我感觉也并不是完全从屏幕外到屏幕中的
然后在style.xml下定义“AppTheme.AnimStyle”,在application下配置android:theme="@style/AppTheme.AnimStyle"
<style name="AppTheme.AnimStyle" parent="Theme.AppCompat.Light.NoActionBar">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="android:windowAnimationStyle">@style/AnimStyle</item>
</style>
<style name="AnimStyle" parent="@android:style/Animation.Activity">
<item name="android:activityOpenEnterAnimation">@anim/slide_in_from_right</item>
<item name="android:activityOpenExitAnimation">@anim/slide_out_to_left</item>
<item name="android:activityCloseExitAnimation">@anim/slide_out_to_right</item>
<item name="android:activityCloseEnterAnimation">@anim/slide_in_from_left</item>
</style>
解释下这4个属性的作用:
A 启动 B 时,A 从屏幕上消失,这时执行的是 A 的 android:activityOpenExitAnimation
A 启动 B 时,B 出现在屏幕上,这时执行的是 B 的 android:activityOpenEnterAnimation
从 B 返回A时,B 从屏幕上消失,这时执行的是 B 的 android:activityCloseExitAnimation
从 B 返回A时,A 出现在屏幕上,这时执行的是 A 的 android:activityCloseEnterAnimation
所有的都搞定,清理一下跑到手机上看效果。嗯,不错,测试的华为手机上效果与我想的一致,又换了几款手机也没问题,然后就与同事聊下中午吃什么的问题。
时间到了下午,突然发现一款三星手机的动画并不是我预计的效果,启动时会有一块白屏在从右侧划入给人感觉很不好,为了解决白屏问题我把AppTheme.AnimStyle做了如下修改:
<style name="AppTheme.AnimStyle" parent="Theme.AppCompat.Light.NoActionBar">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@style/AnimStyle</item>
</style>
添加windowIsTranslucent = true解决启动白屏问题,嗯,白屏是解决了但是发现设置的动画无效了,并且android:windowIsTranslucent与android:windowAnimationStyle还有冲突,需要我们去修改parent="@android:style/Animation.Activity"成parent="@android:style/Animation.Translucent"。
但是:android:windowIsTranslucent加了后出现了各种问题:
1.在华为上(不知道还存不存在其他)导致连续点击切换页面的按钮会回到桌面问题 或者多任务切换栏。
这里我是做了防抖点击的,看日志只执行了一次跳转,并且也没有任何异常,就仅仅是退到后台了
2.影响了正常的生命周期,ActivityA的onRestart()方法没有调用了,没有理具体影响到了哪些生命周期。
最后只好这样处理:将 "android:windowIsTranslucent=true单独提了出来,只给启动页设置,其他页面不设置解决了这个问题。原以为这样一切都解决完了,发出去测试,第二天反馈有手机动画没生效。。。心里累,android为啥这么多机型和厂商啊。。。
最终解决方案:弃用设置主题的方式,使用overridePendingTransition的方式设置动画
在自定义的BaseActivity中添加startActivity方法和重写finish方法
/**
* 跳转activity
*/
public void startActivity(Intent intent) {
if (isFastDoubleClick()) {
startActivity(intent, null);
overridePendingTransition(R.anim.slide_in_from_right, R.anim.slide_out_to_left);
}
}
@Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.slide_in_from_left, R.anim.slide_out_to_right);
}
//一个简单的防快速点击判断
public boolean isFastDoubleClick() {
long time = System.currentTimeMillis();
long timeD = time - lastClickTime;
if (0 < timeD && timeD < 800) {
return false;
}
lastClickTime = time;
return true;
}
为了向别人、向世界证明自己而努力拼搏,而一旦你真的取得了成绩,才会明白:人无须向别人证明什么,只要你能超越自己。