Интерактивное отслеживание с диаграммами iOS. Как

Возможно ли использование iOS Charts (от Daniel Gindi https://github.com/danielgindi/Charts) отслеживать прикосновения? Поэтому, когда я двигаю пальцем по экрану, вместо панорамирования графика он будет постоянно выделять запись, к которой я прикоснулся. Что-то вроде изображения ниже.

Я думаю, возможно, добавить UIGestureRecognizer в представление диаграммы, получить положение касания и программно выделить запись. Но как я могу получить запись в этой конкретной позиции? Спасибо

введите описание изображения здесь


person Jack Guo    schedule 02.02.2018    source источник
comment
Проверьте, полезна ли эта ветка: github.com/danielgindi/Charts/issues/148   -  person Nitish    schedule 02.02.2018
comment
Я не знаю о полной функции, которую вы пытаетесь создать, но потребовалось 15 секунд чтения документов, чтобы увидеть, что в библиотеке уже есть методы для взаимодействия с диаграммами и касания/выделения точек. Я бы начал с них и попытался сделать это, прежде чем задавать вопрос кому-то, кто сделает это за вас.   -  person Simon McLoughlin    schedule 02.02.2018


Ответы (2)


Я понял это, чтобы спасти тебя когда-нибудь

введите описание изображения здесь

extension GraphViewController: ChartViewDelegate {

    func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {

        // I used the x pixel property of the highlight to update the
        // position of the floating label, and set its text to the 
        // x value of the selected entry
        floatingLabelCenterConstraint?.constant = highlight.xPx
        floatingLabel.text = "  Mar 14  \(highlight.x)"

        // Create the nice transition animation
        // fadeIn() and fadeOut() are simple extension methods I wrote
        if floatingLabel.isHidden {
            floatingLabel.fadeIn()
            subscripts.fadeOut()
        }

        // This gives you the y value of the selected entry
        greenNumber.text = NSString(format: "%.2f", highlight.y) as String
    }
}

Однако этот метод делегата вызывается только тогда, когда вы двигаете пальцем. Вам нужен способ сказать, когда жест панорамирования закончился. Диаграммы не имеют этого метода делегата из коробки, поэтому вам нужно его добавить. Перейдите к исходному файлу ChartViewBase.swift, добавьте следующее в протокол ChartViewDelegate

public protocol ChartViewDelegate
{
    ...
    @objc optional func panGestureEnded(_ chartView: ChartViewBase)
}

Затем перейдите к BarLineChartViewBase.swift, найдите panGestureRecognized функцию

@objc private func panGestureRecognized(_ recognizer: NSUIPanGestureRecognizer)
{
    ...
    else if recognizer.state == NSUIGestureRecognizerState.ended || recognizer.state == NSUIGestureRecognizerState.cancelled
    {
    ...

    // Add this line at the end
    delegate?.panGestureEnded?(self)
    }
}

Наконец, вернитесь к вашему viewController и добавьте следующее. Теперь все работает как шарм

func panGestureEnded(_ chartView: ChartViewBase) {
    subscripts.fadeIn()
    floatingLabel.fadeOut()

    // clear selection by setting highlightValue to nil
    chartView.highlightValue(nil)
}
person Jack Guo    schedule 18.03.2018

ОБНОВЛЕНИЕ

Эта функция была добавлена ​​в последнюю версию IOS-Charts с помощью этого запроса на включение< /а>.

ChartViewDelegate был обновлен и теперь включает следующий метод.

public protocol ChartViewDelegate
{
     ...

    /// Called when a user stop highlighting values while panning
    @objc optional func chartViewDidEndPanning(_ chartView: ChartViewBase)
} 

Все, что вам нужно сделать, это реализовать этот метод везде, где вы реализуете ChartViewDelegate (контроллер представления с вашей диаграммой).

Подкласс исходного ответа LineChartView

Ответ @JGuo работает, но требует изменения кода внутри модуля. Это означает, что каждый раз, когда вы обновляете свои модули, вам придется заново вносить эти изменения. Вы можете добиться тех же результатов без изменения модуля следующим образом:

Создать протокол

import Charts

@objc protocol MyChartViewDelegate {
    @objc optional func chartValueNoLongerSelected(_ chartView: MyLineChartView)
}

Подкласс LineChartView

open class MyLineChartView: LineChartView {

    @objc weak var myChartViewDelegate: MyChartViewDelegate?

    private var touchesMoved = false

    // Haptic Feedback
    private let impactGenerator = UIImpactFeedbackGenerator(style: .light)
    private let selectionGenerator = UISelectionFeedbackGenerator()

    override open func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        // This is here to prevent the UITapGesture from blocking touches moved from firing
        if gestureRecognizer.isKind(of: NSUITapGestureRecognizer.classForCoder()){
            return false
        }
        return super.gestureRecognizerShouldBegin(gestureRecognizer)
    }

    override open func nsuiTouchesBegan(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?) {
        impactGenerator.impactOccurred()
        selectionGenerator.prepare()
        // adds the highlight to the graph when tapped
        super.nsuiTouchesBegan(touches, withEvent: event)
        touchesMoved = false
        if let touch = touches.first {
            let h = getHighlightByTouchPoint(touch.location(in: self))

            if h === nil || h == self.lastHighlighted {
                lastHighlighted = nil
                highlightValue(nil, callDelegate: true)
            }
            else {
                lastHighlighted = h
                highlightValue(h, callDelegate: true)
            }
        }
    }

    open override func nsuiTouchesEnded(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?) {
        super.nsuiTouchesEnded(touches, withEvent: event)
        myChartViewDelegate?.chartValueNoLongerSelected?(self) // remove the highlight
    }

    open override func nsuiTouchesCancelled(_ touches: Set<NSUITouch>?, withEvent event: NSUIEvent?) {
        super.nsuiTouchesCancelled(touches, withEvent: event)
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            // if a tap turns into a panGesture touches cancelled is called this prevents the highlight from being moved
            if !self.touchesMoved {
                self.myChartViewDelegate?.chartValueNoLongerSelected?(self)
            }
        }
    }

    override open func nsuiTouchesMoved(_ touches: Set<NSUITouch>, withEvent event: NSUIEvent?) {
        super.nsuiTouchesMoved(touches, withEvent: event)
        touchesMoved = true

        if let touch = touches.first {
            let h = getHighlightByTouchPoint(touch.location(in: self))

            if h === nil {
                lastHighlighted = nil
                highlightValue(nil, callDelegate: true)
            }
            else if h == self.lastHighlighted {
                return
            }
            else {
                lastHighlighted = h
                highlightValue(h, callDelegate: true)
                selectionGenerator.selectionChanged()
            }
        }
    }
}

Создайте свою диаграмму

let lineChartView = MyLineChartView()

override func viewDidLoad() {
    super.viewDidLoad()
    lineChartView.delegate = self // built in delegate for user interaction
    lineChartView.myChartViewDelegate = self // delegate with our additions (knowing when a value is no longer selected)
    lineChartView.highlightPerTapEnabled = false // disable tap gesture to highlight
    lineChartView.highlightPerDragEnabled = false // disable pan gesture
}

Реализация делегатов

extension MyViewController: ChartViewDelegate {

    func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
        // Do something on selection
    }

}

extension MyViewController: MyChartViewDelegate {

    func chartValueNoLongerSelected(_ chartView: FlyLineChartView) {
        // Do something on deselection
    }
}
person DoesData    schedule 11.09.2018