如何使用自动布局在 MKAnnotation 中显示多行?

Posted

技术标签:

【中文标题】如何使用自动布局在 MKAnnotation 中显示多行?【英文标题】:how to show multiple lines in MKAnnotation with autolayout? 【发布时间】:2016-10-24 09:19:07 【问题描述】:

我正在使用 mapkit 如何在 MKAnnotation 视图中使用多行。

那里的每个注释都有标题和副标题。 我如何在 auto layout 的帮助下显示多行副标题?

我找到了答案。请尝试我的答案。我们只需要在

中做代码
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
   


这里我展示了如何将自动布局与 MKAnnotation 一起使用。

【问题讨论】:

How to display 2 lines of text for subtitle of MKAnnotation and change the image for the button on the right?的可能重复 @Jeyamahesan 我只发布这个问题是为了说明如何使用自动布局和 mkannotation。 您已经回答了 (***.com/a/39160132/6176024) 类似类型的问题,并且在此答案中给出了相同的答案和代码 sn-p。 @Jeyamahesan 没有人关注这个答案。 buz那个问题在2011年发布。那个时候自动布局不可用。我只用我的代码帮助其他人。 【参考方案1】:

借助自动布局,我们可以在 MKAnnotation 视图中显示多行

这很简单。

目标c

 - (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation 

        if ([annotation isKindOfClass:[MKUserLocation class]])
            return nil;
        if ([annotation isKindOfClass:[CustomAnnotation class]]) 
            CustomAnnotation *customAnnotation = (CustomAnnotation *) annotation;

            MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"CustomAnnotation"];

            if (annotationView == nil)
                annotationView = customAnnotation.annotationView;
            else
                annotationView.annotation = annotation;

            //Adding multiline subtitle code 

            UILabel *subTitlelbl = [[UILabel alloc]init];
            subTitlelbl.text = @"sri ganganagar this is my home twon.sri ganganagar this is my home twon.sri ganganagar this is my home twon.  ";

            annotationView.detailCalloutAccessoryView = subTitlelbl;

            NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:subTitlelbl attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationLessThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:150];

             NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:subTitlelbl attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:0];
            [subTitlelbl setNumberOfLines:0];
            [subTitlelbl addConstraint:width];
            [subTitlelbl addConstraint:height];




            return annotationView;
         else
            return nil;
    

输出

对于斯威夫特

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? 

        let identifier = "MyPin"

        if annotation.isKindOfClass(MKUserLocation) 
            return nil
        

        var annotationView: MKPinAnnotationView? = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) as? MKPinAnnotationView

        if annotationView == nil 

            annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
            annotationView?.canShowCallout = true

              let label1 = UILabel(frame: CGRectMake(0, 0, 200, 21))
            label1.text = "Some text1 some text2 some text2 some text2 some text2 some text2 some text2"
             label1.numberOfLines = 0
              annotationView!.detailCalloutAccessoryView = label1;

            let width = NSLayoutConstraint(item: label1, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.LessThanOrEqual, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 200)
            label1.addConstraint(width)


            let height = NSLayoutConstraint(item: label1, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 90)
            label1.addConstraint(height)



         else 
            annotationView!.annotation = annotation
        
        return annotationView
    



这里我使用 NSLayoutConstraint

我以编程方式创建标签。在其上添加约束,然后在MKAnnotationView的detailCalloutAccessoryView中添加标签。

【讨论】:

【参考方案2】:

添加多行的扩展:

import MapKit // must import MapKit for MKAnnotationView to get recognized

extension MKAnnotationView 

    func loadCustomLines(customLines: [String]) 
        let stackView = self.stackView()
        for line in customLines 
            let label = UILabel()
            label.text = line
            stackView.addArrangedSubview(label)
        
        self.detailCalloutAccessoryView = stackView
    



    private func stackView() -> UIStackView 
        let stackView = UIStackView()
        stackView.axis = .vertical
        stackView.distribution = .fillEqually
        stackView.alignment = .fill
        return stackView
    

使用:

view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
view.loadCustomLines(customLines: ["qqqq", "wwww", "eee"])

【讨论】:

很好的解决方案!【参考方案3】:

使用自动布局,您可以输入如下内容:

let subtitleLabel = UILabel()
subtitleLabel.text = "Location updated\n" + dateFormatter.string(from: date)
subtitleLabel.numberOfLines = 0
subtitleLabel.font = UIFont.systemFont(ofSize: 14)
subtitleLabel.textColor = .lightGray
subtitleLabel.setContentCompressionResistancePriority(.required, for: .vertical)

annotationView?.detailCalloutAccessoryView = subtitleLabel

【讨论】:

使用setContentCompressionResistancePriority() 似乎是执行此操作的最短方法。此外,可以使用动态类型支持 subtitleLabel.font = UIFont.preferredFont(forTextStyle: .body); subtitleLabel.adjustsFontForContentSizeCategory = true【参考方案4】:

5 个步骤

我创建了一个标签并将其添加到 annotationView?.detailCalloutAccessoryView 属性中(第 5 步)。我还将标签的文本设置为 annotation.subtitle 文本(第 2 步和第 4 步)和 .numberOfLines = 0

步骤在代码上方的cmets中

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? 

    if annotation.isKindOfClass(MKUserLocation) 
        return nil
    

    let reuseIdentifier = "reuseIdentifier"

    var annotationView = mapView.mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier) as? MKPinAnnotationView

    if annotationView == nil 

        annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)

        // 1. set the annotationView's canShowCallout property to true
        annotationView?.canShowCallout = true

        // 2. get the subtitle text from the annontation's subtitle property
        let subtitleText = annotation.subtitle ?? "you have no subtitle"

        // 3. create a label for the subtitle text
        let subtitleLabel = UILabel()
        subtitleLabel.translatesAutoresizingMaskIntoConstraints = false

        // 4. set the subtitle's text to the label's text property and number of lines to 0
        subtitleLabel.text = subtitleText
        subtitleLabel.numberOfLines = 0

        // 5. set the annotation's detailCalloutAccessoryView property to the subtitleLabel
        annotationView?.detailCalloutAccessoryView = subtitleLabel

     else 
        annotationView!.annotation = annotation
    

    return annotationView

【讨论】:

【参考方案5】:

如果你想让多标签点击去某个地方,你需要: 1- 在 AnnotationView 上以编程方式创建 UITapGestureRecognizer。 2-创建传递给手势选择器的函数。该函数采用 UIGestureRecognizer 类型的 sender 参数。有一个 if 语句,确保您将 canshowcallout 设置为 true,这样您就只在它显示时单击,以避免单击实际的 pin 本身。

所以就我而言,我遇到了这种情况。这可能会帮助某人: - 填充了不同位置的单元格的 tableView - 屏幕的上半部分是地图,显示您的每个位置的别针 - 当您单击表格视图或地图中的图钉时,地图中心本身并向您显示图钉标注视图,这是一个带有图片的小视图,并且如果名称位置很长以避免截断尾巴。 - 因为索引在我们的代码中到处都被传递和使用来确定点击了哪个位置,我不得不使用它来在点击位置的标注中显示正确的名称。 我遇到的问题是单击标签,因为我使用了 annotationView.detailCalloutAccessoryView = myLabel 。好像什么时候。您使用详细信息而不是右侧或左侧,即使从 controlTapped 地图委托功能也无法获得点击。所以我必须在我之前谈到的手势选择器功能中执行以下操作: 确保您正在做某种保护,或者如果让这些检查一起使用逗号。 - 通过 let tag = sender.view.tag 检查视图标签 - 获取视图为 MKPinAnnotationView: let view = sender.view as? MKPointAnnotationView - 检查标注以确保它首先显示:view.canShowCallout - 然后在 if 或 guard 的花括号内,让 index = tag 并将索引传递给我的函数,该函数在视图上执行操作以在单击 annotationView 后转到本机苹果地图。

毕竟在 annotationFor View 委托函数中,正如我之前所说,将此函数传递给手势识别器选择器

【讨论】:

【参考方案6】:
let label1 = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 21))
label1.text = "Some text1 some text2 some text2 some text2 some text2 some text2 some text2"
label1.numberOfLines = 0
annotationView!.detailCalloutAccessoryView = label1;

let width = NSLayoutConstraint(item: label1, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.lessThanOrEqual, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 200)
        label1.addConstraint(width)


let height = NSLayoutConstraint(item: label1, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 90)
        label1.addConstraint(height)

【讨论】:

以上是关于如何使用自动布局在 MKAnnotation 中显示多行?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Drupal 的主分类页面中显​​示子术语?

如何在 Swift 中扩展 NSManagedObject 以包含 MKAnnotation?

在实现 MKAnnotation 时如何获取 pin 的标题和副标题?

MKAnnotation 的自定义图像

如何将 MKAnnotation Pin 一个一个丢掉?

如何在 Django 中显式重置模板片段缓存?