swiftui使用教程,swiftui开发框架搭建
墨初 知识笔记 137阅读
SwiftUI模块系列 - 已更新60篇
SwiftUI项目 - 已更新5个项目
往期Demo源码下载
技术:SwiftUI、SwiftUI4.0、Instagram、Firebase
运行环境:
SwiftUI4.0 Xcode14 MacOS12.6 iPhone Simulator iPhone 14 Pro Max

SwiftUI基于Firebase搭建一个类似InstagramApp 2/7部分-搭建TabBar 概述详细一、运行效果二、项目结构图三、程序实现 - 过程1.创建一个项目命名为 SpotifyResponvieUI1.1.引入资源文件和颜色2. 创建一个虚拟文件New Group 命名为 View3. 创建一个虚拟文件New Group 命名为 Model4. 创建一个文件New File 选择SwiftUI View类型 命名为Album 并且继承Identifiable5. 创建一个文件New File 选择SwiftUI View类型 命名为Home6. 创建一个文件New File 选择SwiftUI View类型 命名为OffsetModifier CodeContentView - 主窗口Home - 主页OffsetModifier - 主要是监听ScrollView的滚动Album - 模型
概述

使用SwiftUI基于Firebase搭建一个类似InstagramApp 2/7部分-搭建TabBar - 效果
详细 一、运行效果 二、项目结构图 三、程序实现 - 过程思路:
1.创建头部模块 进行测试上下滚动拥有放大缩小效果
2.搭建分类模块 固定在头部下面
3.搭建列表模块
4.监听滚动偏移的操作
SpotifyResponvieUI
颜色
BG #281A1A
Green #4DD037
随机图片9张
个人大图背景1张
logo1张
New Group
命名为 View
New Group
命名为 Model
New File
选择SwiftUI View
类型 命名为Album
并且继承Identifiable
New File
选择SwiftUI View
类型 命名为Home
主要是:
New File
选择SwiftUI View
类型 命名为OffsetModifier
主要是展示主窗口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) } // 固定的内容 ViewBuilder func SongList()->some View{ VStack(spacing: 25){ ForEach($_albums){$album in HStack(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 in return album.id currentAlbum.id } ?? 0 } // 头部视图 ViewBuilder func HeaderView()->some View{ GeometryReader{proxy in let minY proxy.frame(in: .named(SCROLL)).minY let size proxy.size let 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) } // 固定在头部 ViewBuilder func 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 in VStack(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) } } ⭐️如果是继承ViewModifier struct 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 0 func body(content: Content) -> some View { content .overlay { GeometryReader{proxy in Color.clear .preference(key: OffsetKey.self, value: proxy.frame(in: .named(SCROLL)).minY) .onPreferenceChange(OffsetKey.self) { value in if startValue 0{ startValue value } print(value); offset (value - (returnFromStart ? startValue : 0)) print(offset is \(offset)); } } } }}// 偏好的关键struct OffsetKey: PreferenceKey{ static var defaultValue: CGFloat 0 static 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().uuidString var albumName: String var albumImage : String var 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), ]