AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / user-917521

Deepak Sharma's questions

Martin Hope
Deepak Sharma
Asked: 2025-04-05 23:42:57 +0800 CST

SwiftUI ScrollView scrollTargetLayout 不起作用

  • 5

我在 SwiftUI 中实现了以下清理器。+按钮应该ScrollView向上移动 1 个刻度(或scrollPosition增加 1),但问题是,直到我单击 8-9 次后才会发生滚动。这是 iOS 中的错误还是编程错误?


struct BrokenVerticalScrubberDemo: View {
    @State private var scrollPosition: Int? = 0
    @State private var count: Int = 20

    var body: some View {
        VStack {
            Text("Scroll Position: \(scrollPosition ?? 0)")
                .font(.headline)

            ScrollView(.vertical, showsIndicators: true) {
                VStack(spacing: 8) {
                    ForEach(0..<count, id: \.self) { index in
                        Text("Tick \(index)")
                            .frame(height: 30)
                            .id(index)
                    }
                }
                .scrollTargetLayout()
                .padding(.vertical, 50)
            }
            .scrollTargetBehavior(.viewAligned)
            .scrollPosition(id: $scrollPosition)
            .frame(height: 300)
            .border(Color.gray)

            Button("+1") {
                withAnimation {
                    scrollPosition = min((scrollPosition ?? 0) + 1, count - 1)
                }
            }
            .padding(.top)
        }
        .padding()
    }
}

#Preview {
    BrokenVerticalScrubberDemo()
}

相反,如果我使用ScrollViewReader解决方法,它会在点击 2 次“+”按钮后开始滚动。

import SwiftUI

struct SomeWhatWorkingVerticalScrubberDemo: View {
    @State private var scrollPosition: Int = 0
    @State private var count: Int = 20

    var body: some View {
        VStack {
            Text("Scroll Position: \(scrollPosition)")
                .font(.headline)

            ScrollView(.vertical, showsIndicators: true) {
                ScrollViewReader { scrollViewProxy in
                    VStack(spacing: 8) {
                        ForEach(0..<count, id: \.self) { index in
                            Text("Tick \(index)")
                                .frame(height: 30)
                                .id(index)
                        }
                    }
                    .padding(.vertical, 50)
                    .onChange(of: scrollPosition) { newPosition in
                        withAnimation {
                            scrollViewProxy.scrollTo(newPosition, anchor: .center)
                        }
                    }
                }
            }
            .frame(height: 300)
            .border(Color.gray)

            Button("+1") {
                scrollPosition = min(scrollPosition + 1, count - 1)
            }
            .padding(.top)
        }
        .padding()
    }
}

#Preview {
    SomeWhatWorkingVerticalScrubberDemo()
}

  • 2 个回答
  • 50 Views
Martin Hope
Deepak Sharma
Asked: 2025-03-28 21:44:13 +0800 CST

SwiftUI 离散洗涤器实现

  • 5

我正在尝试在 SwiftUI 中实现带有文本标记的离散洗涤器,如下所示。我的问题是我无法确定先验HStack内部的高度ScrollView,因此我尝试使用onGeometryChange修饰符,但它不起作用(即覆盖文本被截断)。一种解决方法是使用并根据几何代理GeometryReader分配高度,但我想知道是否有另一种不使用的方法。HStackGeometryReader

struct ScrollScrubber: View {
    var config:ScrubberConfig
    
    @State var viewSize:CGSize?
    
    var body: some View {
        let horizontalPadding = (viewSize?.width ?? 0)/2
        
        ScrollView(.horizontal) {
            HStack(spacing:config.spacing) {
                let totalSteps = config.steps * config.count
                
                ForEach(0...totalSteps, id: \.self) { index in
                    let remainder = index % config.steps
                    Divider()
                        .background( remainder == 0 ? Color.primary : Color.gray)
                        .frame(width: 0, height: remainder == 0 ? 20 : 10, alignment: .center)
                        .frame(maxHeight: 20, alignment: .bottom)
                        .overlay(alignment: .bottom) {
                            if remainder == 0 {
                                Text("\(index / config.steps)")
                                    .font(.caption)
                                    .fontWeight(.semibold)
                                    .textScale(.secondary)
                                    .fixedSize()
                                    .offset(y:20)
                            }
                        }
                    
                }
            }
            .frame(height:viewSize?.height)
            
        }
        .scrollIndicators(.hidden)
        .safeAreaPadding(.horizontal, horizontalPadding)
        .onGeometryChange(for: CGSize.self) { proxy in
            proxy.size
        } action: { newValue in
            viewSize = newValue
            print("View Size \(newValue)")
        }


    }
}

struct ScrubberConfig:Equatable {
    var count:Int
    var steps:Int
    var spacing:CGFloat
}

#Preview {
    ScrollScrubber(config: .init(count: 100, steps: 5, spacing: 5.0))
        .frame(height:60)
}


swiftui
  • 1 个回答
  • 32 Views
Martin Hope
Deepak Sharma
Asked: 2025-03-28 19:20:58 +0800 CST

带框架的 SwiftUI onGeometryChange 修饰符

  • 5

下面的代码有什么问题,尽管修饰符设置为高度 60,但viewSize高度仍然为零?frame


struct TestGeometryModifierView: View {
    @State var viewSize:CGSize = .zero
    
    var body: some View {
        Color.red
            .onGeometryChange(for: CGSize.self) { proxy in
                proxy.size
            } action: { newValue in
                viewSize = newValue
                print("View Size \(newValue)")
            }
            .frame(height:viewSize.height)
    }
    
}

#Preview {
    TestGeometryModifierView()
        .frame(height:60)
}

控制台上的打印语句仅显示一行。我预计当在视图上设置框架高度时它会改变。

View Size (402.0, 0.0)
swiftui
  • 1 个回答
  • 37 Views
Martin Hope
Deepak Sharma
Asked: 2025-03-09 05:01:55 +0800 CST

SwiftUI 视图相对于安全区域的偏移

  • 5

我想知道这段 SwiftUI 代码到底是怎么回事。我想在横向模式下将蓝色视图与安全区域的前缘对齐。下面的代码可以工作,但如果我在blueOffset下面的计算中删除 -0.5 点调整,它根本不起作用。它Blue View只是在前缘填充了整个安全区域。我想知道-0.5有什么魔法?

  @ViewBuilder
    var secondBody:some View {
        Color.green.opacity(0.3)
            .ignoresSafeArea()
            .onGeometryChange(for: CGRect.self) { proxy in
                proxy.frame(in: .global)
            } action: { newValue in
                viewSize = newValue.size
            }
            .background {
                Color.blue
                    .ignoresSafeArea()
                    .aspectRatio(verticalSizeClass == .regular ? 9.0/16.0 : 16.0/9.0, contentMode: .fit)
                    .onGeometryChange(for: CGRect.self) { proxy in
                        proxy.frame(in: .global)
                    } action: { newValue in
                        blueViewSize = newValue.size
//This line, why it works????
                        blueOffset = 
verticalSizeClass == .regular ? 0 :
 (viewSize.width - blueViewSize.width)/2 - 0.5
                        print("Blue offset \(blueOffset)")
                    }
                    .offset(x: -blueOffset)
            }
            .persistentSystemOverlays(.hidden)
    }
  • 1 个回答
  • 37 Views
Martin Hope
Deepak Sharma
Asked: 2025-02-27 02:21:34 +0800 CST

SwiftUI 视图在自动旋转时重新初始化[重复]

  • 5
这个问题已经有答案了:
SwiftUI (Mac) @Observable 内存泄漏,与数组相关,触发 App 生命周期 (1 个答案)
昨天休息。

我有以下 SwiftUI 代码:

struct TestContentView: View {
    @Environment(\.verticalSizeClass) var verticalSizeClass
    @Environment(\.horizontalSizeClass) var horizontalSizeClass
    
    var body: some View {
        TestView()
            .ignoresSafeArea()
    }
}

struct TestView: View { 
    @State var model:TestModel = TestModel()
    
    var body: some View {
        Text("Count \(model.counter)")
    }
}

@Observable
class TestModel {
    var counter:Int = 0
    
    deinit {
        print("Calling deinit on TestModel")
    }
}

我的问题是,TestView尽管和是变量TestModel,但它们在设备自动旋转时会被重新初始化。这不是我想要的,我明白问题是我声明了大小类环境变量,这导致它们被重置为新值。解决问题的一种方法是将移动到超级视图并初始化它,但我不确定如果您有更深的视图层次结构,这是否总是一种可扩展的方法。解决这个问题的正确方法是什么,特别是如果可以有或深入视图层次结构?TestModel@StateTestViewtestModelhorizontalSizeClassverticalSizeClass

  • 1 个回答
  • 71 Views
Martin Hope
Deepak Sharma
Asked: 2025-02-26 20:44:11 +0800 CST

SwiftUI 无限循环问题与 @Environment 大小变量

  • 6

horizontalSizeClass我看到 SwiftUI body 在存在环境变量(如或)的情况下被无限循环地重复调用verticalSizeClass。这种情况发生在设备从纵向旋转到横向然后返回纵向模式之后。deinit的方法TestPlayerVM被重复调用。下面粘贴了可重现性最低的示例代码。

如果我删除大小类环境引用,或者如果我跳过初始化程序addPlayerObservers中的调用,就不会出现无限循环TestPlayerVM。

import AVKit
import Combine

struct InfiniteLoopView: View {
       @Environment(\.verticalSizeClass) var verticalSizeClass
       @Environment(\.horizontalSizeClass) var horizontalSizeClass
    
       @State private var openPlayer = false
       @State var playerURL: URL = URL(fileURLWithPath: Bundle.main.path(forResource: "Test_Video", ofType: ".mov")!)
    
        var body: some View {
           PlayerView(playerURL: playerURL)
              .ignoresSafeArea()
        }
     }

struct PlayerView: View {
    @Environment(\.dismiss) var dismiss
    
    var playerURL:URL
    @State var playerVM = TestPlayerVM()
    
    var body: some View {
        VideoPlayer(player: playerVM.player)
            .ignoresSafeArea()
            .background {
                Color.black
            }
            .task {
                let playerItem = AVPlayerItem(url: playerURL)
                playerVM.playerItem = playerItem
            }
    }
  }

@Observable
class TestPlayerVM {
     private(set) public var player: AVPlayer = AVPlayer()

     var playerItem:AVPlayerItem? {
        didSet {
            player.replaceCurrentItem(with: playerItem)
        }
    }
    
    private var cancellable = Set<AnyCancellable>()
    
    init() {
        addPlayerObservers()
    }
    
    deinit {
        print("Deinit Video player manager")
        removeAllObservers()
    }
    
    private func removeAllObservers() {
        cancellable.removeAll()
    }
    
  
    private func addPlayerObservers() {
        
        player.publisher(for: \.timeControlStatus, options: [.initial, .new])
            .receive(on: DispatchQueue.main)
            .sink { timeControlStatus in
                print("Player time control status \(timeControlStatus)")
            }
            .store(in: &cancellable)
        
    }
}

  • 1 个回答
  • 53 Views
Martin Hope
Deepak Sharma
Asked: 2025-01-12 17:07:50 +0800 CST

可观察模型对象中的局部参与者与全局参与者

  • 5

我有以下 SwiftUI Observable 模型类以及本地和全局参与者变量,但无法构建并出现错误Global actor 'MyGlobalActor'-isolated default value in a nonisolated context。我的问题是全局参与者构建失败但本地参与者构建成功有什么特别之处?本地参与者中的 init 方法是否在默认上下文中运行,而全局参与者在隔离上下文中运行?

import SwiftUI
    
@Observable
final class Model {
    let testActor = TestLocalActor() //This builds 
    let testGlobalActor = TestGlobalActor() //Build fails here
}

actor TestLocalActor {
    init() {
        
    }
}

@MyGlobalActor
final class TestGlobalActor {
    init() {
        
    }
}

@globalActor
actor MyGlobalActor: GlobalActor {
   static let shared = MyGlobalActor()
}
swift
  • 1 个回答
  • 47 Views
Martin Hope
Deepak Sharma
Asked: 2025-01-07 18:49:33 +0800 CST

在监视任务中 Actor 的已发布值时,Swift 6 生成错误

  • 4

以下代码在 Xcode 中 Swift 6 语言版本下构建时出错。这是架构问题还是有简单的解决方法?类型Bool是,Sendable但它的发布者不是。

Non-sendable type 'Published<Bool>.Publisher' in implicitly asynchronous access to actor-isolated property '$isRecording' cannot cross actor boundary

import Foundation

final class Recorder {
    
    var writer = Writer()
    var isRecording = false
    
    func startRecording() {
        Task { [writer] in
            await writer.startRecording()
            print("started recording")
        }
    }
    
    func stopRecording() {
        Task { [writer] in
            await writer.stopRecording()
            print("stopped recording")
        }
    }
    
    func observeValues() {
        
        Task {
            for await value in await writer.$isRecording.values {
                isRecording = value
            }
        }
    }
}

actor Writer {
    @Published private(set) public var isRecording = false
    
    func startRecording() {
        isRecording = true
    }
    
    func stopRecording() {
        isRecording = false
    }
}

请参阅此屏幕截图以查看我看到的 AVCam 示例代码中的实际错误(唯一的修改是输入@preconcurrency)import AVFoundation。

请参阅此屏幕截图以了解我看到的 AVCam 示例代码中的实际错误(未经修改)

  • 1 个回答
  • 34 Views
Martin Hope
Deepak Sharma
Asked: 2025-01-07 16:41:21 +0800 CST

Swift 中 Sendable 协议有什么用

  • 5

将类或函数标记为Sendable可确保它可以安全地跨越并发边界,值类型是安全的,因为它们实现了写时复制等,我们都可以在 Swift 语言文档中找到。但我的观点是,这Sendable并不保证变量没有数据竞争。即使在基本值类型中,我们也可能存在数据竞争,如Int下面的代码所示。因此,Sendable并不等同于数据可以安全地避免并发访问/修改,它只意味着值可以安全地跨不同线程复制。但我的问题是它解决了什么问题,或者作为构造的重要性是什么Sendable?有人可以解释一下吗?

var num = 0

DispatchQueue.global(qos: .background).async {
    for _ in 0..<100 {
        num += 1 
    }
}

DispatchQueue.global(qos: .background).async {
    for _ in 0..<100 {
        num -= 1 
    }
}
  • 2 个回答
  • 59 Views
Martin Hope
Deepak Sharma
Asked: 2025-01-07 03:08:22 +0800 CST

Swift 6 传递发送闭包的并发错误

  • 5

在 XCode 中将 Swift 6 设置为语言版本后,我在代码中的几个地方使用 Task 关闭时收到此错误。

Passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure

以下是最低限度可重现的示例代码。

import Foundation

final class Recorder {
    
    var writer = Writer()
    
    func startRecording() {
        Task {
            await writer.startRecording()
            print("started recording")
        }
    }
    
    func stopRecording() {
        Task {
            await writer.stopRecording()
            print("stopped recording")
        }
    }
}

actor Writer {
    var isRecording = false
    
    func startRecording() {
        isRecording = true
    }
    
    func stopRecording() {
        isRecording = false
    }
}
  • 1 个回答
  • 65 Views
Martin Hope
Deepak Sharma
Asked: 2024-12-31 18:37:45 +0800 CST

Swift Actor 和 GCD Dispatch Queue Executor

  • 5

这是参考Apple的AVCam示例代码:

   actor CaptureService {

          // The app's capture session.
         private let captureSession = AVCaptureSession()

        // A serial dispatch queue to use for capture control actions.
         private let sessionQueue = DispatchSerialQueue(label: "com.example.apple-samplecode.AVCam.sessionQueue")

       // Sets the session queue as the actor's executor.
        nonisolated var unownedExecutor: UnownedSerialExecutor {
            sessionQueue.asUnownedSerialExecutor()
        }
     ...
  }

然后在 Actor 代码中:

    // Set the controls delegate.
    captureSession.setControlsDelegate(controlsDelegate, queue: sessionQueue)

如果我理解正确的话,此代码的效果是通过sessionQueue隐式调用使所有隔离方法调用和可变状态修改有效地发生在sessionQueue.sync()。我的理解正确吗?还是还有更多内容?

  • 1 个回答
  • 75 Views
Martin Hope
Deepak Sharma
Asked: 2024-12-23 05:05:07 +0800 CST

在 SwiftUI 中使用 AsyncStream 与 @Observable 宏

  • 3

AsyncStream我想了解iOS 17 引入宏的实用性@Observable,我们可以在其中直接观察模型中任何变量值的变化(并且观察跟踪甚至可以在 SwiftUI 视图之外进行)。因此,如果我AsyncStream在 SwiftUI 视图中使用连续的值流(例如文件的下载进度),则可以在同一个 SwiftUI 视图中使用onChange(of:initial)下载进度(存储为模型对象中的属性)观察到相同的值流。我正在寻找这两种方法的优点、缺点和局限性。

具体来说,我的问题与 Apple 的AVCam 示例代码有关,他们观察到以下几个状态。这是在CameraModel附加到 SwiftUI 视图的类中完成的。

    // MARK: - Internal state observations

// Set up camera's state observations.
private func observeState() {
    Task {
        // Await new thumbnails that the media library generates when saving a file.
        for await thumbnail in mediaLibrary.thumbnails.compactMap({ $0 }) {
            self.thumbnail = thumbnail
        }
    }
    
    Task {
        // Await new capture activity values from the capture service.
        for await activity in await captureService.$captureActivity.values {
            if activity.willCapture {
                // Flash the screen to indicate capture is starting.
                flashScreen()
            } else {
                // Forward the activity to the UI.
                captureActivity = activity
            }
        }
    }
    
    Task {
        // Await updates to the capabilities that the capture service advertises.
        for await capabilities in await captureService.$captureCapabilities.values {
            isHDRVideoSupported = capabilities.isHDRSupported
            cameraState.isVideoHDRSupported = capabilities.isHDRSupported
        }
    }
    
    Task {
        // Await updates to a person's interaction with the Camera Control HUD.
        for await isShowingFullscreenControls in await captureService.$isShowingFullscreenControls.values {
            withAnimation {
                // Prefer showing a minimized UI when capture controls enter a fullscreen appearance.
                prefersMinimizedUI = isShowingFullscreenControls
            }
        }
    }
}

如果我们看到结构,它是一个具有两个 Bool 成员的小结构。这些变化可以通过 SwiftUI 视图直接观察到。我想知道在这里使用并在 for 循环中不断迭代变化CaptureCapabilities是否有特定的优势或理由。AsyncStream

   /// A structure that represents the capture capabilities of `CaptureService` in
  /// its current configuration.
struct CaptureCapabilities {

let isLivePhotoCaptureSupported: Bool
let isHDRSupported: Bool

init(isLivePhotoCaptureSupported: Bool = false,
     isHDRSupported: Bool = false) {
    self.isLivePhotoCaptureSupported = isLivePhotoCaptureSupported
    self.isHDRSupported = isHDRSupported
}

  static let unknown = CaptureCapabilities()
}
  • 1 个回答
  • 115 Views
Martin Hope
Deepak Sharma
Asked: 2024-12-12 01:27:32 +0800 CST

SwiftUI“遮盖”视图的左侧和右侧部分

  • 5

我有一个圆角矩形,我想遮盖它的左右部分(其宽度可以自定义为State变量)。我希望圆角矩形在应用左右遮盖时保留其圆角矩形形状。我说遮盖是为了解释,但.mask如果在整个视图上对手势识别器的命中测试中产生问题,实际实现可能不会使用修饰符。

这是屏蔽圆角矩形左侧和右侧部分的代码。

struct MaskTesting: View {

  @State var rectWidth:CGFloat = 300
  @State var leftMaskWidth:CGFloat = 100
  @State var rightMaskWidth:CGFloat = 100

  var body: some View {
    
    Rectangle()
        .fill(Color.orange)
        .frame(maxHeight:70)
        .frame(width: rectWidth)
        .clipShape(RoundedRectangle(cornerRadius: 5))
        .overlay(alignment: .leading) {
            Rectangle()
                .fill(Color.purple)
                .frame(maxHeight:70)
                .frame(width: leftMaskWidth)
        }
        .overlay(alignment: .leading) {
            Rectangle()
                .fill(Color.purple)
                .frame(maxHeight:70)
                .frame(width: rightMaskWidth)
                .offset(x:rectWidth - 100)
        }
    
}

输出是这样的。但我希望输出中的主橙色视图是圆角矩形而不是普通矩形。如何在 SwiftUI 中实现它?

在此处输入图片描述

  • 1 个回答
  • 48 Views
Martin Hope
Deepak Sharma
Asked: 2024-12-02 04:09:07 +0800 CST

检测 SwiftUI 拖动开始事件

  • 5

我想检测拖动手势的起始位置。我有一个只有 20 点宽的子视图。我向超级视图添加了一个拖动手势,并且仅当手势开始时的拖动手势起始位置在该子视图位置的 20 点以内时,我才想在这个子视图周围移动。我不想向这个子视图添加拖动手势,因为它已经在代码中引起了其他问题(在其他 SO 问题中报告,并且没有干净的解决方案)。所以我尝试将手势添加到超级视图。

我尝试了以下代码,但它不起作用,因为它无法检测手势开始的时间和地点。

  DragGesture(minimumDistance: 0)
                    .updating($scrubberSeeking, body: { value, state, _ in
                        
                        if abs(value.startLocation.x - scrubberOffset) > 20.0  {
                            state = false
                            return
                        }
                        
                        state = true
                    })
                    .onChanged({ value in
                        
                            if scrubberSeeking {
                                ...
                                ...
                            }
                       

                    })
                    .onEnded { value in
                        
                    }
  • 1 个回答
  • 63 Views
Martin Hope
Deepak Sharma
Asked: 2024-11-26 19:09:06 +0800 CST

使用新框架修饰符时的 SwiftUI 视图居中行为

  • 5

我有以下 SwiftUI 代码:

    Rectangle()
        .fill(Color.blue.opacity(0.5))
        .frame(width: 130)
        .frame(maxWidth: .infinity)
        .background(Color.orange.opacity(0.5))
        .padding()
        .frame(maxHeight:100)

这是输出。

在此处输入图片描述

可以清楚地看到,蓝色的内矩形已放置在外矩形的中心。我尝试对框架的对齐方式进行实验,发现只能通过改变外矩形的框架对齐方式来更改内矩形的对齐方式,如下所示:

  .frame(maxWidth: .infinity, alignment: .trailing)

但是如果我改变内部矩形的框架对齐属性,则什么都不会改变。

我想更清楚地理解这种行为——视图是否默认居中,以及为什么内部框架对齐修改没有任何改变。

  • 2 个回答
  • 35 Views
Martin Hope
Deepak Sharma
Asked: 2024-09-29 04:40:11 +0800 CST

在 HStack 中对齐图像

  • 5

我在 SwiftUI 中有以下代码:

  HStack(spacing: 0) {
        ForEach(images) { thumbImage in
            Image(uiImage: thumbImage.image)
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(width: 50, height: 50)
                .clipped()
        }
    }
    .frame(width: 330, alignment: .center)
    .clipped()

我看到以下输出:

在此处输入图片描述

实际上,它会剪切左右两侧的内容HStack。我想要的是只在右侧(尾部)进行剪切,而不是左侧。实现它的正确方法是什么?

  • 1 个回答
  • 35 Views
Martin Hope
Deepak Sharma
Asked: 2024-09-21 04:12:44 +0800 CST

SwiftUI 在视图被拖动时保持背景静止

  • 4

我已经使用 SwiftUI 实现了一个示例视频编辑时间线,但遇到了一些问题。因此,我将问题分解成几个部分,并将每个问题作为单独的问题发布。在下面的代码中,我有一个简单的时间线,它HStack由左间隔、右间隔(表示为简单的黑色)和中间的修剪器 UI 组成。当拖动左右手柄时,修剪器会调整大小。当拖动修剪器手柄时,左右间隔的宽度也会调整。

问题:我希望修剪器中的背景缩略图(当前实现为填充不同颜色的简单矩形)在修剪器调整大小时保持静止。当前,它们会随着修剪器调整大小而移动,如下面的 gif 所示。我该如何修复它?

在此处输入图片描述

import SwiftUI

struct SampleTimeline: View {
    
    let viewWidth:CGFloat = 340 //Width of HStack container for Timeline
   
    @State var frameWidth:CGFloat = 280 //Width of trimmer
    
    var minWidth: CGFloat {
        2*chevronWidth + 10
    } //min Width of trimmer
    
    @State private var leftViewWidth:CGFloat = 20
    @State private var rightViewWidth:CGFloat = 20
    
    var chevronWidth:CGFloat {
        return 24
    }
    
    var body: some View {
        
        HStack(spacing:0) {
            Color.black
                .frame(width: leftViewWidth)
                .frame(height: 70)
            
            HStack(spacing: 0) {
            
                Image(systemName: "chevron.compact.left")
                    .frame(width: chevronWidth, height: 70)
                    .background(Color.blue)
                    .gesture(
                        DragGesture(minimumDistance: 0)
                            .onChanged({ value in
                                leftViewWidth = max(leftViewWidth + value.translation.width, 0)
                                
                                if leftViewWidth > viewWidth - minWidth - rightViewWidth {
                                    leftViewWidth = viewWidth - minWidth - rightViewWidth
                                }
                                   
                                frameWidth = max(viewWidth - leftViewWidth - rightViewWidth, minWidth)
                                
                            })
                            .onEnded { value in
                               
                            }
                    )
        
                Spacer()
                
                Image(systemName: "chevron.compact.right")
                    .frame(width: chevronWidth, height: 70)
                    .background(Color.blue)
                    .gesture(
                        DragGesture(minimumDistance: 0)
                            .onChanged({ value in
                                rightViewWidth = max(rightViewWidth - value.translation.width, 0)
                                
                                if rightViewWidth > viewWidth - minWidth - leftViewWidth {
                                    rightViewWidth = viewWidth - minWidth - leftViewWidth
                                }
                                
                                frameWidth = max(viewWidth - leftViewWidth - rightViewWidth, minWidth)
                            })
                            .onEnded { value in
                              
                            }
                    )
                 
            }
            .foregroundColor(.black)
            .font(.title3.weight(.semibold))
          
            .background {
                
                HStack(spacing:0) {
                    Rectangle().fill(Color.red)
                        .frame(width: 70, height: 60)
                    Rectangle().fill(Color.cyan)
                        .frame(width: 70, height: 60)
                    Rectangle().fill(Color.orange)
                        .frame(width: 70, height: 60)
                    Rectangle().fill(Color.brown)
                        .frame(width: 70, height: 60)
                    Rectangle().fill(Color.purple)
                        .frame(width: 70, height: 60)
                }
                
            }
            .frame(width: frameWidth)
            .clipped()
            
            Color.black
                .frame(width: rightViewWidth)
                .frame(height: 70)
        }
        .frame(width: viewWidth, alignment: .leading)
    }
}

#Preview {
    SampleTimeline()
}

更新:我已设法按如下方式解决问题,但我仍然觉得这只是一种变通方法(因为我已为缩略图视图设置了偏移)。如果您认为有任何更好更准确的解决方案,请发布(例如,使用同时减小修剪器框架宽度的遮罩)。


import SwiftUI

struct SampleTimeline: View {
    
    let viewWidth:CGFloat = 340 //Width of HStack container for Timeline
   
    @State var frameWidth:CGFloat = 280 //Width of trimmer
    
    var minWidth: CGFloat {
        2*chevronWidth + 10
    } //min Width of trimmer
    
    @State private var leftViewWidth:CGFloat = 20
    @State private var rightViewWidth:CGFloat = 20
    @GestureState private var leftEndPanned = false
    @GestureState private var rightEndPanned = false
    
    var chevronWidth:CGFloat {
        return 24
    }
    
    var body: some View {
        
        HStack(spacing:0) {
            Color.clear
                .frame(width: leftViewWidth)
                .frame(height: 70)
            
            HStack(spacing: 0) {
            
                Image(systemName: "chevron.compact.left")
                    .frame(width: chevronWidth, height: 70)
                    .background(Color.blue)
                    .gesture(
                        DragGesture(minimumDistance: 0)
                            .updating($leftEndPanned, body: { _, state, _ in
                                state = true
                            })
                            .onChanged({ value in
                                leftViewWidth = max(leftViewWidth + value.translation.width, 0)
                                
                                if leftViewWidth > viewWidth - minWidth - rightViewWidth {
                                    leftViewWidth = viewWidth - minWidth - rightViewWidth
                                }
                                   
                                frameWidth = max(viewWidth - leftViewWidth - rightViewWidth, minWidth)
                                
                            })
                            .onEnded { value in
                               
                            }
                    )
        
                Spacer()
                
                Image(systemName: "chevron.compact.right")
                    .frame(width: chevronWidth, height: 70)
                    .background(Color.blue)
                    .gesture(
                        DragGesture(minimumDistance: 0)
                            .updating($rightEndPanned, body: { _, state, _ in
                                state = true
                            })
                            .onChanged({ value in
                                rightViewWidth = max(rightViewWidth - value.translation.width, 0)
                                
                                if rightViewWidth > viewWidth - minWidth - leftViewWidth {
                                    rightViewWidth = viewWidth - minWidth - leftViewWidth
                                }
                                
                                frameWidth = max(viewWidth - leftViewWidth - rightViewWidth, minWidth)
                            })
                            .onEnded { value in
                              
                            }
                    )
                 
            }
            .foregroundColor(.black)
            .font(.title3.weight(.semibold))
            .background {
                
                HStack(spacing:0) {
                    Rectangle().fill(Color.red)
                        .frame(width: 70, height: 60)
                    Rectangle().fill(Color.cyan)
                        .frame(width: 70, height: 60)
                    Rectangle().fill(Color.orange)
                        .frame(width: 70, height: 60)
                    Rectangle().fill(Color.brown)
                        .frame(width: 70, height: 60)
                    Rectangle().fill(Color.purple)
                        .frame(width: 70, height: 60)
                }
                .frame(width: viewWidth - leftViewWidth - rightViewWidth, alignment: .leading)
                .offset(x: -leftViewWidth)
                .background(Color.yellow)
                .clipped()
                
            }
            
            
            Color.clear
                .frame(width: rightViewWidth)
                .frame(height: 70)
        }
        .frame(width: viewWidth, alignment: .leading)
    }
}

#Preview {
    SampleTimeline()
}

  • 1 个回答
  • 62 Views
Martin Hope
Deepak Sharma
Asked: 2024-09-16 03:36:57 +0800 CST

SwiftUI 拖动边缘时缩小视图

  • 5

我正在尝试在 SwiftUI 中实现视频修剪器 UI,如下所示:

 struct SimpleTrimmer: View {
    @State private var startPosition: CGFloat = 0
    @GestureState private var isDragging: Bool = false
    
    @State private var lastStartPosition: CGFloat = .zero
    @State private var frameWidth:CGFloat = 300
    
    var body: some View {
        HStack(spacing: 10) {
                Image(systemName: "chevron.compact.left")
                    .frame(height:70)
                    .frame(width:20)
                    .padding(.horizontal, 5)
                    .background(Color.blue)
                    .offset(x: startPosition)
                    .gesture(
                        DragGesture(minimumDistance: 0)
                            .updating($isDragging, body: { value, out, transaction in
                                out = true
                                
                            })
                            .onChanged { value in
                                let translation = value.translation.width
                                startPosition = translation + lastStartPosition
                            }.onEnded { _ in
                                lastStartPosition = startPosition
                                NSLog("Last start position \(lastStartPosition)")
                            }
                    )
            
                
                Spacer()
                
                Image(systemName: "chevron.compact.right")
                .frame(height:70)
                .frame(width:20)
                .padding(.horizontal, 5)
                .background(Color.blue)
            }
            .foregroundColor(.black)
            .font(.title3.weight(.semibold))
            .padding(.horizontal, 7)
            .padding(.vertical, 3)
            .background(.yellow)
            .clipShape(RoundedRectangle(cornerRadius: 7))
            .frame(width: frameWidth)
          //  .offset(x: startPosition)
            .onGeometryChange(for: CGFloat.self) { proxy in
                proxy.size.width
            } action: { width in
                print("width = \(width)")
            }
    }
}

在此处输入图片描述

这适用于拖动时移动修剪器的左手。我还需要SimpleTrimmer拖动末端时缩小视图。无论我做什么(例如调整主 HStack 的偏移量和宽度等),它都不起作用。

  • 1 个回答
  • 26 Views
Martin Hope
Deepak Sharma
Asked: 2024-09-14 18:27:36 +0800 CST

仅用背景颜色填充 SwiftUI 的一部分

  • 7

我正在尝试在 SwiftUI 中设计一个视频修剪器视图,如下所示。结果如下。我的问题是,我是否可以将中间部分(即除左右 20 个点和上下 5 个点之外的所有内容)透明,以便我可以在它们后面显示缩略图(也许通过自定义剪辑形状)?

在此处输入图片描述

  var body: some View {
    HStack(spacing: 10) {
        Image(systemName: "chevron.compact.left")
            .frame(height:70)
        
        Spacer()
        
        Image(systemName: "chevron.compact.right")
    }
    .foregroundColor(.black)
    .font(.title3.weight(.semibold))
    .padding(.horizontal, 7)
    .padding(.vertical, 3)
    .background(.yellow)
    .clipShape(RoundedRectangle(cornerRadius: 7))
    .frame(width: 300)
    .onGeometryChange(for: CGFloat.self) { proxy in
        proxy.size.width
    } action: { width in
        print("width = \(width)")
    }

}
  • 2 个回答
  • 82 Views
Martin Hope
Deepak Sharma
Asked: 2024-01-22 21:37:29 +0800 CST

SwiftUI 视频播放器自动旋转问题

  • 5

我将 SwiftUI 嵌入VideoPlayer到 a 中VStack,看到当设备旋转时屏幕变黑(即即使视频播放器自动旋转,内容也会消失)。即使我使用AVPlayerViewController(as UIViewControllerRepresentable),也会出现此问题。这是一个错误还是我做错了什么?

var videoURL:URL
let player = AVPlayer()

var body: some View {
    VStack {
        VideoPlayer(player: player)
                        .frame(maxWidth:.infinity)
                        .frame(height:300)
                        .padding()
                        .ignoresSafeArea()
                        .background {
                            Color.black
                        }
                        .onTapGesture {
                            player.rate = player.rate == 0.0 ? 1.0 : 0.0
                        } 
       
        Spacer()
    }
    .ignoresSafeArea()
    .background(content: {
        Color.black
    })
    .onAppear {
        let audioSession = AVAudioSession.sharedInstance()
        do {
            try audioSession.setCategory(AVAudioSession.Category.playback, mode: AVAudioSession.Mode.default, options: AVAudioSession.CategoryOptions.duckOthers)
        } catch {
            NSLog("Unable to set session category to playback")
        }
        
        let playerItem = AVPlayerItem(url: videoURL)
        player.replaceCurrentItem(with: playerItem)
    }

 }
  • 1 个回答
  • 22 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve