SwiftUI使用DragGesture实现拖动切换视图时黑色背景过渡的方法
实现方案
核心调整思路是不再用if条件控制两个视图的显隐,而是让两个视图常驻视图层级,通过拖动偏移量实时控制两个视图的位置、透明度,同时在层级底层加固定黑色背景层,即可实现拖动过程中的实时过渡效果。
完整实现代码
struct Swipe: View { // 滑动容器宽度,可根据实际需求调整 private let containerWidth: CGFloat = UIScreen.main.bounds.width // 标记当前显示的视图:0=矩形 1=圆形 @State private var currentIndex: Int = 0 @State private var xOffset: CGFloat = 0.0 var body: some View { VStack { Text("Current xOffset: \(xOffset)") ZStack(alignment: .center) { // 黑色过渡背景 Color.black .frame(width: containerWidth, height: 300) // 矩形视图 Rectangle() .foregroundColor(.red) .frame(width: 100, height: 100) // 实时计算偏移:选中时跟随拖动偏移,未选中时向左移出容器 .offset(x: xOffset + CGFloat(currentIndex == 0 ? 0 : -containerWidth)) // 透明度跟随拖动进度变化 .opacity(1 - abs(xOffset) / containerWidth) // 圆形视图 Circle() .frame(width: 250, height: 250) .foregroundColor(.blue) // 实时计算偏移:选中时跟随拖动偏移,未选中时向右移出容器 .offset(x: xOffset + CGFloat(currentIndex == 1 ? 0 : containerWidth)) .opacity(abs(xOffset) / containerWidth) } .frame(width: containerWidth, height: 300) .clipped() // 裁剪容器外的视图,避免未展示的视图漏出 .gesture( DragGesture() .onChanged { value in xOffset = value.translation.width } .onEnded { value in withAnimation(.spring()) { // 拖动距离超过容器1/3则触发视图切换 let threshold = containerWidth / 3 if value.translation.width < -threshold { currentIndex = min(currentIndex + 1, 1) } else if value.translation.width > threshold { currentIndex = max(currentIndex - 1, 0) } xOffset = 0 } } ) } } }
关键改动说明
- 层级底层新增固定黑色
Color视图,满足过渡阶段背景为黑色的需求 - 移除原控制显隐的布尔变量,改用
currentIndex标记当前显示视图,两个视图常驻层级,拖动过程中通过offset实时控制位置,实现跟随拖动的进出效果 - 透明度参数和拖动偏移量关联,实现两个视图的渐入渐出过渡
- 新增
clipped()修饰符裁剪容器外内容,避免未显示的视图出现在屏幕其他区域 - 调整结束拖动的判断逻辑,用容器宽度比例作为切换阈值,适配不同屏幕尺寸
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

