Swift 時間期間スライダー

TimePeriodSlider

TimePeriodSliderを部品か出来るように切り出せるとベスト。

import Foundation
import SwiftUI

struct ClockEditView: View {
    var index: Int
    
    @EnvironmentObject var clocksData: ClocksData
    @Environment(\.presentationMode) var presentationMode
    @State var startProgress: CGFloat = 0.0
    @State var startBarWith: CGFloat = 0.7
    @State var endProgress: CGFloat = 0.7
    @State var showeEndBar: Bool = false
    
    var body: some View {
        VStack {
            :
            :
            HStack {
                TimePeriodSlider()
            }
            :
            :
        }
        .onAppear() {
            :
    }
    
    @ViewBuilder
    func TimePeriodSlider() -> some View {
        GeometryReader { geometry in
            let progressBarWith = geometry.size.width - 32.0
            ZStack(alignment: .leading) {
                Rectangle()
                    .strokeBorder(.yellow.opacity(1.00), style: StrokeStyle(lineWidth: 40, lineCap: .round, lineJoin: .round))
                Rectangle()
                    .offset(x: progressBarWith * self.startProgress)
                    .strokeBorder(.blue, style: StrokeStyle(lineWidth: 40, lineCap: .round, lineJoin: .round))
                    .frame(width: progressBarWith * self.startBarWith - (progressBarWith * self.startProgress) + 32.0)
                if self.showeEndBar == true {
                    Rectangle()
                        .offset(x: geometry.size.width * 0.0)
                        .strokeBorder(.blue, style: StrokeStyle(lineWidth: 40, lineCap: .round, lineJoin: .round))
                        .frame(width: progressBarWith * self.endProgress + 32.0)
                }
                Image(systemName: "s.circle")
                    .font(.callout)
                    .foregroundColor(.blue)
                    .frame(width: 32, height: 32)
                    .background(.white, in: Circle())
                    .offset(x: progressBarWith * self.startProgress)
                    .gesture(
                        DragGesture()
                            .onChanged({ value in
                                self.onDrag(value: value, with: progressBarWith)
                            })
                    )
                Image(systemName: "e.circle")
                    .font(.callout)
                    .foregroundColor(.blue)
                    .frame(width: 32, height: 32)
                    .background(.white, in: Circle())
                    .offset(x: (geometry.size.width - 32.0) * self.endProgress)
                    .gesture(
                        DragGesture()
                            .onChanged({ value in
                                self.onDrag(value: value, with: progressBarWith, isStart: false)
                            })
                    )
            }
        }
        .frame(width: self.screenBounds().width / 1.1,
               height: 40)
    }
    
    func onDrag(value: DragGesture.Value, with: CGFloat, isStart: Bool = true) {
        print(value)
        print(self.screenBounds().width)
        print(with)
        print(self.screenBounds().width - with)
        var progress = (value.location.x) / with
        var dispprogress = (value.location.x) / (with)
        if progress < 0.0 {
            progress = 0.0
            dispprogress = 0.0
        }
        else if progress > 1.0 {
            progress = 1.0
            dispprogress = (with - 32.0) / (with)
        }
        self.setProgress(with: with, progress: progress, dispprogress: dispprogress, isStart: isStart)

        print("\(progress):\(dispprogress)")
    }
    
    func setProgress(with: CGFloat, progress: CGFloat, dispprogress: CGFloat, isStart: Bool = true) {
        if isStart == true {
            self.startProgress = progress
            if startProgress > endProgress {
                self.startBarWith = 1.0
                self.showeEndBar = true
            }
            else {
                self.startBarWith = self.endProgress
                self.showeEndBar = false
            }
        }
        else {
            self.endProgress = progress
            if endProgress < startProgress {
                self.startBarWith = 1.0
                self.showeEndBar = true
            }
            else {
                self.startBarWith = progress
                self.showeEndBar = false
            }
        }
    }
    
}

SwiftSwift,SwiftUI

Posted by shi-n