将Mapbox标注视图正确定位在顶部

时间:2017-12-06 13:04:20

标签: ios mapbox swift4 mapbox-gl callout

我想将标注框位置放在位置标记的顶部,该位置标记是框左上方的黑色标记。

以下是我目前的代码:

import Mapbox
import UIKit

class CustomCalloutView: UIView, MGLCalloutView {
var representedObject: MGLAnnotation

// Allow the callout to remain open during panning.
let dismissesAutomatically: Bool = false
let isAnchoredToAnnotation: Bool = true

// https://github.com/mapbox/mapbox-gl-native/issues/9228
override var center: CGPoint {
    set {
        var newCenter = newValue
        newCenter.y = newCenter.y - bounds.midY
        super.center = newCenter
    }
    get {
        return super.center
    }
}

lazy var leftAccessoryView = UIView() /* unused */
lazy var rightAccessoryView = UIView() /* unused */

weak var delegate: MGLCalloutViewDelegate?

let tipHeight: CGFloat = 10.0
let tipWidth: CGFloat = 20.0

let mainBody: UIView

required init(representedObject: MGLAnnotation) {
    self.representedObject = representedObject
    self.mainBody = CustomDetailsView().loadNib()

    super.init(frame: .zero)

    backgroundColor = .clear
    autoresizesSubviews = true
    mainBody.backgroundColor = .white
    mainBody.layer.cornerRadius = 4.0

    addSubview(mainBody)
}

required init?(coder decoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}


// MARK: - MGLCalloutView API
func presentCallout(from rect: CGRect, in view: UIView, constrainedTo constrainedView: UIView, animated: Bool) {
    if !representedObject.responds(to: #selector(getter: MGLAnnotation.title)) {
        return
    }

    view.addSubview(self)
    mainBody.sizeToFit()

    // Prepare our frame, adding extra space at the bottom for the tip
    let button = UIButton(type: .system)
    let frameWidth = button.bounds.size.width
    let frameHeight = button.bounds.size.height + tipHeight
    let frameOriginX = rect.origin.x + (rect.size.width/2.0) - (frameWidth/2.0)
    let frameOriginY = rect.origin.y - frameHeight
    frame = CGRect(x: frameOriginX, y: frameOriginY, width: frameWidth, height: frameHeight)

    if animated {
        alpha = 0

        UIView.animate(withDuration: 0.2) { [weak self] in
            self?.alpha = 1
        }
    }
}

func dismissCallout(animated: Bool) {
    if (superview != nil) {
        if animated {
            UIView.animate(withDuration: 0.2, animations: { [weak self] in
                self?.alpha = 0
                }, completion: { [weak self] _ in
                    self?.removeFromSuperview()
            })
        } else {
            removeFromSuperview()
        }
    }
}

// MARK: - Callout interaction handlers

func isCalloutTappable() -> Bool {
    if let delegate = delegate {
        if delegate.responds(to: #selector(MGLCalloutViewDelegate.calloutViewShouldHighlight)) {
            return delegate.calloutViewShouldHighlight!(self)
        }
    }
    return false
}

func calloutTapped() {
    if isCalloutTappable() && delegate!.responds(to: #selector(MGLCalloutViewDelegate.calloutViewTapped)) {
        delegate!.calloutViewTapped!(self)
    }
}

// MARK: - Custom view styling

override func draw(_ rect: CGRect) {
    // Draw the pointed tip at the bottom
    let fillColor : UIColor = .white

    let tipLeft = rect.origin.x + (rect.size.width / 2.0) - (tipWidth / 2.0)
    let tipBottom = CGPoint(x: rect.origin.x + (rect.size.width / 2.0), y: rect.origin.y + rect.size.height)
    let heightWithoutTip = rect.size.height - tipHeight - 1

    let currentContext = UIGraphicsGetCurrentContext()!

    let tipPath = CGMutablePath()
    tipPath.move(to: CGPoint(x: tipLeft, y: heightWithoutTip))
    tipPath.addLine(to: CGPoint(x: tipBottom.x, y: tipBottom.y))
    tipPath.addLine(to: CGPoint(x: tipLeft + tipWidth, y: heightWithoutTip))
    tipPath.closeSubpath()

    fillColor.setFill()
    currentContext.addPath(tipPath)
    currentContext.fillPath()
}

}

enter image description here

我似乎无法找到一种让标注位于引脚顶部的方法。有没有办法通过当前的代码设置获得相同的结果?

1 个答案:

答案 0 :(得分:1)

我最后不得不对使用下面的代码段定位mainBody.frame的方式进行一些更改:

// Prepare our frame, adding extra space at the bottom for the tip
        let frameWidth = mainBody.bounds.size.width
        let frameHeight = mainBody.bounds.size.height + tipHeight
        let frameOriginX = rect.origin.x + (rect.size.width/2.0) - (frameWidth/2.0)
        let frameOriginY = rect.origin.y - frameHeight
        self.frame = CGRect(x: frameOriginX, y: frameOriginY, width: frameWidth, height: frameHeight)
        mainBody.frame.size.width = frameWidth
        mainBody.frame.size.height = frameHeight - tipHeight