TomThorpe / TTRangeSlider

A slider, similar in style to UISlider, but which allows you to pick a minimum and maximum range.
MIT License
968 stars 204 forks source link

Accessing text labels #87

Closed vadimkrutovlv closed 6 years ago

vadimkrutovlv commented 6 years ago

Hello,

I'm using your library, it's awesome and fits all my needs. I wanted to ask is there any possibility to access text label in order to change text?

One more note, I'm using slider via bridging header and swift.

TomThorpe commented 6 years ago

Hey,

Thanks! :-)

You should be able to use the numberFormatterOverride property and write a custom number formatter to return whatever you want the text to be given the input (the slider value)

The custom slider in the example property uses numberFormatterOverride but just sets a standard numberformatter rather than anything specific, but you should be able to just make a number formatter yourself using something like this guy (quick google to find this blog post, I've not fully run through it myself!) http://blog.codehatcher.com/custom-nsnumberformatter-in-swift

vadimkrutovlv commented 6 years ago

Thanks for quick reply, the problem is that at the end I need update only one label value, but formatter will update both values. The idea is when right handle reaches maximum I need add "+" sign to amount. For example $5000+

TomThorpe commented 6 years ago

Ah, gotcha. Yeah that's a bit more tricky, sorry. It might be that you could compared the selectedMinimum and selectedMaximum with the value you're formatting, to try to guess which handle it is, although I realise that's not ideal.

There's also leftHandleSelected and rightHandleSelected bools on TTRangeSlider itself, but annoyingly they're not exposed in the header, they're just properties in the implementation, so you wouldn't be able to get to them without some hacking or editing.

vadimkrutovlv commented 6 years ago

Hey, thanks for you response I came up with very tricky solution. Here it is, I know it's to much just for changing text label value, but still for me it was only solution :)

private func onRangeSliderMaxSelection(sender: TTRangeSlider, selectedMaximum: Float)  {
        guard let layer = self.getSliderMaxiumReachedLayer(sender: sender, selectedMaximum: selectedMaximum) else { return }
        let newLayer = self.createSliderMaxReachedLayer(from: layer)

        if !self.amountFilterReachedMaxValue {
            layer.isHidden = true

            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                sender.layer.addSublayer(newLayer)
            }

            self.amountFilterReachedMaxValue = true
        }
    }

    private func onRangeSliderMaxDeselection(sender: TTRangeSlider, selectedMaximum: Float) {
        guard let sublayers = sender.layer.sublayers else { return }
        guard let layer = self.getSliderMaxiumReachedLayer(sender: sender, selectedMaximum: selectedMaximum) else { return }

        for sublayer in sublayers {
            if sublayer.name == "plusSign" {
                sublayer.removeFromSuperlayer()
                layer.isHidden = false
                self.amountFilterReachedMaxValue = false
            }
        }
    }

    private func getSliderMaxiumReachedLayer(sender: TTRangeSlider, selectedMaximum: Float) -> CATextLayer? {
        guard let sublayers = sender.layer.sublayers else { return  nil }

        for sublayer in sublayers {
            if sublayer.isKind(of: CATextLayer.self) {
                let caTextLayer = sublayer as! CATextLayer
                guard let string = caTextLayer.string as? String else { return nil }
                let formatter = NumberFormatter()
                formatter.numberStyle = .currency

                guard let number = formatter.number(from: string) else { return nil }

                if Float(truncating: number) == selectedMaximum {
                    return caTextLayer
                }
            }
        }

        return nil
    }

    private func createSliderMaxReachedLayer(from caTextLayer: CATextLayer) -> CATextLayer {
        let newLayer = CATextLayer()
        newLayer.name = "plusSign"
        newLayer.alignmentMode = kCAAlignmentCenter
        newLayer.fontSize = caTextLayer.fontSize
        newLayer.frame = CGRect(x: caTextLayer.frame.origin.x - 15,
                                y: caTextLayer.frame.origin.y ,
                                width: caTextLayer.frame.width + 10,
                                height: caTextLayer.frame.height)
        newLayer.contentsScale = UIScreen.main.scale
        newLayer.font = caTextLayer.font
        newLayer.string = "$5000+"
        newLayer.foregroundColor = caTextLayer.foregroundColor

        return newLayer
    }