【SwiftUI模块】0060、SwiftUI基于Firebase搭建一个类似InstagramApp 3/7部分-搭建TabBar
SwiftUI模块系列 - 已更新60篇
SwiftUI项目 - 已更新5个项目
往期Demo源码下载
技术:SwiftUI、SwiftUI4.0、Instagram、Firebase
运行环境:
SwiftUI4.0 + Xcode14 + MacOS12.6 + iPhone Simulator iPhone 14 Pro Max
SwiftUI基于Firebase搭建一个类似InstagramApp 3/7部分-搭建TabBar
- 概述
- 详细
- 一、运行效果
- 二、项目结构图
- 三、程序实现 - 过程
- 1.创建一个项目命名为 `SpotifyResponvieUI`
- 1.1.引入资源文件和颜色
- 2. 创建一个虚拟文件`New Group` 命名为 `View`
- 3. 创建一个虚拟文件`New Group` 命名为 `Model`
- 4. 创建一个文件`New File` 选择`SwiftUI View`类型 命名为`Album` 并且继承`Identifiable`
- 5. 创建一个文件`New File` 选择`SwiftUI View`类型 命名为`Home`
- 6. 创建一个文件`New File` 选择`SwiftUI View`类型 命名为`OffsetModifier`
- Code
- ContentView - 主窗口
- Home - 主页
- OffsetModifier - `主要是监听ScrollView的滚动`
- Album - 模型
概述
使用SwiftUI基于Firebase搭建一个类似InstagramApp 3/7部分-搭建TabBar - 效果
详细
一、运行效果
二、项目结构图
三、程序实现 - 过程
思路:
1.创建头部模块 进行测试上下滚动拥有放大缩小效果
2.搭建分类模块 固定在头部下面
3.搭建列表模块
4.监听滚动偏移的操作
1.创建一个项目命名为 SpotifyResponvieUI
1.1.引入资源文件和颜色
颜色
BG#281A1A
Green#4DD037
随机图片9张
个人大图背景1张
logo1张
2. 创建一个虚拟文件New Group
命名为 View
3. 创建一个虚拟文件New Group
命名为 Model
4. 创建一个文件New File
选择SwiftUI View
类型 命名为Album
并且继承Identifiable
5. 创建一个文件New File
选择SwiftUI View
类型 命名为Home
主要是:
6. 创建一个文件New File
选择SwiftUI View
类型 命名为OffsetModifier
Code
ContentView - 主窗口
主要是展示主窗口
Home
和设置暗黑模式
import SwiftUIstruct ContentView: View {var body: some View {Home()// 永远是黑暗模式.preferredColorScheme(.dark)}}struct ContentView_Previews: PreviewProvider {static var previews: some View {ContentView()}
}
Home - 主页
思路
- 主要就是展示大图背景 + 固定的分类 + 列表模块
//
// Home.swift
// SpotifyResponvieUI (iOS)
//
// Created by lyh on 2022/8/23.
//import SwiftUIstruct Home: View {@State var currentType: String = "Popular"// 光滑滑动效果@Namespace var animation@State var _albums: [Album] = albums// x,y@State var headerOffsets: (CGFloat,CGFloat) = (0,0)var body: some View {ScrollView(.vertical, showsIndicators: false) {VStack(spacing: 0){HeaderView()// 带内容的固定标题LazyVStack(pinnedViews: [.sectionHeaders]) {Section {SongList()} header: {PinnedHeaderView().background(Color.black).offset(y: headerOffsets.1 > 0 ? 0 : -headerOffsets.1 / 8).modifier(OffsetModifier(offset: $headerOffsets.0, returnFromStart: false)).modifier(OffsetModifier(offset: $headerOffsets.1))}}}}.overlay(content: {Rectangle().fill(.black).frame(height: 50).frame(maxHeight: .infinity,alignment: .top).opacity(headerOffsets.0 < 5 ? 1 : 0)}).coordinateSpace(name: "SCROLL").ignoresSafeArea(.container, edges: .vertical)}// 固定的内容@ViewBuilderfunc SongList()->some View{VStack(spacing: 25){ForEach($_albums){$album inHStack(spacing: 12){Text("#\(getIndex(album: album) + 1)").fontWeight(.semibold).foregroundColor(.gray)Image(album.albumImage).resizable().aspectRatio(contentMode: .fill).frame(width: 55, height: 55).clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))VStack(alignment: .leading, spacing: 8) {Text(album.albumName).fontWeight(.semibold)Label {Text("65,587,909")} icon: {Image(systemName: "beats.headphones").foregroundColor(.white)}.foregroundColor(.gray).font(.caption)}.frame(maxWidth: .infinity,alignment: .leading)Button {album.isLiked.toggle()} label: {Image(systemName: album.isLiked ? "suit.heart.fill" : "suit.heart").font(.title3).foregroundColor(album.isLiked ? Color("Green") : .white)}Button {} label: {Image(systemName: "ellipsis").font(.title3).foregroundColor(.white)}}}}.padding().padding(.top,25).padding(.bottom,150)}func getIndex(album: Album)->Int{return _albums.firstIndex { currentAlbum inreturn album.id == currentAlbum.id} ?? 0}// 头部视图@ViewBuilderfunc HeaderView()->some View{GeometryReader{proxy inlet minY = proxy.frame(in: .named("SCROLL")).minYlet size = proxy.sizelet height = (size.height + minY)Image("Ariana").resizable().aspectRatio(contentMode: .fill).frame(width: size.width,height: height > 0 ? height : 0,alignment: .top).overlay(content: {ZStack(alignment: .bottom) {// 调暗文本内容LinearGradient(colors: [.clear,.black.opacity(0.8)], startPoint: .top, endPoint: .bottom)VStack(alignment: .leading, spacing: 12) {Text("宇夜iOS").font(.callout).foregroundColor(.gray)HStack(alignment: .bottom, spacing: 10) {Text("Ariana Grande").font(.title.bold())Image(systemName: "checkmark.seal.fill").foregroundColor(.blue).background{Circle().fill(.white).padding(3)}}Label {Text("Monthly Listeners").fontWeight(.semibold).foregroundColor(.white.opacity(0.7))} icon: {Text("62,354,659").fontWeight(.semibold)}.font(.caption)}.padding(.horizontal).padding(.bottom,25).frame(maxWidth: .infinity,alignment: .leading)}}).cornerRadius(15).offset(y: -minY)}.frame(height: 250)}// 固定在头部@ViewBuilderfunc PinnedHeaderView()->some View{let types: [String] = ["Popular","Albums","Songs","Fans also like","About"]ScrollView(.horizontal, showsIndicators: false) {HStack(spacing: 25){ForEach(types,id: \.self){type inVStack(spacing: 12){Text(type).fontWeight(.semibold).foregroundColor(currentType == type ? .white : .gray)ZStack{if currentType == type{RoundedRectangle(cornerRadius: 4, style: .continuous).fill(.white).matchedGeometryEffect(id: "TAB", in: animation)}else{RoundedRectangle(cornerRadius: 4, style: .continuous).fill(.clear)}}.padding(.horizontal,8).frame(height: 4)}.contentShape(Rectangle()).onTapGesture {withAnimation(.easeInOut){currentType = type}}}}.padding(.horizontal).padding(.top,25).padding(.bottom,5)}}
}struct Home_Previews: PreviewProvider {static var previews: some View {ContentView()}
}
OffsetModifier - 主要是监听ScrollView的滚动
用来监听ScrollView的滚动 偏移量的改变
//
// OffsetModifier.swift
// SpotifyResponvieUI (iOS)
//
// Created by lyh on 2022/8/23.
//import SwiftUI// 继承于 ViewModifier 最主要是能方便扩展一些常见的设置属性
/*比如 给Text设置字体\背景颜色\阴影效果extension Text {func songStyle() -> some View {self.font(.system(size: 24, weight: .bold)).foregroundColor(.white).shadow(radius: 20)}}⭐️如果是继承ViewModifierstruct SongTextViewModifier: ViewModifier {func body(content: Content) -> some View {content.font(.system(size: 24, weight: .bold)).foregroundColor(.white).shadow(radius: 20)}}然后直接通过Text(song).modifier(SongTextViewModifier())设置*/struct OffsetModifier: ViewModifier {@Binding var offset: CGFloat// 可选从0返回值var returnFromStart: Bool = true@State var startValue: CGFloat = 0func body(content: Content) -> some View {content.overlay {GeometryReader{proxy inColor.clear.preference(key: OffsetKey.self, value: proxy.frame(in: .named("SCROLL")).minY).onPreferenceChange(OffsetKey.self) { value inif startValue == 0{startValue = value}print(value);offset = (value - (returnFromStart ? startValue : 0))print("offset is \(offset)");}}}}
}// 偏好的关键
struct OffsetKey: PreferenceKey{static var defaultValue: CGFloat = 0static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {value = nextValue()}
}
Album - 模型
//
// Album.swift
// SpotifyResponvieUI (iOS)
//
// Created by lyh on 2022/8/23.
//import SwiftUI// Ablum模型和样本数据
struct Album: Identifiable {var id = UUID().uuidStringvar albumName: Stringvar albumImage : Stringvar isLiked : Bool = false
}var albums : [Album] = [Album(albumName: "Positions", albumImage: "Album1"),Album(albumName: "The Best", albumImage: "Album2",isLiked: true),Album(albumName: "My Everything", albumImage: "Album3"),Album(albumName: "Yours Truly", albumImage: "Album4"),Album(albumName: "Sweetener", albumImage: "Album5",isLiked: true),Album(albumName: "Rain On Me", albumImage: "Album6"),Album(albumName: "Stuck With U", albumImage: "Album7"),Album(albumName: "7 rings", albumImage: "Album8",isLiked: true),Album(albumName: "Bang Bang", albumImage: "Album9"),]
相关文章:

【SwiftUI模块】0060、SwiftUI基于Firebase搭建一个类似InstagramApp 3/7部分-搭建TabBar
SwiftUI模块系列 - 已更新60篇 SwiftUI项目 - 已更新5个项目 往期Demo源码下载 技术:SwiftUI、SwiftUI4.0、Instagram、Firebase 运行环境: SwiftUI4.0 Xcode14 MacOS12.6 iPhone Simulator iPhone 14 Pro Max SwiftUI基于Firebase搭建一个类似InstagramApp 3/7部分-搭建Tab…...
PureFlash云原生存储部署方法
PureFlash云原生存储 PureFlash是一个开源存储系统,它能为云计算和传统应用提供块存储服务。PureFlash最显著的优势是其高性能,每节点能提供超过100万IOPS随机写IO。 PureFlash可以以云原生的方式部署,并为云原生应用提供持久存储。 PureFl…...

SqueezeNet 一维,二维网络复现 pytorch 小白易懂版
SqueezeNet 时隔一年我又开始复现神经网络的经典模型,这次主要复的是轻量级网络全家桶,轻量级神经网络旨在使用更小的参数量,无限的接近大模型的准确率,降低处理时间和运算量,这次要复现的是轻量级网络的非常经典的一…...
Java 数据结构
枚举 Java枚举是一种特殊的类,它用于定义有限个特定的值,例如一周的星期或者性别。枚举在Java中被视为数据类型,你可以使用它们来创建枚举类型的变量,然后使用那些枚举值等。 在Java中,声明枚举类型需要使用enum关键字…...

python sqlalchemy(ORM)- 02 表关系
文章目录 表关系ORM表示 1v1ORM表示 1vm 表关系 1:1,表A 中的一条记录,仅对应表B中的一条记录;表B的一条记录,仅对应表A的一条记录。1:m,表A中的一条记录,对应表B中的多条记录,表B中的一条记录…...

Http长连接同一个socket多个请求和响应如何保证一一对应?
HTTP/2引入二进制数据帧和流的概念,其中帧对数据进行顺序标识,如下图所示,这样浏览器收到数据之后,就可以按照序列对数据进行合并,而不会出现合并后数据错乱的情况。同样是因为有了序列,服务器就可以并行的…...

Standford Compiler Course Assignment 2
第二部分的作业是语法分析,通过编写cool.y(这个assignment的任务),利用bison将其自动生成语法分析LALR(1)的代码。 语法分析,就是将词法分析阶段已经识别好的token,按照语法的规则,构建抽象语法树的过程。 比如以下的…...

基于Java的校园论坛管理系统设计与实现(源码+lw+部署文档+讲解等)
文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding) 代码参考数据库参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…...

谈谈你对Spring的理解
谈谈你对Spring的理解 一,什么是Spring 1.介绍 Spring是一个用于开发Java应用程序的工具集合,它提供了许多方便的组件和工具,可以帮助开发者更轻松地构建企业级应用程序。 Spring Framework是Spring的核心部分,它可以帮助开发者…...
系统架构师考试易混淆知识点总结
易混淆点1:系统工程生命周期与信息系统的生命周期 1、系统工程生命周期阶段 探索性研究→概念阶段→开发阶段→生产阶段→使用阶段→保障阶段→退役阶段 2、信息系统的生命周期 产生阶段→开发阶段(单个系统开发:总体规划、系统分析、系统设计、系统实施、系统验收…...

反射的作用( 越过泛型检查 和 可以使用反射保存所有对象的具体信息 )
1、绕过 编译阶段 为集合添加数据 反射是作用在运行时的技术,此时集合的泛型将不能产生约束了,此时是可以 为集合存入其他任意类型的元素的 。泛型只是在编译阶段可以约束集合只能操作某种数据类型,在 编译成Class文件进入 运行阶段 的时候&a…...

前端开发实践:vue中用qrcode库将超链接生成二维码图片
🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,阿里云社区专家博主,2023年6月csdn上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责…...

数据库连接池有什么用?它有哪些关键参数?
首先,数据库连接池是一种池化技术,池化技术的核心思想是实现资源的复用,避免资源重复创建销毁的开销。而在数据库的应用场景里面,应用程序每次向数据库发起 CRUD 操作的时候,都需要创建连接.在数据库访问量较大的情况下…...

Android Settings解析
Android Settings 系列文章: Android Settings解析SettingsIntelligenceSettingsProvider 首语 Android设置应用是Android系统中一个非常重要的系统应用,它允许用户调整和设置系统的各种参数和功能(系统设置/自定义设置/控制应用权限/开发…...

Spring+spring mvc+mybatis整合的框架
Spring是一个轻量级的企业级应用开发框架,于2004年由Rod Johnson发布了1.0版本,经过多年的更新迭代,已经逐渐成为Java开源世界的第一框架,Spring框架号称Java EE应用的一站式解决方案,与各个优秀的MVC框架如SpringMVC、…...

02-2、PyCharm中文乱码的三处解决方法
PyCharm中文乱码 修改处1: 修改处2:这个也没用 在Pycharm中可以创建一个模版,每次新建python文件时Pycharm会默认在前两行生成utf-8 #!/user/bin/env python3 # -- coding: utf-8 -- 还是乱码 再在这里设置以下 添加 : -Dfi…...

Axi接口的DDR3:参数,时序,握手机制
参考 AXI总线的Burst Type以及地址计算 | WRAP到底是怎么一回事?_axi wrap-CSDN博客 还有官方手册,名字太长想起来再写。 Transaction/Burst/Transfer/Beat Transaction指一次传输事务,实际上包括了address phase, data phase与response ph…...

浏览器标签上添加icon图标;html引用ico文件
实例 <link rel"shortcut icon" href"./XXX.ico" type"image/x-icon">页面和图标在同一目录内 则 <link rel"shortcut icon" type"text/css" href"study.ico"/>可以阿里矢量图库关键字搜索下载自己…...

深入解析i++和++i的区别及性能影响
在我们编写代码时,经常需要对变量进行自增操作。这种情况下,我们通常会用到两种常见的操作符:i和i。最近在阅读博客时,我偶然看到了有关i和i性能的讨论。之前我一直在使用它们,但从未从性能的角度考虑过,这…...

2023年中国酒类新零售行业发展概况分析:线上线下渠道趋向深度融合[图]
近年来,我国新零售业态不断发展,线上便捷性和个性化推荐的优势逐步在放大,线下渠道智慧化水平持续提升,线上线下渠道趋向深度融合。2022年,我国酒类新零售市场规模约为1516亿元,预计2025年酒类新零售市场规…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...