스위프트 3.0에서 다시 작성한이 범위 슬라이더를 사용하면 2.2를 신속하게 재현 할 수 있습니다.하지만 문제가 발생했습니다. 문제가있는 것 같습니다. 그래서 지금 나는 당신들과 그것을 공유하고 있습니다 :)스위프트 범위 슬라이더가 제대로 작동하지 않습니다. 버그를 찾을 수 없습니다
문제는 제가 단지 엄지 손가락 중 하나를 드래그 할 수 있다는 것입니다, 그리고 오직 한 번만, 그리고 모든 것이 붙어 있습니다. https://github.com/nharbo/RangeSliderSwift2.2 그것은 단지 2 클래스, 그래서 당신은 시간이 있다면, 난 당신이 좀보고 싶어요 :
내 데모 프로젝트는 여기에서 찾을 수 있습니다! 또한
, 여기에 내가 의심하는 클래스 중 하나의 코드가되어있어 하나 만드는 문제 :
/// Range slider track layer. Responsible for drawing the horizontal track
public class RangeSliderTrackLayer: CALayer {
/// owner slider
weak var rangeSlider: NHRangeSlider?
/// draw the track between 2 thumbs
///
/// - Parameter ctx: current graphics context
public override func drawInContext(ctx: CGContext) {
super.drawInContext(ctx)
guard let slider = rangeSlider else {
return
}
// Clip
let cornerRadius = bounds.height * slider.curvaceousness/2.0
let path = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius)
CGContextAddPath(ctx, path.CGPath)
// Fill the track
CGContextSetFillColorWithColor(ctx, slider.trackTintColor.CGColor)
CGContextAddPath(ctx, path.CGPath)
CGContextFillPath(ctx)
// Fill the highlighted range
CGContextSetFillColorWithColor(ctx, slider.trackHighlightTintColor.CGColor)
let lowerValuePosition = CGFloat(slider.positionForValue(slider.lowerValue))
let upperValuePosition = CGFloat(slider.positionForValue(slider.upperValue))
let rect = CGRect(x: lowerValuePosition, y: 0.0, width: upperValuePosition - lowerValuePosition, height: bounds.height)
CGContextFillRect(ctx, rect)
}
}
/// the thumb for upper , lower bounds
public class RangeSliderThumbLayer: CALayer {
/// owner slider
weak var rangeSlider: NHRangeSlider?
/// whether this thumb is currently highlighted i.e. touched by user
public var highlighted: Bool = false {
didSet {
setNeedsDisplay()
}
}
/// stroke color
public var strokeColor: UIColor = UIColor.grayColor() {
didSet {
setNeedsDisplay()
}
}
/// line width
public var lineWidth: CGFloat = 0.5 {
didSet {
setNeedsDisplay()
}
}
/// draw the thumb
///
/// - Parameter ctx: current graphics context
public override func drawInContext(ctx: CGContext) {
super.drawInContext(ctx)
guard let slider = rangeSlider else {
return
}
let thumbFrame = bounds.insetBy(dx: 2.0, dy: 2.0)
let cornerRadius = thumbFrame.height * slider.curvaceousness/2.0
let thumbPath = UIBezierPath(roundedRect: thumbFrame, cornerRadius: cornerRadius)
// Fill
CGContextSetFillColorWithColor(ctx, slider.thumbTintColor.CGColor)
CGContextAddPath(ctx, thumbPath.CGPath)
CGContextFillPath(ctx)
// Outline
CGContextSetStrokeColorWithColor(ctx, strokeColor.CGColor)
CGContextSetLineWidth(ctx, lineWidth)
CGContextAddPath(ctx, thumbPath.CGPath)
CGContextStrokePath(ctx)
if highlighted {
CGContextSetFillColorWithColor(ctx, UIColor(white: 0.0, alpha: 0.1).CGColor)
CGContextAddPath(ctx, thumbPath.CGPath)
CGContextFillPath(ctx)
}
}
}
/// Range slider view with upper, lower bounds
@IBDesignable
public class NHRangeSlider: UIControl {
// MARK: properties
/// minimum value
@IBInspectable public var minimumValue: Double = 0.0 {
willSet(newValue) {
assert(newValue < maximumValue, "NHRangeSlider: minimumValue should be lower than maximumValue")
}
didSet {
updateLayerFrames()
}
}
/// max value
@IBInspectable public var maximumValue: Double = 100.0 {
willSet(newValue) {
assert(newValue > minimumValue, "NHRangeSlider: maximumValue should be greater than minimumValue")
}
didSet {
updateLayerFrames()
}
}
/// value for lower thumb
@IBInspectable public var lowerValue: Double = 0.0 {
didSet {
if lowerValue < minimumValue {
lowerValue = minimumValue
}
updateLayerFrames()
}
}
/// value for upper thumb
@IBInspectable public var upperValue: Double = 100.0 {
didSet {
if upperValue > maximumValue {
upperValue = maximumValue
}
updateLayerFrames()
}
}
/// stepValue. If set, will snap to discrete step points along the slider . Default to nil
@IBInspectable public var stepValue: Double? = nil {
willSet(newValue) {
if newValue != nil {
assert(newValue! > 0, "NHRangeSlider: stepValue must be positive")
}
}
didSet {
if let val = stepValue {
if val <= 0 {
stepValue = nil
}
}
updateLayerFrames()
}
}
/// minimum distance between the upper and lower thumbs.
@IBInspectable public var gapBetweenThumbs: Double = 2.0
/// tint color for track between 2 thumbs
@IBInspectable public var trackTintColor: UIColor = UIColor(white: 0.9, alpha: 1.0) {
didSet {
trackLayer.setNeedsDisplay()
}
}
/// track highlight tint color
@IBInspectable public var trackHighlightTintColor: UIColor = UIColor(red: 0.0, green: 0.45, blue: 0.94, alpha: 1.0) {
didSet {
trackLayer.setNeedsDisplay()
}
}
/// thumb tint color
@IBInspectable public var thumbTintColor: UIColor = UIColor.whiteColor() {
didSet {
lowerThumbLayer.setNeedsDisplay()
upperThumbLayer.setNeedsDisplay()
}
}
/// thumb border color
@IBInspectable public var thumbBorderColor: UIColor = UIColor.grayColor() {
didSet {
lowerThumbLayer.strokeColor = thumbBorderColor
upperThumbLayer.strokeColor = thumbBorderColor
}
}
/// thumb border width
@IBInspectable public var thumbBorderWidth: CGFloat = 0.5 {
didSet {
lowerThumbLayer.lineWidth = thumbBorderWidth
upperThumbLayer.lineWidth = thumbBorderWidth
}
}
/// set 0.0 for square thumbs to 1.0 for circle thumbs
@IBInspectable public var curvaceousness: CGFloat = 1.0 {
didSet {
if curvaceousness < 0.0 {
curvaceousness = 0.0
}
if curvaceousness > 1.0 {
curvaceousness = 1.0
}
trackLayer.setNeedsDisplay()
lowerThumbLayer.setNeedsDisplay()
upperThumbLayer.setNeedsDisplay()
}
}
/// previous touch location
private var previouslocation = CGPoint()
/// track layer
private let trackLayer = RangeSliderTrackLayer()
/// lower thumb layer
public let lowerThumbLayer = RangeSliderThumbLayer()
/// upper thumb layer
public let upperThumbLayer = RangeSliderThumbLayer()
/// thumb width
private var thumbWidth: CGFloat {
return CGFloat(bounds.height)
}
/// frame
override public var frame: CGRect {
didSet {
updateLayerFrames()
}
}
// MARK: init methods
override public init(frame: CGRect) {
super.init(frame: frame)
initializeLayers()
}
required public init?(coder: NSCoder) {
super.init(coder: coder)
initializeLayers()
}
// MARK: layers
/// layout sub layers
///
/// - Parameter of: layer
public override func layoutSublayersOfLayer(layer: CALayer) {
super.layoutSublayersOfLayer(layer)
updateLayerFrames()
}
/// init layers
private func initializeLayers() {
layer.backgroundColor = UIColor.clearColor().CGColor
trackLayer.rangeSlider = self
trackLayer.contentsScale = UIScreen.mainScreen().scale
layer.addSublayer(trackLayer)
lowerThumbLayer.rangeSlider = self
lowerThumbLayer.contentsScale = UIScreen.mainScreen().scale
layer.addSublayer(lowerThumbLayer)
upperThumbLayer.rangeSlider = self
upperThumbLayer.contentsScale = UIScreen.mainScreen().scale
layer.addSublayer(upperThumbLayer)
}
/// update layer frames
public func updateLayerFrames() {
CATransaction.begin()
CATransaction.setDisableActions(true)
trackLayer.frame = bounds.insetBy(dx: 0.0, dy: bounds.height/3)
trackLayer.setNeedsDisplay()
let lowerThumbCenter = CGFloat(positionForValue(lowerValue))
lowerThumbLayer.frame = CGRect(x: lowerThumbCenter - thumbWidth/2.0, y: 0.0, width: thumbWidth, height: thumbWidth)
lowerThumbLayer.setNeedsDisplay()
let upperThumbCenter = CGFloat(positionForValue(upperValue))
upperThumbLayer.frame = CGRect(x: upperThumbCenter - thumbWidth/2.0, y: 0.0, width: thumbWidth, height: thumbWidth)
upperThumbLayer.setNeedsDisplay()
CATransaction.commit()
}
/// thumb x position for new value
public func positionForValue(value: Double) -> Double {
if (maximumValue == minimumValue) {
return 0
}
return Double(bounds.width - thumbWidth) * (value - minimumValue)/(maximumValue - minimumValue)
+ Double(thumbWidth/2.0)
}
/// bound new value within lower and upper value
///
/// - Parameters:
/// - value: value to set
/// - lowerValue: lower value
/// - upperValue: upper value
/// - Returns: current value
public func boundValue(value: Double, toLowerValue lowerValue: Double, upperValue: Double) -> Double {
return min(max(value, lowerValue), upperValue)
}
// MARK: - Touches
/// begin tracking
public override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
super.beginTrackingWithTouch(touch, withEvent: event)
// set highlighted positions for lower and upper thumbs
if lowerThumbLayer.frame.contains(previouslocation) {
lowerThumbLayer.highlighted = true
}
if upperThumbLayer.frame.contains(previouslocation) {
upperThumbLayer.highlighted = true
}
return lowerThumbLayer.highlighted || upperThumbLayer.highlighted
}
/// update positions for lower and upper thumbs
public override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
super.continueTrackingWithTouch(touch, withEvent: event)
let location = touch.locationInView(self)
// Determine by how much the user has dragged
let deltaLocation = Double(location.x - previouslocation.x)
var deltaValue: Double = 0
if (bounds.width != bounds.height) {
deltaValue = (maximumValue - minimumValue) * deltaLocation/Double(bounds.width - bounds.height)
}
previouslocation = location
// if both are highlighted. we need to decide which direction to drag
if lowerThumbLayer.highlighted && upperThumbLayer.highlighted {
if deltaLocation > 0 {
// left to right
upperValue = boundValue(upperValue + deltaValue, toLowerValue: lowerValue + gapBetweenThumbs, upperValue: maximumValue)
}
else {
// right to left
lowerValue = boundValue(lowerValue + deltaValue, toLowerValue: minimumValue, upperValue: upperValue - gapBetweenThumbs)
}
}
else {
// Update the values
if lowerThumbLayer.highlighted {
lowerValue = boundValue(lowerValue + deltaValue, toLowerValue: minimumValue, upperValue: upperValue - gapBetweenThumbs)
} else if upperThumbLayer.highlighted {
upperValue = boundValue(upperValue + deltaValue, toLowerValue: lowerValue + gapBetweenThumbs, upperValue: maximumValue)
}
}
// only send changed value if stepValue is not set. We will trigger this later in endTracking
if stepValue == nil {
sendActionsForControlEvents(.ValueChanged)
}
return true
}
/// end touch tracking. Unhighlight the two thumbs
public override func endTrackingWithTouch(touch: UITouch?, withEvent event: UIEvent?) {
super.endTrackingWithTouch(touch, withEvent: event)
lowerThumbLayer.highlighted = false
upperThumbLayer.highlighted = false
// let slider snap after user stop dragging
if let stepValue = stepValue {
lowerValue = round(lowerValue/stepValue) * stepValue
upperValue = round(upperValue/stepValue) * stepValue
sendActionsForControlEvents(.ValueChanged)
}
}
}
좋아요, 이것은 많은 도움이되었습니다. 감사! 문제는, 내가 쓰는 것처럼 upperThumb이 movine이라는 것입니다. 그것은 드래그 할 때 손가락으로 움직이지만 첫 번째 터치에서 약간 이상하게 작동합니다. 그것은 터치로 왼쪽으로 이동 .. 왜 어떤 ide? :-) 그리고 다시, 고마워! 이것은 이미 훨씬 더 좋습니다 !! –
행복했기 때문에 :) 물론 유용했다면 "정답"을 주시겠습니까? 여기 저녁입니다. 내일 아침 코드를 살펴보고 첫 번째 터치에 대해 알려 드리겠습니다 ... 내 의심은 엄지 손가락의 프레임을 어딘가에 설정하는 것입니다. 그래서 그게 문제인지 살펴 보시 겠어요? 물론 – Fahim
! 나는 당신의 대답을 받아 들일 것이다. 그리고 제발, 만일 당신이 마지막 일부에 관해 안다면, 나는 매우 행복 할 것이다! 나는 네가 말한 것을 보 겠지만, 너도 그렇게 멋진 이드가 될 것이다 :) 멋진 하루 보내! :)) –