【情人节用Compose给女神写个爱心动画APP】
情人节用Compose给女神写个爱心动画APP
- 前言
- 涉及知识点
- 实现思路
- 实现过程
- 绘制爱心
- 创建动画效果
- Preview预览效果
- 完整源码
- 彩蛋
前言
前一阵子看电视里的学霸用代码写了个炫酷的爱心,网上有很多js和python的源码,复制粘贴就能拥有,但是Android的好像还没有人写过。今天正好是情人节,咱们来用Compose写一个简单的爱心动画,告诉女神们,咱们程序猿也有自己的浪漫(/手动狗头)
废话不多说,直接看效果:
(源码在最后)
涉及知识点
本篇文章涉及到技术不多,也都不深,适合各方面技术入门,以下列出关键的一些:
- Jetpack Compose
- Compose动画
- Canvas自由绘制
- 三次贝塞尔曲线
实现思路
-
爱心是左右对称的,所以我们只要能实现半边,另外半边就很容易了
-
半边爱心的曲线不算太复杂,但也不简单,使用两段三阶贝塞尔曲线相连才可以达到效果,取样点可以自己草图上画一下,草图可以不用很精确,后续可以根据效果再调整参数,如下
-
绘制好一边之后,另一边就很简单,数据可以直接拿过来用,注意x轴符号取反就ok了
-
用Compose的InfiniteTransition实现大小 和 透明度 的无限循环动画
实现过程
绘制爱心
讲解都在代码注释里了,直接看代码吧
@Composable
fun HeartBeat(modifier: Modifier = Modifier.fillMaxSize(),color: Color = Color.Red
) {Canvas(modifier = modifier) {//取canvas当前画布宽高的较小值-30,防止超出边界val minSize = min(size.height, size.width) - 30fval path = Path()//右半边爱心,先移动到中间心窝位置path.moveTo(center.x, center.y - minSize / 3)//相对位置的三阶贝塞尔曲线,从当前点连接下三个取样点path.relativeCubicTo(minSize / 4, -minSize / 4,minSize / 2, 0f,minSize / 2, minSize / 5)//同理,三阶贝塞尔曲线path.relativeCubicTo(0f, minSize / 3,-minSize * 3 / 8, minSize * 3 / 8,-minSize / 2, minSize * 3 / 4)//左半边爱心,同理,回到心窝位置开始,x轴参数取反即可path.moveTo(center.x, center.y - minSize / 3)path.relativeCubicTo(-minSize / 4, -minSize / 4,-minSize / 2, 0f,-minSize / 2, minSize / 5)path.relativeCubicTo(0f, minSize / 3,minSize * 3 / 8, minSize * 3 / 8,minSize / 2, minSize * 3 / 4)drawPath(path, color)}
}
创建动画效果
想要实现心跳的感觉,一个是大小的变化,还有一个就是透明度,由于是无线循环动画,所以使用Compose的InfiniteTransition来实现,不太了解的同学可以后续自行补习一下Compose动画
在HeartBeat方法内,Canvas代码块之上添加如下代码:
@Composable
fun HeartBeat(modifier: Modifier = Modifier.fillMaxSize(),color: Color = Color.Red,duration: Int = 600
) {//创建InfiniteTransitionval transition = rememberInfiniteTransition()//使用animateFloat创建透明度动画的State<Float>val alpha by transition.animateFloat(initialValue = 0.3f,targetValue = 1f,animationSpec = infiniteRepeatable(tween(duration),repeatMode = RepeatMode.Reverse))//同理,创建跳动大小动画的State<Float>val beatSize by transition.animateFloat(initialValue = 150f,targetValue = 50f,animationSpec = infiniteRepeatable(tween(duration),repeatMode = RepeatMode.Reverse))Canvas(modifier = modifier) {//...}
}
再改一下原来的Canvas,使用这两个动画参数
//...
Canvas(modifier = modifier) {val minSize = min(size.height, size.width) - beatSize//...drawPath(path, color, alpha)
}
Preview预览效果
这一步早在开发过程中就应该添加了,用Compose的话说:边看边开发,让你更加自信
@Preview
@Composable
fun HeartBeatPre() {HeartBeat()
}
至此就已经实现了这么一个简单的心跳动画,附上源码:
完整源码
/** Copyright (c) 2023.* @username: LiePy* @file: HeartBeat.kt* @project: ComposeAnimationKit* @model: ComposeAnimationKit.ComposeAnimationKit.main* @date: 2023/2/13 下午9:44*/package com.lie.composeanimationkit.animationimport androidx.compose.animation.core.*
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.tooling.preview.Preview
import kotlin.math.min/*** @desc 爱心跳动* @author LiePy* @date 2023/2/13*/@Composable
fun HeartBeat(modifier: Modifier = Modifier.fillMaxSize(),color: Color = Color.Red,duration: Int = 600
) {val transition = rememberInfiniteTransition()val alpha by transition.animateFloat(initialValue = 0.3f,targetValue = 1f,animationSpec = infiniteRepeatable(tween(duration),repeatMode = RepeatMode.Reverse))val beatSize by transition.animateFloat(initialValue = 150f,targetValue = 50f,animationSpec = infiniteRepeatable(tween(duration),repeatMode = RepeatMode.Reverse))Canvas(modifier = modifier) {//最小边作为正方形val minSize = min(size.height, size.width) - beatSizeval path = Path()//右半边爱心path.moveTo(center.x, center.y - minSize / 3)path.relativeCubicTo(minSize / 4, -minSize / 4,minSize / 2, 0f,minSize / 2, minSize / 5)path.relativeCubicTo(0f, minSize / 3,-minSize * 3 / 8, minSize * 3 / 8,-minSize / 2, minSize * 3 / 4)//左半边爱心path.moveTo(center.x, center.y - minSize / 3)path.relativeCubicTo(-minSize / 4, -minSize / 4,-minSize / 2, 0f,-minSize / 2, minSize / 5)path.relativeCubicTo(0f, minSize / 3,minSize * 3 / 8, minSize * 3 / 8,minSize / 2, minSize * 3 / 4)drawPath(path, color, alpha)}
}@Preview
@Composable
fun HeartBeatPre() {HeartBeat()
}
彩蛋
本动画已收录至我的 git 开源库项目,持续更新中。。。
GitHub: ComposeAnimationKit
Gitee: ComposeAnimationKit
导入使用ComposeAnimationKit,更多好玩的动画等你发现,
implementation 'io.github.LiePy:ComposeAnimationKit:1.1.2'
相关文章:

【情人节用Compose给女神写个爱心动画APP】
情人节用Compose给女神写个爱心动画APP前言涉及知识点实现思路实现过程绘制爱心创建动画效果Preview预览效果完整源码彩蛋前言 前一阵子看电视里的学霸用代码写了个炫酷的爱心,网上有很多js和python的源码,复制粘贴就能拥有,但是Android的好…...

GUI swing和awt
GUI(Graphical User Interface,简称 GUI,图形用户界面)是指采用图形方式显示的计算机操作用户界面,与早期计算机使用的命令行界面相比,图形界面对于用户来说在视觉上更易于接受。Java GUI主要有两个核心库&…...

速通Spring
尚硅谷2023最新版Spring6课程_bilibili 1 Spring 【强制】Spring是什么? 1) Spring是一款主流的Java EE轻量级开源框架。 轻量级:体积很小,且不需要依赖于其他组件。 2) 狭义的Spring。 Spring Framework。 3) 广义的Spring。 以Spring F…...

【C++】C++入门
一、 C关键字(C98) C有63个关键字(C语言有32个),如下: asmdoifreturntrycontinueautodoubleinlineshorttypedefforbooldynamic_castintsignedtypeidpublicbreakelselongsizeoftypenamethrowcaseenummutabl…...

Linux网络技术学习(五)—— 网络设备初始化(I)
文章目录什么时候进行的设备初始化?设备注册和初始化NIC(网卡 Network Interface Card)初始化的基本目标设备与内核之间的交互硬件中断中断类型传送节流方式为了改善效率中断共享IRQ处理函数映射的组织irqaction结构体存储方式什么时候进行的…...

[技术选型] ClickHouse和StarRocks的介绍
文章目录1.ClickHouse介绍2.StarRocks介绍1.ClickHouse介绍 ClickHouse是面向联机分析处理(OLAP)的开源分析引擎。最初由俄罗斯第一搜索引擎Yandex开发,于2016年开源,开发语言为C。由于其优良的查询性能,PB级的数据规…...

算法刷题打卡第90天:表现良好的最长时间段
表现良好的最长时间段 难度:中等 给你一份工作时间表 hours,上面记录着某一位员工每天的工作小时数。 我们认为当员工一天中的工作小时数大于 8 小时的时候,那么这一天就是「劳累的一天」。 所谓「表现良好的时间段」,意味在这…...

Python语言零基础入门教程(十七)
Python 文件I/O 本章只讲述所有基本的 I/O 函数,更多函数请参考Python标准文档。 #### 打印到屏幕 最简单的输出方法是用print语句,你可以给它传递零个或多个用逗号隔开的表达式。此函数把你传递的表达式转换成一个字符串表达式,并将结果写…...

C语言中大小端问题
目录 一、什么是大小端 二、 举个例子 三、大小端演示 四、解释"二"中举例的问题 五、怎么判断是大端还是小端 六、一个题目 一、什么是大小端 大端模式(大端字节序存储):就是高位字节数据存放在内存的低地址端ÿ…...

vue2+微前端qiankun从搭建到部署的实践(主子应用切换;集成vue3+vite3子应用)
一、最终效果 二、微前端(qiankun)介绍及为什么选择用微前端,可以看官网 三、目录结构如下 四、具体配置 一、主应用配置 1、主应用技术栈 Vue-cli4搭建项目Vue2Element-Uiqiankun;Vue2Element-Uiqiankun 2、搭建好主项目&…...

怎么代理微信小程序创业?
随着微信的兴起,小程序已经成为了人们生活中不可或缺的一部分。如果你想要创业的话,那么代理微信小程序是一个不错的选择。本文将为大家介绍怎么代理微信小程序创业。 一、什么是微信小程序 微信小程序是一款专为移动设备使用者而设计的应用。它通过扫…...

今天是情人节呐,我利用Python制作了好多表白的东西,快来吧~
今天是情人节那,有没有现在没有对象的宝子,评论里扣个111哈哈 目录 玫瑰 爱心树 丘比特 多彩气球 阿玥的小课堂 一、情人节的由来 二、情人节的来历和意义 玫瑰 局部代码实现如下: # 花瓣1 turtle.left(150) turtle.circle(-90, 70) …...

【Linux】-- 进程信号(处理、内核)
上篇:【Linux】-- 进程信号(认识、应用)_川入的博客-CSDN博客 目录 信号其他相关常见概念 pending handler block 信号处理的过程 sigset_t sigset_t使用 系统接口 sigpending sigprocmask 捕捉方法 sigaction struct sigactio …...

C/【静态通讯录】
🌱博客主页:大寄一场. 🌱系列专栏:C语言学习笔记 😘博客制作不易欢迎各位👍点赞⭐收藏➕关注 前言 往期回顾: C/扫雷 C/N子棋 通讯录作为通讯录地址的书本,当今的通讯录可以涵盖多项…...
万卷书 - 让孩子对自己负责 [The Self-Driven Child]
让孩子对自己负责 The Self-Driven Child - 让你的孩子更加科学合理的掌控自己的生活 简介 《The Self-Driven Child》(2018)解释了我们对孩子的习惯性控制欲,它导致了孩子压力过大、难以合作,以及主观能动性差。本书不提倡这种做法,而是认为我们应该帮助孩子自己做出合适…...
Postman中cookie的操作
在接口测试中,某些接口的调用,需要带入已有Cookie,比如有些接口需要登陆后才能访问。 Postman接口请求使用Cookie有如下两种方式: 1、直接在头域中添加Cookie头域,适用于已经知道请求所用Cookie数据的情况。 2、使用…...

torch.grid_sample
参考: 双线性插值的理论Pytorch grid_sample解析PyTorch中grid_sample的使用方法pytorch中的grid_sample()使用 查阅官方文档,TORCH.NN.FUNCTIONAL.GRID_SAMPLE grid_sample的函数签名如下所示,torch.nn.functional.grid_sample(input, gr…...

前端基于 Docker 的 SSR 持续开发集成环境实践
项目收益 整体开发效率提升20%。加快首屏渲染速度,减少白屏时间,弱网环境下页面打开速度提升40%。 权衡 在选择使用SSR之前,需要考虑以下事项! SSR需要可以运行Node.js的服务器,学习成本相对较高。对于服务器而言&a…...
ARM交叉编译入门及交叉编译第三方库常见问题解析
1. 交叉编译是什么? 交叉编译简单说来,就是编译成果物的地儿不是你运行这个成果物的地儿。最常见的场景,就是我们要编译一个 ARM版本 的可执行程序,但我们编译这个 ARM版本 可执行程序的地方,是在一个 x86_x64 的平台…...
Ruby Web Service 应用 - SOAP4R
什么是 SOAP? 简单对象访问协议(SOAP,全写为Simple Object Access Protocol)是交换数据的一种协议规范。 SOAP 是一种简单的基于 XML 的协议,它使应用程序通过 HTTP 来交换信息。 简单对象访问协议是交换数据的一种协议规范,是一种轻量的、…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...

高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...