调整范围滑块最小值、最大值、下限值和上限值?



我按照Raywenderlich网站(https://www.raywenderlich.com/7595-how-to-make-a-custom-control-tutorial-a-reusable-slider(上的教程来创建自定义范围滑块。我执行的步骤如下:

(1( 创建了一个 swift 文件,并添加了以下代码:

import UIKit
class RangeSlider: UIControl {
override var frame: CGRect {
didSet {
updateLayerFrames()
}
}
private var previousLocation = CGPoint()
var minimumValue: CGFloat = 0 {
didSet {
updateLayerFrames()
}
}
var maximumValue: CGFloat = 1 {
didSet {
updateLayerFrames()
}
}
var lowerValue: CGFloat = 0.2 {
didSet {
updateLayerFrames()
}
}
var upperValue: CGFloat = 0.8 {
didSet {
updateLayerFrames()
}
}
var trackTintColor = UIColor(white: 0.9, alpha: 1) {
didSet {
trackLayer.setNeedsDisplay()
}
}
var trackHighlightTintColor = UIColor(red: 0, green: 0.45, blue: 0.94, alpha: 1) {
didSet {
trackLayer.setNeedsDisplay()
}
}
var thumbImage = #imageLiteral(resourceName: "Oval") {
didSet {
upperThumbImageView.image = thumbImage
lowerThumbImageView.image = thumbImage
updateLayerFrames()
}
}
var highlightedThumbImage = #imageLiteral(resourceName: "HighlightedOval") {
didSet {
upperThumbImageView.highlightedImage = highlightedThumbImage
lowerThumbImageView.highlightedImage = highlightedThumbImage
updateLayerFrames()
}
}
private let trackLayer = RangeSliderTrackLayer()
private let lowerThumbImageView = UIImageView()
private let upperThumbImageView = UIImageView()
override init(frame: CGRect) {
super.init(frame: frame)
trackLayer.rangeSlider = self
trackLayer.contentsScale = UIScreen.main.scale
layer.addSublayer(trackLayer)
lowerThumbImageView.image = thumbImage
addSubview(lowerThumbImageView)
upperThumbImageView.image = thumbImage
addSubview(upperThumbImageView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func updateLayerFrames() {
CATransaction.begin()
CATransaction.setDisableActions(true)
trackLayer.frame = bounds.insetBy(dx: 0.0, dy: bounds.height / 3)
trackLayer.setNeedsDisplay()
lowerThumbImageView.frame = CGRect(origin: thumbOriginForValue(lowerValue),size: thumbImage.size)
upperThumbImageView.frame = CGRect(origin: thumbOriginForValue(upperValue),size: thumbImage.size)
CATransaction.commit()
}
func positionForValue(_ value: CGFloat) -> CGFloat {
return bounds.width * value
}
private func thumbOriginForValue(_ value: CGFloat) -> CGPoint {
let x = positionForValue(value) - thumbImage.size.width / 2.0
return CGPoint(x: x, y: (bounds.height - thumbImage.size.height) / 2.0)
}
}
extension RangeSlider {
override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
previousLocation = touch.location(in: self)
if lowerThumbImageView.frame.contains(previousLocation) {
lowerThumbImageView.isHighlighted = true
} else if upperThumbImageView.frame.contains(previousLocation) {
upperThumbImageView.isHighlighted = true
}
return lowerThumbImageView.isHighlighted || upperThumbImageView.isHighlighted
}
override func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
let location = touch.location(in: self)
let deltaLocation = location.x - previousLocation.x
let deltaValue = (maximumValue - minimumValue) * deltaLocation / bounds.width
previousLocation = location
if lowerThumbImageView.isHighlighted {
lowerValue += deltaValue
lowerValue = boundValue(lowerValue, toLowerValue: minimumValue, upperValue: upperValue)
} else if upperThumbImageView.isHighlighted {
upperValue += deltaValue
upperValue = boundValue(upperValue, toLowerValue: lowerValue, upperValue: maximumValue)
}
sendActions(for: .valueChanged)
return true
}
private func boundValue(_ value: CGFloat, toLowerValue lowerValue: CGFloat, upperValue: CGFloat) -> CGFloat {
return min(max(value, lowerValue), upperValue)
}
override func endTracking(_ touch: UITouch?, with event: UIEvent?) {
lowerThumbImageView.isHighlighted = false
upperThumbImageView.isHighlighted = false
}
}

(2( 然后,我在项目中创建了另一个 Swift 文件,并根据上述教程在其中添加了以下代码:

import UIKit
class RangeSliderTrackLayer: CALayer {
weak var rangeSlider: RangeSlider?
override func draw(in ctx: CGContext) {
guard let slider = rangeSlider else {
return
}
let path = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius)
ctx.addPath(path.cgPath)
ctx.setFillColor(slider.trackTintColor.cgColor)
ctx.fillPath()
ctx.setFillColor(slider.trackHighlightTintColor.cgColor)
let lowerValuePosition = slider.positionForValue(slider.lowerValue)
let upperValuePosition = slider.positionForValue(slider.upperValue)
let rect = CGRect(x: lowerValuePosition, y: 0, width: upperValuePosition - lowerValuePosition, height: bounds.height)
ctx.fill(rect)
}
}

(3(最后一步,是我在ViewController中创建了一个自定义范围滑块类的实例,我有兴趣在里面实现RangeSlider:

import UIKit
class FilterDataVC: UIViewController {
let rangeSlider = RangeSlider(frame: .zero)
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(rangeSlider)
rangeSlider.addTarget(self, action: #selector(rangeSliderValueChanged(_:)), for: .valueChanged)
}
override func viewDidLayoutSubviews() {
let margin: CGFloat = 20
let width = view.bounds.width - 2 * margin
let height: CGFloat = 30
rangeSlider.frame = CGRect(x: 0, y: 0, width: width, height: height)
rangeSlider.center = view.center
}
@objc func rangeSliderValueChanged(_ rangeSlider: RangeSlider) {
let values = "((rangeSlider.lowerValue) (rangeSlider.upperValue))"
}

到目前为止,事情运行完美,我获得了与教程相同的结果。但是,显然我需要为我自己的应用程序自定义范围滑块。因此,我尝试通过将上面步骤 01 中所述的代码部分更改为如下所示的代码部分来更改滑块的最小值、最大值值、下层值和上限值:

var minimumValue: CGFloat = 100 {
didSet {
updateLayerFrames()
}
}
var maximumValue: CGFloat = 1200 {
didSet {
updateLayerFrames()
}
}
var lowerValue: CGFloat = 200 {
didSet {
updateLayerFrames()
}
}
var upperValue: CGFloat = 800 {
didSet {
updateLayerFrames()
}
}

但是,在进行上述修改后,并使用模拟器运行了我的应用程序。范围滑块仅显示曲目,我看不到拇指。知道出了什么问题吗?

我设法通过调整上面 Step-01 中提到的部分代码来解决我的问题:

func positionForValue(_ value: CGFloat) -> CGFloat { 
return (bounds.width * value) / (maximumValue - minimumValue) 
} 

相关内容

最新更新