Files
OrderScheduling/Pods/ZLPhotoBrowser/Sources/Edit/ZLAdjustSlider.swift
DDIsFriend f0e8a1709d initial
2023-08-18 17:28:57 +08:00

200 lines
7.1 KiB
Swift

//
// ZLAdjustSlider.swift
// ZLPhotoBrowser
//
// Created by long on 2021/12/17.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import UIKit
class ZLAdjustSlider: UIView {
static let maximumValue: Float = 1
static let minimumValue: Float = -1
let sliderWidth: CGFloat = 5
lazy var valueLabel: UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 12)
label.layer.shadowColor = UIColor.black.withAlphaComponent(0.6).cgColor
label.layer.shadowOffset = .zero
label.layer.shadowOpacity = 1
label.textColor = .white
label.textAlignment = ZLPhotoUIConfiguration.default().adjustSliderType == .vertical ? .right : .center
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.6
return label
}()
lazy var separator: UIView = {
let view = UIView()
view.backgroundColor = .zl.rgba(230, 230, 230)
return view
}()
lazy var shadowView: UIView = {
let view = UIView()
view.backgroundColor = .zl.adjustSliderNormalColor
view.layer.cornerRadius = sliderWidth / 2
view.layer.shadowColor = UIColor.black.withAlphaComponent(0.4).cgColor
view.layer.shadowOffset = .zero
view.layer.shadowOpacity = 1
view.layer.shadowRadius = 3
return view
}()
lazy var whiteView: UIView = {
let view = UIView()
view.backgroundColor = .zl.adjustSliderNormalColor
view.layer.cornerRadius = sliderWidth / 2
view.layer.masksToBounds = true
return view
}()
lazy var tintView: UIView = {
let view = UIView()
view.backgroundColor = .zl.adjustSliderTintColor
return view
}()
lazy var pan = UIPanGestureRecognizer(target: self, action: #selector(panAction(_:)))
private var impactFeedback: UIImpactFeedbackGenerator?
private var valueForPanBegan: Float = 0
var value: Float = 0 {
didSet {
valueLabel.text = String(Int(roundf(value * 100)))
tintView.frame = calculateTintFrame()
}
}
private var isVertical = ZLPhotoUIConfiguration.default().adjustSliderType == .vertical
var beginAdjust: (() -> Void)?
var valueChanged: ((Float) -> Void)?
var endAdjust: (() -> Void)?
deinit {
zl_debugPrint("ZLAdjustSlider deinit")
}
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
let editConfig = ZLPhotoConfiguration.default().editImageConfiguration
if editConfig.impactFeedbackWhenAdjustSliderValueIsZero {
impactFeedback = UIImpactFeedbackGenerator(style: editConfig.impactFeedbackStyle)
}
addGestureRecognizer(pan)
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
if isVertical {
shadowView.frame = CGRect(x: 40, y: 0, width: sliderWidth, height: bounds.height)
whiteView.frame = shadowView.frame
tintView.frame = calculateTintFrame()
let separatorH: CGFloat = 1
separator.frame = CGRect(x: 0, y: (bounds.height - separatorH) / 2, width: sliderWidth, height: separatorH)
valueLabel.frame = CGRect(x: 0, y: bounds.height / 2 - 10, width: 38, height: 20)
} else {
valueLabel.frame = CGRect(x: 0, y: 0, width: zl.width, height: 38)
shadowView.frame = CGRect(x: 0, y: valueLabel.zl.bottom + 2, width: zl.width, height: sliderWidth)
whiteView.frame = shadowView.frame
tintView.frame = calculateTintFrame()
let separatorW: CGFloat = 1
separator.frame = CGRect(x: (zl.width - separatorW) / 2, y: 0, width: separatorW, height: sliderWidth)
}
}
private func setupUI() {
addSubview(shadowView)
addSubview(whiteView)
whiteView.addSubview(tintView)
whiteView.addSubview(separator)
addSubview(valueLabel)
}
private func calculateTintFrame() -> CGRect {
if isVertical {
let totalH = zl.height / 2
let tintH = totalH * abs(CGFloat(value)) / CGFloat(ZLAdjustSlider.maximumValue)
if value > 0 {
return CGRect(x: 0, y: totalH - tintH, width: sliderWidth, height: tintH)
} else {
return CGRect(x: 0, y: totalH, width: sliderWidth, height: tintH)
}
} else {
let totalW = zl.width / 2
let tintW = totalW * abs(CGFloat(value)) / CGFloat(ZLAdjustSlider.maximumValue)
if value > 0 {
return CGRect(x: totalW, y: 0, width: tintW, height: sliderWidth)
} else {
return CGRect(x: totalW - tintW, y: 0, width: tintW, height: sliderWidth)
}
}
}
@objc private func panAction(_ pan: UIPanGestureRecognizer) {
let translation = pan.translation(in: self)
if pan.state == .began {
valueForPanBegan = value
beginAdjust?()
impactFeedback?.prepare()
} else if pan.state == .changed {
let transValue = isVertical ? -translation.y : translation.x
let totalLength = isVertical ? zl.height / 2 : zl.width / 2
var temp = valueForPanBegan + Float(transValue / totalLength)
temp = max(ZLAdjustSlider.minimumValue, min(ZLAdjustSlider.maximumValue, temp))
if (-0.0049..<0.005) ~= temp {
temp = 0
}
guard value != temp else { return }
value = temp
valueChanged?(value)
guard #available(iOS 10.0, *) else { return }
if value == 0 {
impactFeedback?.impactOccurred()
}
} else {
valueForPanBegan = value
endAdjust?()
}
}
}