I am drawing the lines using the following code. The line edges have dots and i want to show the tooltip when user click on the end dots. The code snippet is below,
override func drawRect(rect: CGRect) {
// Drawing code
UIColor.brownColor().set()
let context = UIGraphicsGetCurrentContext()
//CGContextSetLineWidth(context, 5)
CGContextMoveToPoint(context, 50, 50)
CGContextAddLineToPoint(context,100, 200)
CGContextStrokePath(context)
// now add the circle on at the line edges
var point = CGPoint(x:50 , y:50)
point.x -= 5.0/2
point.y -= 5.0/2
var circle = UIBezierPath(ovalInRect: CGRect(origin: point, size: CGSize(width: 5.0,height: 5.0)))
circle.fill()
point = CGPoint(x:100 , y:200)
point.x -= 5.0/2
point.y -= 5.0/2
circle = UIBezierPath(ovalInRect: CGRect(origin: point, size: CGSize(width: 5.0,height: 5.0)))
circle.fill()
}
It is currently displaying the following image,
and i want to show the tooltip like below,
Does anybody have an idea how will i recognise that this particular dot is clicked and also how will i show the tooltip. I am looking for a solution in swift.
Define a struct to hold points you have to touch, and the text to show:
struct TouchPoint {
var point: CGPoint // touch near here to show a tooltip
var tip: String // show this text when touched
}
then in the UIView
subclass where you define drawRect
, make somewhere to keep them:
var touchPoints: [TouchPoint] = [] // where we have to touch and what tooltip to show
drawRect
can be called many times, so start fresh each time:
override func drawRect(rect: CGRect) {
touchPoints = []
// ...
// add a touchPoint for every place to touch
touchPoints.append(TouchPoint(point: point, tip: "point 1"))
}
You need to detect taps on the UIView, so add a gesture recognizer by changing its initialisation:
required init?(coder aDecoder: NSCoder) {
// standard init for a UIView wiht an added gesture recognizer
super.init(coder: aDecoder)
addGestureRecognizer(UITapGestureRecognizer(target: self, action: Selector("touched:")))
}
then you need a method to see whether touches are near touchpoints, and to show the right tooltip:
func touched(sender:AnyObject) {
let tapTolerance = CGFloat(20) // how close to the point to touch to see tooltip
let tipOffset = CGVector(dx: 10, dy: -10) // tooltip offset from point
let myTag = 1234 // random number not used elsewhere
guard let tap:CGPoint = (sender as? UITapGestureRecognizer)?.locationInView(self) else { print("touched: failed to find tap"); return }
for v in subviews where v.tag == myTag { v.removeFromSuperview() } // remove existing tooltips
let hitPoints:[TouchPoint] = touchPoints.filter({CGPointDistance($0.point, to: tap) < tapTolerance}) // list of tooltips near to tap
for h in hitPoints { // for each tooltip to show
let f = CGRect(origin: h.point+tipOffset, size: CGSize(width: 100, height: 20)) // fixed size label :-(
let l = UILabel(frame: f)
l.tag = myTag // just to be able to remove the tooltip later
l.text = h.tip // draw the text
addSubview(l) // add the label to the view
}
}
func CGPointDistanceSquared(from: CGPoint, to: CGPoint) -> CGFloat { return (from.x - to.x) * (from.x - to.x) + (from.y - to.y) * (from.y - to.y) }
func CGPointDistance(from: CGPoint, to: CGPoint) -> CGFloat { return sqrt(CGPointDistanceSquared(from, to: to)) }
and that incidentally uses a new version of the +
operator to perform vector addition on CGPoint
:
func +(left: CGPoint, right: CGVector) -> CGPoint { return CGPoint(x: left.x+right.dx, y: left.y+right.dy) }
and that works OK for me. Extra tweaks would be to compute the UILabel size from the text string, and move the UILabel so it didn't run off the side of the UIView at the edges. Good Luck!