본문 바로가기

iOS

SwiftUI CustomSlidebar

728x90
반응형
SMALL

리팩토링 해야하지만 하기 싫습니다.

최근 Bluetooth 관련해서 공부하면서 너무 바쁜 와중에
뷰짜는 일을 취미로 하고 있습니다.

 

아 저도 뷰를 그리고 싶어요 🥲

뷰 그리는 일이 재밌습니다 :)

 

갈 길이 아주 아주 머네요! 다들 행복하세요!

//
//  ContentView.swift
//  CustomSlideBar
//
//  Created by Byeon jinha on 2023/06/23.
//

import SwiftUI

struct ContentView: View {
    @State var lowerValue: Double = -0.5
    @State var upperValue: Double = 0.5
    let minValue: Double = 0
    let maxValue: Double = 1
    
    var body: some View {
        VStack {
            CustomSlider(minValue: minValue, maxValue: maxValue, lowerValue: $lowerValue, upperValue: $upperValue)
                .frame(height: 50)
                .padding(.horizontal)
        }
    }
}


struct CustomSlider: View {
    var minValue: Double
    var maxValue: Double
    @Binding var lowerValue: Double
    @Binding var upperValue: Double
    let chargingSection: [Double] =  [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1]
    
    var body: some View {
        let width = UIScreen.main.bounds.width * 0.8
        
        ZStack {
            Rectangle()
                .frame(width: width, height: 8)
                .overlay(
                    ZStack{
                        ForEach(chargingSection.indices) { idx in
                            if idx == 0 {
                                Text("시작")
                                    .offset(x: (chargingSection[idx] - 0.5) * width, y: 30 )
                            } else {
                                Text("\(Int(chargingSection[idx] * 1000))")
                                    .offset(x: (chargingSection[idx] - 0.5) * width, y: 30 )
                            }
                          }
                        VStack{
                            ZStack{
                                Rectangle()
                                    .frame(width: CGFloat((upperValue - lowerValue) / (maxValue - minValue)) * width, height: 8)
                                    .foregroundColor(.black)
                                    .offset(x: CGFloat((lowerValue - minValue) / (maxValue - minValue)) * width +  CGFloat((upperValue - lowerValue) / (maxValue - minValue)) * width / 2)
                                Circle()
                                    .foregroundColor(.red)
                                    .frame(width: 30, height: 30)
                                    .offset(x: CGFloat((lowerValue - minValue) / (maxValue - minValue)) * width)
                                    .gesture(DragGesture()
                                        .onChanged { gesture in
                                            let dragValue = Double(gesture.location.x / width) * (maxValue - minValue) + minValue
                                            lowerValue = min(max(dragValue, -0.5), upperValue)
                                        }
                                        .onEnded { gesture in
                                            var minValue: Double = 1
                                            var minValueIdx: Int = 8
                                            for (idx, section) in chargingSection.enumerated(){
                                                if minValue > abs((lowerValue + 0.5) - section) {
                                                    minValue =  abs((lowerValue + 0.5) - section)
                                                    minValueIdx = idx
                                                }
                                            }
                                            lowerValue = chargingSection[minValueIdx] - 0.5
                                        }
                                    )
                                
                                Circle()
                                    .foregroundColor(.blue)
                                    .frame(width: 30, height: 30)
                                    .offset(x: CGFloat((upperValue - minValue) / (maxValue - minValue)) * width)
                                    .gesture(DragGesture()
                                        .onChanged { gesture in
                                            let dragValue = Double(gesture.location.x / width) * (maxValue - minValue) + minValue
                                            upperValue = min(max(dragValue, lowerValue), 0.5)
                                        }
                                        .onEnded{ gesture in
                                            var minValue: Double = 1
                                            var minValueIdx: Int = 8
                                            for (idx, section) in chargingSection.enumerated(){
                                                if minValue > abs((upperValue + 0.5) - section) {
                                                    minValue =  abs((upperValue + 0.5) - section)
                                                    minValueIdx = idx
                                                }
                                            }
                                            upperValue = chargingSection[minValueIdx] - 0.5
                                        }
                                    )
                            }
                        }
                    }
                )
                .onTapGesture() { location in
                    let xPos = location.x / (width)
                    if abs((upperValue + 0.5) - (xPos)) > abs((lowerValue + 0.5) - (xPos)) {
                        lowerValue = min(max((xPos - 0.5) , -0.5), 0.5)
                        var minValue: Double = 1
                        var minValueIdx: Int = 8
                        for (idx, section) in chargingSection.enumerated(){
                            if minValue > abs((lowerValue + 0.5) - section) {
                                minValue =  abs((lowerValue + 0.5) - section)
                                minValueIdx = idx
                            }
                        }
                        lowerValue = chargingSection[minValueIdx] - 0.5
                    } else if abs((upperValue + 0.5) - (xPos)) < abs((lowerValue + 0.5) - (xPos)) {
                        upperValue = max(min((xPos - 0.5) , 0.5), -0.5)
                        var minValue: Double = 1
                        var minValueIdx: Int = 8
                        for (idx, section) in chargingSection.enumerated(){
                            if minValue > abs((upperValue + 0.5) - section) {
                                minValue =  abs((upperValue + 0.5) - section)
                                minValueIdx = idx
                            }
                        }
                        upperValue = chargingSection[minValueIdx] - 0.5
                    } else if abs((upperValue + 0.5) - (xPos)) == abs((lowerValue + 0.5) - (xPos)) {
                        if upperValue <= (xPos) - 0.5 {
                            upperValue = max(min((xPos - 0.5) , 0.5), -0.5)
                            var minValue: Double = 1
                            var minValueIdx: Int = 8
                            for (idx, section) in chargingSection.enumerated(){
                                if minValue > abs((upperValue + 0.5) - section) {
                                    minValue =  abs((upperValue + 0.5) - section)
                                    minValueIdx = idx
                                }
                            }
                            upperValue = chargingSection[minValueIdx] - 0.5
                        } else {
                            lowerValue = min(max((xPos - 0.5) , -0.5), 0.5)
                            var minValue: Double = 1
                            var minValueIdx: Int = 8
                            for (idx, section) in chargingSection.enumerated(){
                                if minValue > abs((lowerValue + 0.5) - section) {
                                    minValue =  abs((lowerValue + 0.5) - section)
                                    minValueIdx = idx
                                }
                            }
                            lowerValue = chargingSection[minValueIdx] - 0.5
                        }
                    }
                }
                .foregroundColor(.gray)
        }
    }
}
728x90
반응형
LIST

'iOS' 카테고리의 다른 글

SwiftUI로 네이버 탭바 흉내나기  (0) 2023.07.09
DDD 중간 회고 feat. ( fastlane, slack, jira, tuist )  (1) 2023.07.09
📝[docs]: Core Bluetooth - 0621  (0) 2023.06.21
Tuist에서 xcode 버전 manage  (0) 2023.06.17
ViewBuilder  (0) 2023.06.01