首页 > 其他分享 >swiftui轮播图

swiftui轮播图

时间:2024-10-31 18:18:56浏览次数:5  
标签:index 轮播 spacing width swiftui currentIndex var currentTab

import SwiftUI

struct Post: Identifiable {
    
    var id = UUID().uuidString
    var postImage: String
}
import SwiftUI

struct SnapCarousel<Content: View, T: Identifiable>: View {

    var content: (T) -> Content
    var list: [T]
    
    // properties
    var spacing: CGFloat
    var trailingSpace: CGFloat
    @Binding var index: Int
    
    init(spacing: CGFloat = 15, trailingSpace: CGFloat = 100, index: Binding<Int>, items: [T], @ViewBuilder content: @escaping (T) -> Content) {
        
        self.list = items
        self.spacing = spacing
        self.trailingSpace = trailingSpace
        self._index = index
        self.content = content
    }
    
    @GestureState var offset: CGFloat = 0
    @State var currentIndex: Int = 0
    
    var body: some View {
        
        GeometryReader { proxy in
            
            let width = proxy.size.width - (trailingSpace - spacing)
            let adjustMentWidth = (trailingSpace / 2) - spacing
            
            HStack(spacing: spacing) {
                
                ForEach(list) { item in
                    content(item)
                        .frame(width: proxy.size.width - trailingSpace)
                }
            }
            .padding(.horizontal, spacing)
            .offset(x: (CGFloat(currentIndex) * -width) + (currentIndex != 0 ? adjustMentWidth : 0) + offset)
            .gesture(
            DragGesture()
                .updating($offset, body: { value, out, _ in
                    
                    out = value.translation.width
                })
                .onEnded({ value in
                    
                    let offsetX = value.translation.width
                    
                    let progress = -offsetX / width
                    
                    let roundIndex = progress.rounded()
                    
//                    currentIndex += Int(roundIndex)
                    currentIndex = max(min(currentIndex + Int(roundIndex), list.count - 1), 0)
                    
                    currentIndex = index
                })
                .onChanged({ value in
                    
                    let offsetX = value.translation.width
                    
                    let progress = -offsetX / width
                    
                    let roundIndex = progress.rounded()
                    
                    index = max(min(currentIndex + Int(roundIndex), list.count - 1), 0)
                
                })
            )
        }
        .animation(.easeInOut, value: offset == 0)
    }
}
  • SnapCarousel 是一个通用结构体,它接收两个类型参数:Content:表示视图的内容,必须符合 View 协议。T:表示数据模型,并且必须遵循 Identifiable 协议,这样SwiftUI 能够识别和管理数据集中的每个元素。

    • content: 一个闭包,用于生成视图内容。

    • list: 一个数组,包含要在轮播中显示的元素。

    • 使用 DragGesture 来捕捉用户的拖动。

    • 当手势更新时,通过 updating 方法来设置偏移量。

    • 在手势结束时计算出当前应该显示的索引,并更新 currentIndex 和绑定的 index

    • 在手势变化时,也会更新绑定的 index

import SwiftUI

struct Banner: View {
    @State var currentIndex: Int = 0
    @State var posts: [Post] = []
    @State var currentTab = "Slide Show"
    @Namespace var animation
    
    var body: some View {
        
        VStack(spacing: 15) {
            
            VStack(alignment: .leading, spacing: 12) {
                
                Button {
                    
                }label: {
                    
                    Label {
                        Text("Back")
                            .fontWeight(.semibold)
                    } icon: {
                        Image(systemName: "chevron.left")
                            .font(.title2.bold())
                    }
                    .foregroundColor(.primary)
                }
                
                Text("My Wishes")
                    .font(.title)
                    .fontWeight(.black)
            }
            .frame(maxWidth: .infinity, alignment: .leading)
            .padding()
            
            // segment Control
            HStack(spacing: 0) {
                
                TabButton(title: "Slide Show", animation: animation, currentTab: $currentTab)
                TabButton(title: "List", animation: animation, currentTab: $currentTab)
            }
            .background(Color.black.opacity(0.04), in: RoundedRectangle(cornerRadius: 10))
            .padding(.horizontal)
            
            // Snap Carousel
            SnapCarousel(index: $currentIndex, items: posts) { post in
                
                GeometryReader { proxy in
                    let size = proxy.size
                    
                    Image(post.postImage)
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                        .frame(width: size.width)
                        .cornerRadius(12)
                }
            }
            .padding(.vertical, 40)
            
            // Indicator
            HStack(spacing: 10) {
                
                ForEach(posts.indices, id: \.self) { index in
                    
                    Circle()
                        .fill(Color.black.opacity(currentIndex == index ? 1 : 0.1))
                        .frame(width: 10, height: 10)
                        .scaleEffect(currentIndex == index ? 1.4 : 1)
                        .animation(.spring(), value: currentIndex == index)
                }
            }
            .padding(.bottom, 40)
        }
        .frame(maxHeight: .infinity, alignment: .top)
        .onAppear {
            for index in 1...4 {
                posts.append(Post(postImage: "banner\(index)"))
            }
        }
    }
}

struct Banner_Previews: PreviewProvider {
    static var previews: some View {
        Banner()
    }
}


// TabButton
struct TabButton: View {
    
    var title: String
    var animation: Namespace.ID
    @Binding var currentTab: String
    
    var body: some View {
        
        Button {
            
            withAnimation(.spring()) {
                
                currentTab = title
            }
        }label: {
            
            Text(title)
                .fontWeight(.bold)
                .foregroundColor(currentTab == title ? .white : .black)
                .frame(maxWidth: .infinity)
                .padding(.vertical, 8)
                .background(
                
                    ZStack {
                        
                        if currentTab == title {
                            RoundedRectangle(cornerRadius: 10)
                                .fill(.black)
                                .matchedGeometryEffect(id: "TAB", in: animation)
                        }
                    }
                )
        }
    }
}

标签:index,轮播,spacing,width,swiftui,currentIndex,var,currentTab
From: https://blog.csdn.net/qq_63007445/article/details/143402941

相关文章

  • ng-zorro走马灯carousel轮播图不自动轮播问题
    原文链接:ng-zorro走马灯carousel轮播图不自动轮播问题–每天进步一点点 angular项目(angular7),ng-zorro(7.5.x)使用carousel走马灯设置自动轮播图功能,从官网上copy下一段代码如下:<nz-carouselnzAutoPlay><divnz-carousel-content*ngFor="letindexofarray">......
  • swiftui之覆盖、跳转页面
    Color.black.edgesIgnoringSafeArea(.all):创建一个黑色背景,并扩展至安全区域外。importSwiftUIstructJumpView:View{@StatevarshowHome=falsevarbody:someView{ZStack{Color.black.edgesIgnoringSafeArea(.all)......
  • SwiftUI 中.sheet的简单使用
    在SwiftUI中,使用.sheet显示视图时,可以通过状态变量来控制视图的显示和隐藏。onDismiss 在视图关闭时执行某些操作。structCatView:View{@StateprivatevarshowSheet=false//控制视图的显示状态@Stateprivatevarmessage=""//用于显示的信息......
  • vue3 使用swiper轮播组件
    1.本地环境信息参考node版本:nodejs:v18.20.4npm:10.7.0vue版本"dependencies":{"vue":"^3.2.13",...}2.安装swiper依赖执行命令:npmiswiper安装后,查看工程中的package.json文件,新增了swiper依赖(默认最新版):"dependencies":{......
  • 原生js实现列表内容向上滚动,列表内容向上轮播
    <divid="review_box"><ulid="conent1"><li>第一条内容</li><li>第二条内容</li><li>第三条内容</li><li>第四条内容</li><li>第五条内容</li>......
  • el-table轮播
    <el-tableref="reportTable":data="tableData"stripestyle="width:98%;margin:0auto;"><!--<el-table-columnprop="rank"label="排名"align="center"></el-......
  • 无缝轮播图
    ```html<template> <!--@touchend="handleTouchEnd"--> <!--@touchstart="handleTouchStart"--> <divclass="carousel-conainer">  <div   class="carousel-list"   :style=&quo......
  • 网站后台修改首页轮播图?
    登录后台管理系统打开浏览器,输入后台管理系统的地址。输入用户名和密码进行登录。进入轮播图管理页面登录后,找到并点击“内容管理”或类似名称的菜单。在子菜单中选择“轮播图管理”或“首页轮播图”。编辑现有轮播图在轮播图列表中,找到需要修改的轮播图。点击......
  • 手风琴、轮播图案例
    摸鱼时,水一篇博客咯~~~分享两个小案例!!!!!!!!!!!!前言手风琴:仿王者荣耀做的一个小案例,结合JQuery.js轮播图:仿华泰保险官网首页图做的小案例,结合ant-design-vue轮播图使用一、手风琴效果图代码<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname=......
  • 网站后台修改模板?公司网站轮播如何修改?
    网站后台修改模板登录后台:使用管理员账号登录网站后台。导航至模板管理:在后台主界面中找到“模板管理”、“主题设置”或类似的选项。选择模板:从模板列表中选择当前使用的模板或想要切换的新模板。编辑模板:进入模板编辑页面,可以对模板的样式、布局等进行调整。......