【SwiftUI模块】0059、SwiftU自定义AppStore

2023-10-07 21:59

本文主要是介绍【SwiftUI模块】0059、SwiftU自定义AppStore,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

SwiftUI模块系列 - 已更新59篇
SwiftUI项目 - 已更新5个项目
往期Demo源码下载

技术:SwiftUI、SwiftUI4.0、AppStore、AppStoreUI
运行环境:
SwiftUI4.0 + Xcode14 + MacOS12.6 + iPhone Simulator iPhone 14 Pro Max

SwiftUI-搭建一个自定义AppStoreUI

    • 概述
    • 详细
      • 一、运行效果
      • 二、项目结构图
      • 三、程序实现 - 过程
        • 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做一个自定义AppStoreUI - 效果

详细

一、运行效果

请添加图片描述

二、项目结构图

在这里插入图片描述

三、程序实现 - 过程

思路:
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 - 主页

思路

  1. 主要就是展示大图背景 + 固定的分类 + 列表模块
//
//  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模块】0059、SwiftU自定义AppStore的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/160685

相关文章

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并

Python通用唯一标识符模块uuid使用案例详解

《Python通用唯一标识符模块uuid使用案例详解》Pythonuuid模块用于生成128位全局唯一标识符,支持UUID1-5版本,适用于分布式系统、数据库主键等场景,需注意隐私、碰撞概率及存储优... 目录简介核心功能1. UUID版本2. UUID属性3. 命名空间使用场景1. 生成唯一标识符2. 数

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提

Java实现自定义table宽高的示例代码

《Java实现自定义table宽高的示例代码》在桌面应用、管理系统乃至报表工具中,表格(JTable)作为最常用的数据展示组件,不仅承载对数据的增删改查,还需要配合布局与视觉需求,而JavaSwing... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

一文详解Java Stream的sorted自定义排序

《一文详解JavaStream的sorted自定义排序》Javastream中的sorted方法是用于对流中的元素进行排序的方法,它可以接受一个comparator参数,用于指定排序规则,sorte... 目录一、sorted 操作的基础原理二、自定义排序的实现方式1. Comparator 接口的 Lam

一文深入详解Python的secrets模块

《一文深入详解Python的secrets模块》在构建涉及用户身份认证、权限管理、加密通信等系统时,开发者最不能忽视的一个问题就是“安全性”,Python在3.6版本中引入了专门面向安全用途的secr... 目录引言一、背景与动机:为什么需要 secrets 模块?二、secrets 模块的核心功能1. 基

如何自定义一个log适配器starter

《如何自定义一个log适配器starter》:本文主要介绍如何自定义一个log适配器starter的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录需求Starter 项目目录结构pom.XML 配置LogInitializer实现MDCInterceptor

Druid连接池实现自定义数据库密码加解密功能

《Druid连接池实现自定义数据库密码加解密功能》在现代应用开发中,数据安全是至关重要的,本文将介绍如何在​​Druid​​连接池中实现自定义的数据库密码加解密功能,有需要的小伙伴可以参考一下... 目录1. 环境准备2. 密码加密算法的选择3. 自定义 ​​DruidDataSource​​ 的密码解密3

spring-gateway filters添加自定义过滤器实现流程分析(可插拔)

《spring-gatewayfilters添加自定义过滤器实现流程分析(可插拔)》:本文主要介绍spring-gatewayfilters添加自定义过滤器实现流程分析(可插拔),本文通过实例图... 目录需求背景需求拆解设计流程及作用域逻辑处理代码逻辑需求背景公司要求,通过公司网络代理访问的请求需要做请

Python logging模块使用示例详解

《Pythonlogging模块使用示例详解》Python的logging模块是一个灵活且强大的日志记录工具,广泛应用于应用程序的调试、运行监控和问题排查,下面给大家介绍Pythonlogging模... 目录一、为什么使用 logging 模块?二、核心组件三、日志级别四、基本使用步骤五、快速配置(bas