【情人节用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 来交换信息。 简单对象访问协议是交换数据的一种协议规范,是一种轻量的、…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
