最近一直在学习kotlin,又接触到 Lottie 动画,网上是Java写的 Lottie动画,我用kotlin写了一边,发现了一写问题。总结一下
Lottie学习文章
Lottie for Android GitHub
Lottie,简单的说,流程就是(Android为例):UI设计给出动画的 Json 文件,放到项目中,加载,展示动画。
特别说明一下:Lottie 2.8.0,对应的最小SDK,一定要 大于等于16(Android 4.1)。现在很少有低于4.1了吧,注意下就好
我网上找了个动画对应的Json
出自文章:Lottie开源动画库介绍与使用示例
现在,开始使用:
这里,我先讲一下Java的使用,很简单:
1、我项目中,是用的 androidx
implementation "com.airbnb.android:lottie:2.8.0"
2、res文件夹下,创建raw文件夹,然后,创建一个:hello_world.json 文件
(上面提到的,学习文章中,有这么一句:建议使用 res/raw,因为可以对动画通过 R 文件使用静态引用,而不只是使用字符串名称)
3、把上面提到的,动画对应的 json,复制到 hello_world.json 文件中
4、布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.airbnb.lottie.LottieAnimationView
android:background="#55ff0000"
android:id="@+id/animation_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
app:lottie_loop="true"
app:lottie_rawRes="@raw/hello_world" />
</RelativeLayout>
5、代码中使用:
private boolean animationStatus = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_2);
final LottieAnimationView animationView = findViewById(R.id.animation_view);
animationView.playAnimation();
animationView.addAnimatorListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
animationStatus = true;
Log.e("getAnimatedValue()", "onAnimationStart==" + animationView.isAnimating());
}
@Override
public void onAnimationEnd(Animator animation) {
animationStatus = false;
Log.e("getAnimatedValue()", "onAnimationEnd==" + animationView.isAnimating());
}
@Override
public void onAnimationCancel(Animator animation) {
animationStatus = false;
Log.e("getAnimatedValue()", "onAnimationCancel==" + animationView.isAnimating());
}
@Override
public void onAnimationRepeat(Animator animation) {
animationStatus = true;
Log.e("getAnimatedValue()", "onAnimationRepeat==" + animationView.isAnimating());
}
});
//animationView.addAnimatorUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
// @Override
// public void onAnimationUpdate(ValueAnimator animation) {
// Log.e("getAnimatedValue()",animation.getAnimatedValue()+"");
// }
//});
animationView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (animationStatus) {
animationView.cancelAnimation();
} else {
animationView.playAnimation();
}
}
});
}
到这里,使用就结束了。很简单。
接下来,用kotlin实现一下。
新建kotlin项目,然后引入依赖
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.android.support:recyclerview-v7:28.0.0'
implementation "com.airbnb.android:lottie:2.8.0"
}
这里,注意一下:新建后,默认的是:com.android.support
然后,和上面一样了,区别在于Activity中的使用写法:
<com.airbnb.lottie.LottieAnimationView
android:background="#55ff0000"
android:id="@+id/animation_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
app:lottie_loop="true"
app:lottie_rawRes="@raw/hello_world" />
注意,id 是 animation_view
//动画状态,默认是false:不运动
var animationStatus: Boolean = false
override fun initView() {
setContentView(R.layout.activity_main_5)
animation_view.playAnimation()
animation_view.addAnimatorListener(object : Animator.AnimatorListener {
override fun onAnimationRepeat(animation: Animator?) {
animationStatus = true
Utils.logE("addAnimatorListener == onAnimationRepeat == " + animation_view.isAnimating)
}
override fun onAnimationEnd(animation: Animator?) {
animationStatus = false
Utils.logE("addAnimatorListener == onAnimationEnd == " + animation_view.isAnimating)
}
override fun onAnimationCancel(animation: Animator?) {
animationStatus = false
Utils.logE("addAnimatorListener == onAnimationCancel == " + animation_view.isAnimating)
}
override fun onAnimationStart(animation: Animator?) {
animationStatus = true
Utils.logE("addAnimatorListener == onAnimationStart ==" + animation_view.isAnimating)
}
})
animation_view.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View?) {
if (animationStatus) {
animation_view.cancelAnimation()
} else {
animation_view.playAnimation()
}
}
})
}
然后,运行,就会报错了:
* What went wrong:
Execution failed for task ':app:processDebugManifest'.
> Manifest merger failed : Attribute application@appComponentFactory value=(android.support.v4.app.CoreComponentFactory) from [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91
is also present at [androidx.core:core:1.0.0] AndroidManifest.xml:22:18-86 value=(androidx.core.app.CoreComponentFactory).
Suggestion: add 'tools:replace="android:appComponentFactory"' to <application> element at AndroidManifest.xml:5:5-31:19 to override.
出了什么问题:
任务':app:processDebugManifest'执行失败。
清单合并失败:属性application@appComponentFactory value=(android. android.support:support-compat:28.0.0) from [com.android.support: compat:28.0.0] AndroidManifest.xml:22:18-91
也存在于[androidx.core:core:1.0.0] AndroidManifest。xml: 22:18 - 86值= (androidx.core.app.CoreComponentFactory)。
建议:在AndroidManifest的 element中添加'tools:replace="android:appComponentFactory"'。xml: 5:5-31:19覆盖。
我试过所谓的清单文件中的加属性,没用。
出现这个问题,是因为 androidx 和 android.support 冲突了!
即:androidx 和 项目中默认的 android.support,冲突了!
但是,我们没有写 androidx 啊,它在哪里有使用或者出现呢?
去看下Lottie的源码下的 build.gradle
里面明确有一句:
implementation "androidx.appcompat:appcompat:${androidXVersion}"
解决办法:
1、共存。让 androidx 和 android.support 共存。这样比较麻烦,代价也大
2、
处理之后:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4'
implementation 'androidx.room:room-runtime:2.0.0-beta01'
annotationProcessor 'androidx.room:room-compiler:2.0.0-beta01'
implementation "com.airbnb.android:lottie:2.8.0"
}
最后,特别说明一下:
我在xml的布局文件中,指定了,动画是无限循环的。
那么,对应的动画状态是:
start -> 执行 -> 一次执行完 -> repeat -> 执行 -> ...
当执行方法
cancelAnimation()
后,状态是 cancel,但是,这个时候,
@Override
public void onAnimationCancel(Animator animation) {
Log.e("getAnimatedValue()", "onAnimationCancel==" + animationView.isAnimating());
}
日志:true
源码中执行方法顺序我没找到,不过,看属性动画的源码,是cancel,在end之前执行的,这里,应该也是。end,对应的 animationView.isAnimating() -> false
如果,动画只执行一次,状态是:
start -> 执行 -> end
@Override
public void onAnimationEnd(Animator animation) {
Log.e("getAnimatedValue()", "onAnimationEnd==" + animationView.isAnimating());
}
日志:false
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)