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

devtools/2024/11/23 7:55:53/
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/devtools/136241.html

相关文章

解决前后端发版本时候,手动清除浏览器缓存

在.html页面中添加标签 后端配置nginx,让index.html不缓存 location /index.html { add_header Cache-Control “no-cache, no-store”; }在vite.config.ts中添加 rollupOpyions: { output: { // 输出编译后的文件名称&#xff1a;【文件名称.时间戳】、【文件名称.版本号.…

【AI系统】GPU 架构回顾(从2018年-2024年)

Turing 架构 2018 年 Turing 图灵架构发布&#xff0c;采用 TSMC 12 nm 工艺&#xff0c;总共 18.6 亿个晶体管。在 PC 游戏、专业图形应用程序和深度学习推理方面&#xff0c;效率和性能都取得了重大进步。相比上一代 Volta 架构主要更新了 Tensor Core&#xff08;专门为执行…

自动化立体仓库:详解

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》人俱乐部 完整版文件和更多学习资料&#xff0c;请球友到知识星球【智能仓储物流技术研习社】自行下载。 自动化立体仓库&#xff08;Automated S…

Kafka:分布式消息系统的核心原理与安装部署

Kafka&#xff1a;分布式消息系统的核心原理与安装部署-CSDN博客 自定义 Kafka 脚本 kf-use.sh 的解析与功能与应用示例-CSDN博客 Kafka 生产者全面解析&#xff1a;从基础原理到高级实践-CSDN博客 Kafka 生产者优化与数据处理经验-CSDN博客 Kafka 工作流程解析&#xff1a…

Rust 智能指针

Rust 智能指针 引言 Rust 是一种系统编程语言,以其内存安全性、并发性和高性能而闻名。Rust 的核心特性之一是其独特的所有权模型,它确保了内存安全,同时避免了垃圾收集。在 Rust 中,智能指针是一种特殊的数据结构,它们不仅存储数据,还负责管理数据的生命周期。智能指针…

不完全竞争市场

垄断竞争市场 垄断竞争市场的特征 在垄断竞争市场上&#xff0c;大量厂商通过销售有差别的产品竞争&#xff0c;产品之间高度替代但又不是完全替代厂商可以自由进出&#xff0c;会限制在位企业的市场势力和盈利能力。 垄断竞争市场的短期均衡 因为生产差异化产品&#xff0…

游戏引擎学习第16天

视频参考:https://www.bilibili.com/video/BV1mEUCY8EiC/ 这些字幕讨论了编译器警告的概念以及如何在编译过程中启用和处理警告。以下是字幕的内容摘要&#xff1a; 警告的定义&#xff1a;警告是编译器用来告诉你某些地方可能存在问题&#xff0c;尽管编译器不强制要求你修复…

数据驱动与并行策略:用 JUnit 5 让软件测试更高效

在软件测试的数字化时代&#xff0c;工具的选择对于提升测试效率和质量至关重要。而在众多的自动化测试框架中&#xff0c;JUnit 5因其出色的设计和强大功能受到了广泛关注。本篇文章将深入探讨JUnit 5中的数据驱动与并行策略&#xff0c;以帮助我们在测试开发的旅程中更有效地…