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

embedded/2024/11/27 1:23:01/
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/embedded/140776.html

相关文章

Redis Key 命名规范文档

开发过程中为确保 Redis 键名的一致性、可读性和易维护性&#xff0c;本规范旨在指导开发团队在使用 Redis 时设计合理的键名格式。 1. 命名格式 采用 模块:子模块:业务描述:标识 的分层格式&#xff0c;明确数据来源和用途。 层次清晰&#xff1a;从全局到具体逐步细化。唯一…

如何修复WordPress .htaccess文件

.htaccess文件是一个隐藏的配置文件&#xff0c;对WordPress网站的运行至关重要。它本质上是Apache Web服务器的指令集&#xff0c;而Apache Web服务器通常由你的WordPress主机运行。其核心功能之一是为你的博客文章和页面创建用户友好的URL。你还可以通过.htaccess文件来实现安…

FPGA经验谈系列文章——9、块储存器的高效使用

前言 每个7系列的FPGA都包含多个36Kb容量的块存储器,俗称BlockRAM。一个BlockRAM是36Kb,它能够拆分成独立的两个18Kb,因此最小的使用单位就是18Kb。如果只想使用1Kb怎么办?不好意思,也得占用半个块存储资源18Kb。那如果使用了19Kb的话,那么就得使用一个完整的36Kb的Block…

PyTorch2

Tensor的常见操作&#xff1a; 获取元素值&#xff1a; 注意&#xff1a; 和Tensor的维度没有关系&#xff0c;都可以取出来&#xff01; 如果有多个元素则报错&#xff1b; import torch def test002():data torch.tensor([18])print(data.item())pass if __name__ &qu…

[极客大挑战 2019]BabySQL--详细解析

信息搜集 进入界面&#xff1a; 输入用户名为admin&#xff0c;密码随便输一个&#xff1a; 发现是GET传参&#xff0c;有username和password两个传参点。 我们测试一下password点位能不能注入&#xff1a; 单引号闭合报错&#xff0c;根据报错信息&#xff0c;我们可以判断…

深度学习——3种常见的Transformer位置编码【sin/cos、基于频率的二维位置编码(2D Frequency Embeddings)、RoPE】

&#x1f33a;历史文章列表&#x1f33a; 深度学习——优化算法、激活函数、归一化、正则化深度学习——权重初始化、评估指标、梯度消失和梯度爆炸深度学习——前向传播与反向传播、神经网络&#xff08;前馈神经网络与反馈神经网络&#xff09;、常见算法概要汇总万字长文解读…

基于 DRNN 神经网络整定的 PID 解耦控制

1. 基本原理 DRNN&#xff08;Dynamic Recurrent Neural Network, 动态递归神经网络&#xff09;是一种带有时间反馈的神经网络&#xff0c;能够建模系统的动态特性&#xff0c;适用于非线性、多变量、时变系统的控制。结合 PID 解耦控制&#xff0c;利用 DRNN 进行动态建模和…

5.5 W5500 TCP服务端与客户端

文章目录 1、TCP介绍2、W5500简介2.1 关键函数socketlistensendgetSn_RX_RSRrecv自动心跳包检测getSn_SR 1、TCP介绍 TCP 服务端&#xff1a; 创建套接字[socket]&#xff1a;服务器首先创建一个套接字&#xff0c;这是网络通信的端点。绑定套接字[bind]&#xff1a;服务器将…