507 lines
19 KiB
Swift
507 lines
19 KiB
Swift
//
|
|
// weightView.swift
|
|
// anniversary_Project
|
|
//
|
|
// Created by 忆海16 on 2024/7/9.
|
|
//
|
|
|
|
import UIKit
|
|
|
|
//let DISTANCELEFTANDRIGHT: CGFloat = 8.0 // 标尺左右距离
|
|
//let DISTANCEVALUE: CGFloat = 8.0 // 每隔刻度实际长度8个点
|
|
//let DISTANCETOPANDBOTTOM: CGFloat = 5.0 // 标尺上下距离
|
|
|
|
//class weightViewScrollView: UIScrollView {
|
|
//
|
|
// var maxValue: CGFloat = 500
|
|
// var minValue: CGFloat = 0
|
|
// var rulerAverage: CGFloat = 1
|
|
//
|
|
// var rulerCount: Int {
|
|
// return Int(maxValue - minValue)
|
|
// }
|
|
//
|
|
// var isShowShortSymbol = true
|
|
// var isSmallModel: Bool = true
|
|
//
|
|
// var binary: Int = 10
|
|
// var ruleFont = UIFont.systemFont(ofSize: 12)
|
|
//
|
|
// var longSymbolColor = UIColor.hexSting(color: "#B6BCC7", alpha: 1) {
|
|
// didSet {
|
|
// longSymbol.strokeColor = longSymbolColor.cgColor
|
|
// }
|
|
// }
|
|
// var middleSymbolColor = UIColor.hexSting(color: "#B6BCC7", alpha: 1) {
|
|
// didSet {
|
|
// middleSymbol.strokeColor = middleSymbolColor.cgColor
|
|
// }
|
|
// }
|
|
// var shortSymbolColor = UIColor.hexSting(color: "#B6BCC7", alpha: 1) {
|
|
// didSet {
|
|
// shortSymbol.strokeColor = shortSymbolColor.cgColor
|
|
// }
|
|
// }
|
|
//
|
|
// fileprivate lazy var longSymbol: CAShapeLayer = {
|
|
// let shapeLayer = CAShapeLayer()
|
|
// shapeLayer.strokeColor = longSymbolColor.cgColor
|
|
// shapeLayer.fillColor = UIColor.clear.cgColor
|
|
// shapeLayer.lineWidth = 3
|
|
// shapeLayer.lineCap = .round
|
|
// return shapeLayer
|
|
// }()
|
|
//
|
|
// fileprivate lazy var middleSymbol: CAShapeLayer = {
|
|
// let shapeLayer = CAShapeLayer()
|
|
// shapeLayer.strokeColor = middleSymbolColor.cgColor
|
|
// shapeLayer.fillColor = UIColor.clear.cgColor
|
|
// shapeLayer.lineWidth = 3
|
|
// shapeLayer.lineCap = .round
|
|
// return shapeLayer
|
|
// }()
|
|
//
|
|
// fileprivate lazy var shortSymbol: CAShapeLayer = {
|
|
// let shapeLayer = CAShapeLayer()
|
|
// shapeLayer.strokeColor = shortSymbolColor.cgColor
|
|
// shapeLayer.fillColor = UIColor.clear.cgColor
|
|
// shapeLayer.lineWidth = 3
|
|
// shapeLayer.lineCap = .round
|
|
// return shapeLayer
|
|
// }()
|
|
//
|
|
// override init(frame: CGRect) {
|
|
// super.init(frame: frame)
|
|
// setupSubviews()
|
|
// }
|
|
//
|
|
// required init?(coder aDecoder: NSCoder) {
|
|
// fatalError("init(coder:) has not been implemented")
|
|
// }
|
|
//
|
|
// func setupSubviews() {
|
|
// layer.addSublayer(shortSymbol)
|
|
// layer.addSublayer(middleSymbol)
|
|
// layer.addSublayer(longSymbol)
|
|
// backgroundColor = UIColor.white
|
|
// }
|
|
//
|
|
// func drawRuler() {
|
|
// layer.sublayers?.forEach { (sublayer) in
|
|
// if sublayer.isKind(of: CATextLayer.self) {
|
|
// sublayer.removeFromSuperlayer()
|
|
// }
|
|
// }
|
|
//
|
|
// let longPathRef = CGMutablePath()
|
|
// let middlePathRef = CGMutablePath()
|
|
// let shortPathRef = CGMutablePath()
|
|
//
|
|
// for idx in 0 ... rulerCount {
|
|
// let i = CGFloat(idx)
|
|
//
|
|
// let rule = CATextLayer()
|
|
// rule.foregroundColor = UIColor.lightGray.cgColor
|
|
// rule.font = ruleFont
|
|
// rule.fontSize = ruleFont.pointSize
|
|
// rule.contentsScale = UIScreen.main.scale
|
|
// rule.string = String(format: "%.0f", (i + minValue) * rulerAverage)
|
|
//
|
|
// let textSize = (rule.string as! NSString).size(withAttributes: [NSAttributedString.Key.font: ruleFont])
|
|
// rule.bounds = CGRect(origin: CGPoint.zero, size: textSize)
|
|
//
|
|
// let xPos = DISTANCELEFTANDRIGHT + DISTANCEVALUE * i
|
|
//
|
|
// if idx % Int(binary) == 0 {
|
|
// longPathRef.move(to: CGPoint(x: xPos, y: DISTANCETOPANDBOTTOM + textSize.height + 5))
|
|
// longPathRef.addLine(to: CGPoint(x: xPos, y: bounds.height - DISTANCETOPANDBOTTOM))
|
|
// rule.position = CGPoint(x: xPos, y: 5 + textSize.height / 2)
|
|
// layer.addSublayer(rule)
|
|
//
|
|
// } else if idx % Int(binary / 2) == 0 {
|
|
// middlePathRef.move(to: CGPoint(x: xPos, y: DISTANCETOPANDBOTTOM + textSize.height + 10))
|
|
// middlePathRef.addLine(to: CGPoint(x: xPos, y: bounds.height - DISTANCETOPANDBOTTOM))
|
|
//
|
|
// } else if isShowShortSymbol {
|
|
// shortPathRef.move(to: CGPoint(x: xPos, y: DISTANCETOPANDBOTTOM + textSize.height + 15))
|
|
// shortPathRef.addLine(to: CGPoint(x: xPos, y: bounds.height - DISTANCETOPANDBOTTOM))
|
|
// }
|
|
// }
|
|
//
|
|
// longSymbol.path = longPathRef
|
|
//
|
|
// let longSymbolFrame = longSymbol.path?.boundingBoxOfPath ?? .zero
|
|
// let longSymbolCenterY = longSymbolFrame.midY
|
|
//
|
|
// middleSymbol.path = middlePathRef
|
|
// shortSymbol.path = shortPathRef
|
|
//
|
|
// middleSymbol.position.y += (longSymbolCenterY - (middlePathRef.boundingBoxOfPath.midY))
|
|
// shortSymbol.position.y += (longSymbolCenterY - (shortPathRef.boundingBoxOfPath.midY))
|
|
//
|
|
// if isSmallModel {
|
|
// contentInset = UIEdgeInsets(top: 0, left: bounds.width / 2 - DISTANCELEFTANDRIGHT, bottom: 0, right: bounds.width / 2 - DISTANCELEFTANDRIGHT)
|
|
// contentOffset = CGPoint(x: DISTANCEVALUE * ((currentRulerValue - minValue) / rulerAverage) - bounds.width + (bounds.width / 2 + DISTANCELEFTANDRIGHT), y: 0)
|
|
// } else {
|
|
// contentOffset = CGPoint(x: DISTANCEVALUE * ((currentRulerValue - minValue) / rulerAverage) - bounds.width / 2.0 + DISTANCELEFTANDRIGHT, y: 0)
|
|
// }
|
|
//
|
|
// contentSize = CGSize(width: CGFloat(rulerCount) * DISTANCEVALUE + DISTANCELEFTANDRIGHT * 2, height: bounds.height)
|
|
// }
|
|
//
|
|
// // Computed property to get the current ruler value based on scroll position
|
|
// var currentRulerValue: CGFloat {
|
|
// let offsetX = contentOffset.x + bounds.size.width / 2 - DISTANCELEFTANDRIGHT
|
|
// return (offsetX / DISTANCEVALUE) * rulerAverage + minValue
|
|
// }
|
|
//}
|
|
//
|
|
//protocol weightViewDelegate: AnyObject {
|
|
// func sliderRulerView(ruler: UIView, rulervalue: CGFloat)
|
|
//
|
|
//}
|
|
//
|
|
//class weightRulerView: UIView {
|
|
//
|
|
// weak var delegate: weightViewDelegate?
|
|
//
|
|
// var valueLabelFont = UIFont.boldSystemFont(ofSize: 14) {
|
|
// didSet {
|
|
// valueLabel.font = valueLabelFont
|
|
// }
|
|
// }
|
|
//
|
|
// var rulerHeight: CGFloat = 50.0 {
|
|
// didSet {
|
|
// rulerScrollView.frame = CGRect(x: 0, y: frame.size.height - rulerHeight, width: frame.size.width, height: rulerHeight)
|
|
// rulerScrollView.drawRuler()
|
|
// }
|
|
// }
|
|
//
|
|
// public var rulerScrollView = weightViewScrollView()
|
|
// public let markLine = CALayer()
|
|
// public let valueLabel = UILabel()
|
|
// public let valueImageV = UIImageView()
|
|
// public let TriangleimagV = UIImageView()
|
|
// public let TriangtopleimagV = UIImageView()
|
|
//
|
|
//// var rulerValue: CGFloat {
|
|
//// return rulerScrollView.rulerValue
|
|
//// }
|
|
//
|
|
// override init(frame: CGRect) {
|
|
// super.init(frame: frame)
|
|
// rulerScrollView.frame = CGRect(x: 0, y: frame.size.height - rulerHeight, width: frame.size.width, height: rulerHeight)
|
|
// rulerScrollView.showsHorizontalScrollIndicator = false
|
|
// rulerScrollView.delegate = self
|
|
// addSubview(rulerScrollView)
|
|
//
|
|
//
|
|
// valueImageV.image = UIImage(named: "bgkg")
|
|
// valueImageV.frame = CGRect(x: center.x - 119.5, y: rulerScrollView.frame.minY - 55, width: 239, height: 46)
|
|
// addSubview(valueImageV)
|
|
//
|
|
//
|
|
// TriangleimagV.image = UIImage(named: "buttonTriangle")
|
|
// TriangleimagV.frame = CGRect(x: center.x - 11, y: rulerScrollView.frame.minY + 55, width: 22, height: 12)
|
|
// addSubview(TriangleimagV)
|
|
//
|
|
// TriangtopleimagV.image = UIImage(named: "topTriangle")
|
|
// TriangtopleimagV.frame = CGRect(x: center.x - 11, y: rulerScrollView.frame.maxY - 55, width: 22, height: 12)
|
|
// addSubview(TriangtopleimagV)
|
|
//
|
|
// valueLabel.font = UIFont.boldSystemFont(ofSize: 24)
|
|
// valueLabel.textAlignment = .center
|
|
// valueLabel.textColor = UIColor.hexSting(color: "#62BFFF", alpha: 1)
|
|
// valueLabel.frame = CGRect(x: 0, y: rulerScrollView.frame.minY - 44, width: bounds.width, height: 25)
|
|
// valueLabel.text = "160 kg"
|
|
// addSubview(valueLabel)
|
|
//
|
|
// }
|
|
//
|
|
// required init?(coder aDecoder: NSCoder) {
|
|
// fatalError("init(coder:) has not been implemented")
|
|
// }
|
|
//
|
|
// override func layoutSubviews() {
|
|
// super.layoutSubviews()
|
|
// rulerScrollView.drawRuler()
|
|
// }
|
|
//
|
|
// func animationRebound() {
|
|
// // Method intentionally left empty to remove snapping effect
|
|
// }
|
|
//}
|
|
//
|
|
//extension weightRulerView: UIScrollViewDelegate {
|
|
//
|
|
// func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
|
//
|
|
// let offSetX = scrollView.contentOffset.x + bounds.size.width / 2 - DISTANCELEFTANDRIGHT
|
|
// let ruleValue = (offSetX / DISTANCEVALUE) * rulerScrollView.rulerAverage
|
|
// let valuetext = "\(round(ruleValue) + rulerScrollView.minValue) kg"
|
|
// if valuetext != valueLabel.text {
|
|
// valueLabel.text = valuetext
|
|
//
|
|
// }
|
|
// }
|
|
//
|
|
//
|
|
// func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
|
|
// // animationRebound() removed to prevent snapping
|
|
// }
|
|
//
|
|
// func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
|
|
// // animationRebound() removed to prevent snapping
|
|
// }
|
|
//}
|
|
|
|
import UIKit
|
|
|
|
class weightViewScrollView: UIScrollView {
|
|
|
|
// var onweightSelected: ((Int) -> Void)?
|
|
var maxValue: CGFloat = 500
|
|
var minValue: CGFloat = 0
|
|
var rulerAverage: CGFloat = 1
|
|
|
|
var rulerCount: Int {
|
|
return Int(maxValue - minValue)
|
|
}
|
|
|
|
var isShowShortSymbol = true
|
|
var isSmallModel: Bool = true
|
|
|
|
var binary: Int = 10
|
|
var ruleFont = UIFont.systemFont(ofSize: 12)
|
|
|
|
var longSymbolColor = UIColor.hexSting(color: "#B6BCC7", alpha: 1) {
|
|
didSet {
|
|
longSymbol.strokeColor = longSymbolColor.cgColor
|
|
}
|
|
}
|
|
var middleSymbolColor = UIColor.hexSting(color: "#B6BCC7", alpha: 1) {
|
|
didSet {
|
|
middleSymbol.strokeColor = middleSymbolColor.cgColor
|
|
}
|
|
}
|
|
var shortSymbolColor = UIColor.hexSting(color: "#B6BCC7", alpha: 1) {
|
|
didSet {
|
|
shortSymbol.strokeColor = shortSymbolColor.cgColor
|
|
}
|
|
}
|
|
|
|
fileprivate lazy var longSymbol: CAShapeLayer = {
|
|
let shapeLayer = CAShapeLayer()
|
|
shapeLayer.strokeColor = longSymbolColor.cgColor
|
|
shapeLayer.fillColor = UIColor.clear.cgColor
|
|
shapeLayer.lineWidth = 3
|
|
shapeLayer.lineCap = .round
|
|
return shapeLayer
|
|
}()
|
|
|
|
fileprivate lazy var middleSymbol: CAShapeLayer = {
|
|
let shapeLayer = CAShapeLayer()
|
|
shapeLayer.strokeColor = middleSymbolColor.cgColor
|
|
shapeLayer.fillColor = UIColor.clear.cgColor
|
|
shapeLayer.lineWidth = 3
|
|
shapeLayer.lineCap = .round
|
|
return shapeLayer
|
|
}()
|
|
|
|
fileprivate lazy var shortSymbol: CAShapeLayer = {
|
|
let shapeLayer = CAShapeLayer()
|
|
shapeLayer.strokeColor = shortSymbolColor.cgColor
|
|
shapeLayer.fillColor = UIColor.clear.cgColor
|
|
shapeLayer.lineWidth = 3
|
|
shapeLayer.lineCap = .round
|
|
return shapeLayer
|
|
}()
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
setupSubviews()
|
|
}
|
|
|
|
required init?(coder aDecoder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func setupSubviews() {
|
|
layer.addSublayer(shortSymbol)
|
|
layer.addSublayer(middleSymbol)
|
|
layer.addSublayer(longSymbol)
|
|
backgroundColor = UIColor.white
|
|
}
|
|
|
|
func drawRuler() {
|
|
layer.sublayers?.forEach { (sublayer) in
|
|
if sublayer.isKind(of: CATextLayer.self) {
|
|
sublayer.removeFromSuperlayer()
|
|
}
|
|
}
|
|
|
|
let longPathRef = CGMutablePath()
|
|
let middlePathRef = CGMutablePath()
|
|
let shortPathRef = CGMutablePath()
|
|
|
|
for idx in 0 ... rulerCount {
|
|
let i = CGFloat(idx)
|
|
|
|
let rule = CATextLayer()
|
|
rule.foregroundColor = UIColor.lightGray.cgColor
|
|
rule.font = ruleFont
|
|
rule.fontSize = ruleFont.pointSize
|
|
rule.contentsScale = UIScreen.main.scale
|
|
rule.string = String(format: "%.0f", (i + minValue) * rulerAverage)
|
|
|
|
let textSize = (rule.string as! NSString).size(withAttributes: [NSAttributedString.Key.font: ruleFont])
|
|
rule.bounds = CGRect(origin: CGPoint.zero, size: textSize)
|
|
|
|
let xPos = DISTANCELEFTANDRIGHT + DISTANCEVALUE * i
|
|
|
|
if idx % Int(binary) == 0 {
|
|
longPathRef.move(to: CGPoint(x: xPos, y: DISTANCETOPANDBOTTOM + textSize.height + 5))
|
|
longPathRef.addLine(to: CGPoint(x: xPos, y: bounds.height - DISTANCETOPANDBOTTOM))
|
|
rule.position = CGPoint(x: xPos, y: 5 + textSize.height / 2)
|
|
layer.addSublayer(rule)
|
|
|
|
} else if idx % Int(binary / 2) == 0 {
|
|
middlePathRef.move(to: CGPoint(x: xPos, y: DISTANCETOPANDBOTTOM + textSize.height + 10))
|
|
middlePathRef.addLine(to: CGPoint(x: xPos, y: bounds.height - DISTANCETOPANDBOTTOM))
|
|
|
|
} else if isShowShortSymbol {
|
|
shortPathRef.move(to: CGPoint(x: xPos, y: DISTANCETOPANDBOTTOM + textSize.height + 15))
|
|
shortPathRef.addLine(to: CGPoint(x: xPos, y: bounds.height - DISTANCETOPANDBOTTOM))
|
|
}
|
|
}
|
|
|
|
longSymbol.path = longPathRef
|
|
|
|
let longSymbolFrame = longSymbol.path?.boundingBoxOfPath ?? .zero
|
|
let longSymbolCenterY = longSymbolFrame.midY
|
|
|
|
middleSymbol.path = middlePathRef
|
|
shortSymbol.path = shortPathRef
|
|
|
|
middleSymbol.position.y += (longSymbolCenterY - (middlePathRef.boundingBoxOfPath.midY))
|
|
shortSymbol.position.y += (longSymbolCenterY - (shortPathRef.boundingBoxOfPath.midY))
|
|
|
|
if isSmallModel {
|
|
contentInset = UIEdgeInsets(top: 0, left: bounds.width / 2 - DISTANCELEFTANDRIGHT, bottom: 0, right: bounds.width / 2 - DISTANCELEFTANDRIGHT)
|
|
contentOffset = CGPoint(x: DISTANCEVALUE * ((currentRulerValue - minValue) / rulerAverage) - bounds.width + (bounds.width / 2 + DISTANCELEFTANDRIGHT), y: 0)
|
|
} else {
|
|
contentOffset = CGPoint(x: DISTANCEVALUE * ((currentRulerValue - minValue) / rulerAverage) - bounds.width / 2.0 + DISTANCELEFTANDRIGHT, y: 0)
|
|
}
|
|
|
|
contentSize = CGSize(width: CGFloat(rulerCount) * DISTANCEVALUE + DISTANCELEFTANDRIGHT * 2, height: bounds.height)
|
|
}
|
|
|
|
var currentRulerValue: CGFloat {
|
|
let offsetX = contentOffset.x + bounds.size.width / 2 - DISTANCELEFTANDRIGHT
|
|
// onweightSelected?(Int((offsetX / DISTANCEVALUE) * rulerAverage + minValue))
|
|
return (offsetX / DISTANCEVALUE) * rulerAverage + minValue
|
|
|
|
}
|
|
}
|
|
|
|
protocol weightViewDelegate: AnyObject {
|
|
func sliderRulerView(ruler: weightRulerView, rulervalue: CGFloat)
|
|
}
|
|
|
|
class weightRulerView: UIView {
|
|
// var onweightSelected: ((Int) -> Void)?
|
|
weak var delegate: weightViewDelegate?
|
|
|
|
var valueLabelFont = UIFont.boldSystemFont(ofSize: 14) {
|
|
didSet {
|
|
valueLabel.font = valueLabelFont
|
|
}
|
|
}
|
|
|
|
var rulerHeight: CGFloat = 50.0 {
|
|
didSet {
|
|
rulerScrollView.frame = CGRect(x: 0, y: frame.size.height - rulerHeight, width: frame.size.width, height: rulerHeight)
|
|
rulerScrollView.drawRuler()
|
|
}
|
|
}
|
|
|
|
public var rulerScrollView = weightViewScrollView()
|
|
public let markLine = CALayer()
|
|
public let valueLabel = UILabel()
|
|
public let valueImageV = UIImageView()
|
|
public let TriangleimagV = UIImageView()
|
|
public let TriangtopleimagV = UIImageView()
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
rulerScrollView.frame = CGRect(x: 0, y: frame.size.height - rulerHeight, width: frame.size.width, height: rulerHeight)
|
|
rulerScrollView.showsHorizontalScrollIndicator = false
|
|
rulerScrollView.delegate = self
|
|
addSubview(rulerScrollView)
|
|
|
|
valueImageV.image = UIImage(named: "bgkg")
|
|
valueImageV.frame = CGRect(x: center.x - 119.5, y: rulerScrollView.frame.minY - 55, width: 239, height: 46)
|
|
addSubview(valueImageV)
|
|
|
|
TriangleimagV.image = UIImage(named: "buttonTriangle")
|
|
TriangleimagV.frame = CGRect(x: center.x - 11, y: rulerScrollView.frame.minY + 55, width: 22, height: 12)
|
|
addSubview(TriangleimagV)
|
|
|
|
TriangtopleimagV.image = UIImage(named: "topTriangle")
|
|
TriangtopleimagV.frame = CGRect(x: center.x - 11, y: rulerScrollView.frame.maxY - 55, width: 22, height: 12)
|
|
addSubview(TriangtopleimagV)
|
|
|
|
valueLabel.font = UIFont.boldSystemFont(ofSize: 24)
|
|
valueLabel.textAlignment = .center
|
|
valueLabel.textColor = UIColor.hexSting(color: "#62BFFF", alpha: 1)
|
|
valueLabel.frame = CGRect(x: 0, y: rulerScrollView.frame.minY - 44, width: bounds.width, height: 25)
|
|
valueLabel.text = "160 kg"
|
|
addSubview(valueLabel)
|
|
let defaults = UserDefaults.standard
|
|
let weightint = Int(valueLabel.text!)
|
|
defaults.set(weightint, forKey: "weight")
|
|
}
|
|
|
|
required init?(coder aDecoder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
override func layoutSubviews() {
|
|
super.layoutSubviews()
|
|
rulerScrollView.drawRuler()
|
|
}
|
|
|
|
func animationRebound() {
|
|
// Method intentionally left empty to remove snapping effect
|
|
}
|
|
}
|
|
|
|
extension weightRulerView: UIScrollViewDelegate {
|
|
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
|
print("ScrollView did scroll")
|
|
let offSetX = scrollView.contentOffset.x + bounds.size.width / 2 - DISTANCELEFTANDRIGHT
|
|
let ruleValue = (offSetX / DISTANCEVALUE) * rulerScrollView.rulerAverage
|
|
let valueText = "\(round(ruleValue) + rulerScrollView.minValue) kg"
|
|
|
|
if valueText != valueLabel.text {
|
|
valueLabel.text = valueText
|
|
delegate?.sliderRulerView(ruler: self, rulervalue: ruleValue + rulerScrollView.minValue)
|
|
}
|
|
// onweightSelected?(Int(valueText) ?? 0)
|
|
let defaults = UserDefaults.standard
|
|
let currentRulerValue = rulerScrollView.currentRulerValue
|
|
print("----\(currentRulerValue)")
|
|
let weightint = Int(currentRulerValue)
|
|
defaults.set(weightint, forKey: "weight")
|
|
}
|
|
|
|
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
|
|
// animationRebound() removed to prevent snapping
|
|
}
|
|
|
|
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
|
|
// animationRebound() removed to prevent snapping
|
|
}
|
|
}
|