Custom font for callout MKAnnotationView

Fortunately, the standard MKAnnotationView view for MKAnnotationView meets our needs — title , subtitle , leftCalloutAccessoryView and rightCalloutAccessoryView .

Unfortunately, we use custom fonts in our application and would like to extend these custom fonts to these callouts.

MKAnnotationView does not provide a standard way of doing this.

How can I use my own font in the MKAnnotation callout MKAnnotation ?

+2
source share
2 answers

If you need a special font, you need to subclass MKAnnotationView , but you do not need to recreate all the behavior that you get for free with the standard MKAnnotationView . It is actually quite easy.

  • Subclass MKAnnotationView
  • Override -layout subviews
  • When MKAnnotationView selected, the MKAnnotationView is added as a preview. Therefore, we can recursively scroll through the subqueries of our subclass and find the UILabel that we want to change.
  • What is it!

The only drawback of this method is that you can see that the leader adjusts its size if your font is smaller or larger than the standard system font that he expected. It would be great if all the settings were made before they were presented to the user.

 // elsewhere, in a category on UIView. // thanks to this answer: http://stackoverflow.com/a/25877372/607876 // typedef void(^ViewBlock)(UIView *view, BOOL *stop); @interface UIView (Helpers) - (void)loopViewHierarchy:(ViewBlock)block; @end @implementation UIView (Helpers) - (void)loopViewHierarchy:(ViewBlock)block { BOOL stop = false; if (block) { block(self, &stop); } if (!stop) { for (UIView* subview in self.subviews) { [subview loopViewHierarchy:block]; } } } @end // then, in your MKAnnotationView subclass // @implementation CustomFontAnnotationView - (void)layoutSubviews { // MKAnnotationViews only have subviews if they've been selected. // short-circuit if there nothing to loop over if (!self.selected) { return; } [self loopViewHierarchy:^(UIView *view, BOOL *stop) { if ([view isKindOfClass:[UILabel class]]) { *stop = true; ((UILabel *)view).font = {custom_font_name}; } }]; } @end 

I checked the view tree by first subclassing MKAnnotationView and setting a breakpoint in my overridden -layoutSubviews . In the debugger, I released po [self recursiveDescription] . Make sure you turn off the breakpoint when your map loads first, because, as mentioned above, MKAnnotationView do not have subzones until they are selected. Before making a choice, turn on a breakpoint, tap your pin, break and print the presentation tree. You will see UILabel at the very bottom of the tree.

+1
source

Since I need a Swift version - here it is. In addition, you must call setNeedsLayout () on didAddSubview (), because otherwise, when you deselect and re-select the annotation, layoutSubviews () is not called, and the callout has its old font.

 // elsewhere, in a category on UIView. // thanks to this answer: http://stackoverflow.com/a/25877372/607876 typealias ViewBlock = (_ view: UIView) -> Bool extension UIView { func loopViewHierarchy(block: ViewBlock?) { if block?(self) ?? true { for subview in subviews { subview.loopViewHierarchy(block: block) } } } } // then, in your MKAnnotationView subclass class CustomFontAnnotationView: MKAnnotationView { override func didAddSubview(_ subview: UIView) { if isSelected { setNeedsLayout() } } override func layoutSubviews() { // MKAnnotationViews only have subviews if they've been selected. // short-circuit if there nothing to loop over if !isSelected { return } loopViewHierarchy { (view: UIView) -> Bool in if let label = view as? UILabel { label.font = labelFont return false } return true } } } 
+6
source

Source: https://habr.com/ru/post/981765/


All Articles