• 【SwiftUI模块】0024、SwiftUI创建一个时尚的3D轮播滑块


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

    技术:SwiftUI、SwiftUI3.0、3D、轮播滑块、3D轮播滑轮
    运行环境:
    SwiftUI3.0 + Xcode13.4.1 + MacOS12.5 + iPhone Simulator iPhone 13 Pro Max

    概述

    SwiftUI创建一个时尚的3D轮播滑块

    详细

    一、运行效果

    请添加图片描述

    二、项目结构图

    在这里插入图片描述

    三、程序实现 - 过程

    思路:
    1.创建主页 并且使用tabView加载多张图片进行滚动
    2.给每张旋转木马图片设置3D动画处理
    3.统一使用滚动视图偏移的处理器进行处理偏移问题

    1.创建一个项目命名为 MatchedCarousel

    在这里插入图片描述
    在这里插入图片描述

    1.1.引入资源文件和颜色

    颜色
    随机图片8张
    在这里插入图片描述

    2. 创建一个虚拟文件New Group 命名为 View

    在这里插入图片描述
    在这里插入图片描述

    3. 创建一个文件New File 选择SwiftUI View类型 命名为Home

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    4. 创建一个文件New File 选择SwiftUI View类型 命名为CarouselBodyView

    主要是: 用来加载TabView的每一张图片的3d转场动画的处理

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    5. 创建一个文件New File 选择SwiftUI View类型 命名为ScrollViewOffsetModifier

    在这里插入图片描述
    在这里插入图片描述

    Code

    ContentView - 主窗口

    主要是展示主窗口Home

    //
    //  ContentView.swift
    //  Shared
    //
    //  Created by 李宇鸿 on 2022/9/5.
    //
    
    import SwiftUI
    
    struct ContentView: View {
        var body: some View {
           Home()
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    Home - 主页

    思路

    1. 主要是用来展示tabView的多张图片
    //
    //  Home.swift
    //  MatchedCarousel (iOS)
    //
    //  Created by 李宇鸿 on 2022/9/5.
    //
    
    import SwiftUI
    
    struct Home: View {
        
        
        // 背景将是当前标签图像…
        @State var currentTab = "p1"
        var body: some View {
            ZStack{
                // 获取屏幕大小的几何读取器…
                GeometryReader{proxy in
                    let size = proxy.size
                    
                    Image(currentTab)
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                        .frame(width: size.width, height: size.height)
                        .cornerRadius(1)
                    
                }
                .ignoresSafeArea()
                // 材料的效果……
                .overlay(.ultraThinMaterial)
                // 暗黑模式
                .colorScheme(.dark)
    
                // 旋转木马列表
                TabView(selection: $currentTab) {
                    ForEach(1...7,id:\.self){index  in
                        
                        // 旋转木马视图
                        CarouselBodyView(index:index)
                    }
                }
                
                //页面标签风格……
                .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
                
                
            }
    
        }
    }
    
    struct Home_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    CarouselBodyView - 每一张3D转场动画的图片
    //
    //  CarouselBodyView.swift
    //  MatchedCarousel (iOS)
    //
    //  Created by 李宇鸿 on 2022/9/5.
    //
    
    import SwiftUI
    
    struct CarouselBodyView: View {
        var index : Int
        // Offset
        @State var offset : CGFloat = 0
        var body: some View {
           
            GeometryReader{proxy in
                let size = proxy.size
                
                ZStack{
                    Image("p\(index)")
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                        .frame(width: size.width - 8, height: size.height / 1.2)
                        .cornerRadius(12)
                    
                    VStack{
                        VStack(alignment: .leading, spacing: 10) {
                            Text("Human Integration Supervisor")
                                .font(.title2.bold())
                            //letter spacing...
                                .kerning(1.5)
                            
                            Text("The world's largest collection of animal facts, pictures and more!")
                                .kerning(1.2)
                                .foregroundStyle(.secondary)
    
                        }
                        .foregroundStyle(.white)
                        .padding(.top)
                        Spacer(minLength: 0)
                        
                        
                        VStack(alignment:.leading, spacing:30){
                            HStack(spacing:15){
                                Image("justine")
                                    .resizable()
                                    .aspectRatio(contentMode: .fill)
                                    .frame(width: 55, height: 55)
                                    .clipShape(Circle())
                                
                                VStack(alignment: .leading, spacing: 6) {
                                    
                                    Text("iJustine")
                                        .font(.title2.bold())
                                    
                                    Text("Apple Sheep")
                                        .foregroundStyle(.secondary)
                                }
                                .foregroundStyle(.black)
                                
                                
                                
                            }
                        
                            
                            HStack{
                                VStack{
                                    Text("1303")
                                        .font(.title2.bold())
                                    Text("Posts")
                                        .foregroundStyle(.secondary)
                                }
                                .frame(maxWidth:.infinity)
                                
                                
                                VStack{
                                    Text("3103")
                                        .font(.title2.bold())
                                    Text("Followers")
                                        .foregroundStyle(.secondary)
                                }
                                .frame(maxWidth:.infinity)
                                
                                
                                VStack{
                                    Text("1503")
                                        .font(.title2.bold())
                                    Text("Following")
                                        .foregroundStyle(.secondary)
                                }
                                .frame(maxWidth:.infinity)
                                
                                
                            }
                            .foregroundStyle(.black)
                            
                        }
                        .padding(20)
                        .padding(.horizontal,10)
                        .background(.white,in:RoundedRectangle(cornerRadius: 4))
                    }
                    .padding(20)
    
                }
                .frame(width: size.width - 8, height: size.height / 1.2)
                .frame(width: size.width, height: size.height)
                
            }
            // 设置tag
            .tag("p\(index)")
             //旋转……
            //基于偏移量的锚
            .rotation3DEffect(.init(degrees: getProgress() * 90), axis: (x: 0, y: 1, z: 0),anchor: offset > 0 ? .leading : .trailing,anchorZ: 0,perspective: 0.6)
            
    
            //自定义3D旋转…
    		//因为我们需要从0开始,所以我们得到前导偏移量…
            .modifier(ScrollViewOffsetModifier(anchorPoint: .leading, offset: $offset))
    //        .overlay(Text("\(offset)").foregroundColor(.white))
            
            
            
        }
        
        
        // 获取进度
        func getProgress()-> CGFloat{
            let progress = -offset / UIScreen.main.bounds.width
            return progress
        }
    }
    
    struct CarouselBodyView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    ScrollViewOffsetModifier - 主要是监听ScrollView的滚动

    用来监听ScrollView的滚动 偏移量的改变

    //
    //  ScrollViewOffsetModifier.swift
    //  MatchedCarousel (iOS)
    //
    //  Created by 李宇鸿 on 2022/9/5.
    //
    
    import SwiftUI
    
    struct ScrollViewOffsetModifier: ViewModifier {
      
        var anchorPoint : Anchor = .top
        @Binding var offset : CGFloat
        
        func body(content: Content)-> some View{
            content
                .overlay(
                    GeometryReader{proxy -> Color in
                        let frame = proxy.frame(in:.global)
                        
                        DispatchQueue.main.async {
                            
                            switch anchorPoint {
                            case .top:
                                offset = frame.minY
                            case .bottom:
                                offset = frame.maxY
                            case .leading:
                                offset = frame.minX
                            case .trailing:
                                offset = frame.maxX
                            }
                            
                        }
                        
                        return Color.clear
                        
                    }
                )
        }
        
    }
    
    
    //自定义修改ScrollView或标签视图…
    //枚举自定义锚…
    
    enum Anchor{
        case top
        case bottom
        case leading
        case trailing
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
  • 相关阅读:
    C++Primer第五版 第十四章习题答案(1~5)
    windows/ubuntu怎么修改hosts文件
    web综合案例_day02
    Nginx动静分离、URLRwrite、防盗链及Https证书配置
    2023年全球市场氮化铝外延片总体规模、主要生产商、主要地区、产品和应用细分研究报告
    Win11查看电脑磁盘分区格式的方法教学
    人工智能-卷积神经网络
    【安卓学习之常见问题】jar文件中Class转java文件不准(不同软件打开的class文件不一样)
    在Ubuntu20.04安装Kylin4 On Docker并在DataGrip配置JDBC协议连接容器内Hive1.2.1及Kylin4.0.0
    set容器 集合 常用 API操作 (只读迭代器)
  • 原文地址:https://blog.csdn.net/qq_42816425/article/details/126696686