Android开发教程案例源码分享-匹配动画多个头像飘动效果

news/2024/11/26 0:35:39/
Android开发教程案例源码分享-匹配动画多个头像飘动效果

匹配往往出现多个头像飘动,吸引人点击,有时出现的位置还不固定

一、思路:

用MotionLayout

二、效果图:

在这里插入图片描述
看视频更直观点:

Android开发教程案例源码分享-匹配动画多个头像飘动效果

三、关键代码:

xml布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"xmlns:app="http://schemas.android.com/apk/res-auto"android:background="@color/color_1F1C4C"><androidx.core.widget.NestedScrollViewandroid:layout_width="match_parent"android:layout_height="0dp"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"><FrameLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"><androidx.constraintlayout.widget.ConstraintLayoutandroid:id="@+id/cl_img_anim"android:layout_width="@dimen/dp_240"android:layout_height="@dimen/dp_240"android:layout_gravity="center_horizontal"android:layout_marginTop="@dimen/dp_70"><ImageViewandroid:id="@+id/iv_video_match"android:layout_width="match_parent"android:layout_height="match_parent"android:src="@mipmap/img_video_match"/></androidx.constraintlayout.widget.ConstraintLayout><androidx.constraintlayout.motion.widget.MotionLayoutandroid:id="@+id/cl_amin1"android:layout_width="match_parent"android:layout_height="@dimen/dp_340"android:layout_marginTop="@dimen/dp_20"app:layoutDescription="@xml/activity_video_match_scene1"><ImageViewandroid:id="@+id/iv_anim1"android:layout_width="@dimen/dp_50"android:layout_height="@dimen/dp_50"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"android:scaleType="centerCrop"android:src="@mipmap/yishi"/></androidx.constraintlayout.motion.widget.MotionLayout><androidx.constraintlayout.motion.widget.MotionLayoutandroid:id="@+id/cl_amin2"android:layout_width="match_parent"android:layout_height="@dimen/dp_340"android:layout_marginTop="@dimen/dp_20"app:layoutDescription="@xml/activity_video_match_scene2"><ImageViewandroid:id="@+id/iv_anim2"android:layout_width="@dimen/dp_50"android:layout_height="@dimen/dp_50"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"android:src="@mipmap/yishi2"android:scaleType="centerCrop"/></androidx.constraintlayout.motion.widget.MotionLayout><androidx.constraintlayout.motion.widget.MotionLayoutandroid:id="@+id/cl_amin3"android:layout_width="match_parent"android:layout_height="@dimen/dp_340"android:layout_marginTop="@dimen/dp_20"app:layoutDescription="@xml/activity_video_match_scene3"><ImageViewandroid:id="@+id/iv_anim3"android:layout_width="@dimen/dp_50"android:layout_height="@dimen/dp_50"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"android:src="@mipmap/yishi3"android:scaleType="centerCrop"/></androidx.constraintlayout.motion.widget.MotionLayout><androidx.constraintlayout.motion.widget.MotionLayoutandroid:id="@+id/cl_amin4"android:layout_width="match_parent"android:layout_height="@dimen/dp_340"android:layout_marginTop="@dimen/dp_20"app:layoutDescription="@xml/activity_video_match_scene4"><ImageViewandroid:id="@+id/iv_anim4"android:layout_width="@dimen/dp_50"android:layout_height="@dimen/dp_50"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"android:src="@mipmap/yishi4"android:scaleType="centerCrop"/></androidx.constraintlayout.motion.widget.MotionLayout><androidx.constraintlayout.motion.widget.MotionLayoutandroid:id="@+id/cl_amin5"android:layout_width="match_parent"android:layout_height="@dimen/dp_340"android:layout_marginTop="@dimen/dp_20"app:layoutDescription="@xml/activity_video_match_scene5"><ImageViewandroid:id="@+id/iv_anim5"android:layout_width="@dimen/dp_50"android:layout_height="@dimen/dp_50"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"android:src="@mipmap/yishi5"android:scaleType="centerCrop"/></androidx.constraintlayout.motion.widget.MotionLayout><androidx.constraintlayout.motion.widget.MotionLayoutandroid:id="@+id/cl_amin6"android:layout_width="match_parent"android:layout_height="@dimen/dp_340"android:layout_marginTop="@dimen/dp_20"app:layoutDescription="@xml/activity_video_match_scene6"><ImageViewandroid:id="@+id/iv_anim6"android:layout_width="@dimen/dp_50"android:layout_height="@dimen/dp_50"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"android:src="@mipmap/yishi6"android:scaleType="centerCrop"/></androidx.constraintlayout.motion.widget.MotionLayout><androidx.constraintlayout.motion.widget.MotionLayoutandroid:id="@+id/cl_amin7"android:layout_width="match_parent"android:layout_height="@dimen/dp_340"android:layout_marginTop="@dimen/dp_20"app:layoutDescription="@xml/activity_video_match_scene7"><ImageViewandroid:id="@+id/iv_anim7"android:layout_width="@dimen/dp_50"android:layout_height="@dimen/dp_50"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"android:src="@mipmap/yishi7"android:scaleType="centerCrop"/></androidx.constraintlayout.motion.widget.MotionLayout></FrameLayout></androidx.core.widget.NestedScrollView></androidx.constraintlayout.widget.ConstraintLayout>

kotlin代码

package com.cong.mymoreheadanimimport androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.view.View
import androidx.constraintlayout.motion.widget.MotionLayout
import com.cong.mymoreheadanim.databinding.ActivityVideoMatchBinding
import com.zailiaoliao.lib.image.ImageLoaderclass MainActivity : AppCompatActivity() {lateinit var mBinding:ActivityVideoMatchBindingprivate var isStart2 = falseprivate var isStart3 = falseprivate var isStart4 = falseprivate var isStart5 = falseprivate var isStart6 = falseprivate var isStart7 = falseprivate var isStartAnim1 = falseoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)mBinding = ActivityVideoMatchBinding.inflate(layoutInflater)setContentView(mBinding.root)ImageLoader.loadAvatar(mBinding.ivAnim1,R.mipmap.yishi)ImageLoader.loadAvatar(mBinding.ivAnim2,R.mipmap.yishi2)ImageLoader.loadAvatar(mBinding.ivAnim3,R.mipmap.yishi3)ImageLoader.loadAvatar(mBinding.ivAnim4,R.mipmap.yishi4)ImageLoader.loadAvatar(mBinding.ivAnim5,R.mipmap.yishi5)ImageLoader.loadAvatar(mBinding.ivAnim6,R.mipmap.yishi6)ImageLoader.loadAvatar(mBinding.ivAnim7,R.mipmap.yishi7)dealAnimListener()}override fun onResume() {super.onResume()if (!isStartAnim1){Handler().postDelayed({mBinding.clAmin1.transitionToStart()mBinding.clAmin1.setTransition(R.id.left_to_right)mBinding.clAmin1.transitionToEnd()isStartAnim1 = true},500)}}private fun dealAnimListener(){mBinding.clAmin1.addTransitionListener(object : MotionLayout.TransitionListener{override fun onTransitionStarted(p0: MotionLayout?, p1: Int, p2: Int) {mBinding.ivAnim1.visibility = View.VISIBLE}override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {if (p3 >= 0.2f && !isStart2){mBinding.clAmin2.transitionToStart()mBinding.clAmin2.setTransition(R.id.left_to_right2)mBinding.clAmin2.transitionToEnd()isStart2 = true}}override fun onTransitionCompleted(p0: MotionLayout, p1: Int) {isStart2 = false}override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) {}})mBinding.clAmin2.addTransitionListener(object : MotionLayout.TransitionListener{override fun onTransitionStarted(p0: MotionLayout?, p1: Int, p2: Int) {mBinding.ivAnim2.visibility = View.VISIBLE}override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {if (p3 >= 0.2f && !isStart3){mBinding.clAmin3.transitionToStart()mBinding.clAmin3.setTransition(R.id.left_to_right3)mBinding.clAmin3.transitionToEnd()isStart3 = true}}override fun onTransitionCompleted(p0: MotionLayout, p1: Int) {isStart3 = false}override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) {}})mBinding.clAmin3.addTransitionListener(object : MotionLayout.TransitionListener{override fun onTransitionStarted(p0: MotionLayout?, p1: Int, p2: Int) {mBinding.ivAnim3.visibility = View.VISIBLE}override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {if (p3 >= 0.5f && !isStart4){mBinding.clAmin4.transitionToStart()mBinding.clAmin4.setTransition(R.id.left_to_right4)mBinding.clAmin4.transitionToEnd()isStart4 = true}}override fun onTransitionCompleted(p0: MotionLayout, p1: Int) {isStart4 = false}override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) {}})mBinding.clAmin4.addTransitionListener(object : MotionLayout.TransitionListener{override fun onTransitionStarted(p0: MotionLayout?, p1: Int, p2: Int) {mBinding.ivAnim4.visibility = View.VISIBLE}override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {if (p3 >= 0.3f && !isStart5){mBinding.clAmin5.transitionToStart()mBinding.clAmin5.setTransition(R.id.left_to_right5)mBinding.clAmin5.transitionToEnd()isStart5 = true}}override fun onTransitionCompleted(p0: MotionLayout, p1: Int) {isStart5 = false}override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) {}})mBinding.clAmin5.addTransitionListener(object : MotionLayout.TransitionListener{override fun onTransitionStarted(p0: MotionLayout?, p1: Int, p2: Int) {mBinding.ivAnim5.visibility = View.VISIBLE}override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {if (p3 >= 0.3f && !isStart6){mBinding.clAmin6.transitionToStart()mBinding.clAmin6.setTransition(R.id.left_to_right6)mBinding.clAmin6.transitionToEnd()isStart6 = true}}override fun onTransitionCompleted(p0: MotionLayout, p1: Int) {isStart6 = false}override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) {}})mBinding.clAmin6.addTransitionListener(object : MotionLayout.TransitionListener{override fun onTransitionStarted(p0: MotionLayout?, p1: Int, p2: Int) {mBinding.ivAnim6.visibility = View.VISIBLE}override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {if (p3 >= 0.3f && !isStart7){mBinding.clAmin7.transitionToStart()mBinding.clAmin7.setTransition(R.id.left_to_right7)mBinding.clAmin7.transitionToEnd()isStart7 = true}}override fun onTransitionCompleted(p0: MotionLayout, p1: Int) {isStart7 = falsemBinding.ivAnim1.visibility = View.GONEmBinding.clAmin1.transitionToStart()mBinding.clAmin1.setTransition(R.id.left_to_right)mBinding.clAmin1.transitionToEnd()}override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) {}})mBinding.clAmin7.addTransitionListener(object : MotionLayout.TransitionListener{override fun onTransitionStarted(p0: MotionLayout?, p1: Int, p2: Int) {mBinding.ivAnim7.visibility = View.VISIBLE}override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {}override fun onTransitionCompleted(p0: MotionLayout, p1: Int) {}override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) {}})}
}
项目demo源码结构图:

在这里插入图片描述
有问题或者需要demo源码的私信我


http://www.ppmy.cn/news/1549951.html

相关文章

已解决java.lang.StackOverflowError异常的正确解决方法,亲测有效!!!

成功解决java.lang.StackOverflowError异常 本文目录 问题分析 报错原因 解决思路 解决方法 检查递归调用 优化算法 调整JVM栈大小 减少局部变量的使用 总结 在编写Java程序时&#xff0c;你可能会遇到一种名为java.lang.StackOverflowError的错误。这个问题通常是由…

用Python爬虫“偷窥”1688商品详情:一场数据的奇妙冒险

引言&#xff1a;数据的宝藏 在这个信息爆炸的时代&#xff0c;数据就像是一座座等待挖掘的宝藏。而对于我们这些电商界的探险家来说&#xff0c;1688上的商品详情就是那些闪闪发光的金子。今天&#xff0c;我们将化身为数据的海盗&#xff0c;用Python这把锋利的剑&#xff0…

VSCode 如何选中包含某个字母的所有行

文章目录 写在前面一、需求描述二、解决方法参考链接 写在前面 自己的测试环境&#xff1a;VSCode 一、需求描述 由于需要处理文件&#xff0c;需求是删除文件中包含某个字母的所有行。 二、解决方法 在 Visual Studio Code (VSCode) 中&#xff0c;如果你想选中所有包含某…

网络安全概论

一、 网络安全是一个综合性的技术。在Internet这样的环境中&#xff0c;其本身的目的就是为了提供一种开放式的交互环境&#xff0c;但是为了保护一些秘密信息&#xff0c;网络安全成为了在开放网络环境中必要的技术之一。网络安全技术是随着网络技术的进步逐步发展的。 网络安…

秋招面试基础总结,Java八股文基础(串联知识),四万字大全

目录 值传递和引用传递 静态变量和静态代码块的执行顺序 Java​​​​​​​集合的框架&#xff0c;Set,HashSet,LinkedHashSet这三个底层是什么 多线程篇 Java实现多线程的方式 假设一个线程池&#xff0c;核心线程数是2&#xff0c;最大线程数是3&#xff0c;阻塞队列是4…

Linux-Nginx反向代理

文章目录 反向代理负载均衡 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Linux专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年11月24日10点32分 反向代理 虚拟主机 1 为虚拟主机 3 提供代理服务 vi /etc/nginx/conf.d/vhost.confser…

【创建型设计模式】单例模式

【创建型设计模式】单例模式 这篇博客接下来几篇都将阐述设计模式相关内容。 接下来的顺序大概是&#xff1a;单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。 一、什么是单例模式 单例模式是一种创建型设计模式&#xff0c;它保证一个类仅有一个实例&#…

Linux---ps命令

​​​​​​Linux ps 命令 | 菜鸟教程 (runoob.com) process status 用于显示进程的状态 USER: 用户名&#xff0c;运行此进程的用户名。PID: 进程ID&#xff08;Process ID&#xff09;&#xff0c;每个进程的唯一标识号%CPU: 进程当前使用的CPU百分比%MEM: 进程当前使用的…