web-dev-qa-db-fra.com

iOS 8 MKAnnotationView rightCalloutAccessoryView mal aligné

Je suis encore assez novice en matière d'iOS en général et j'ai trouvé un problème lors du test de la compatibilité de notre application avec iOS 8. Dans iOS 7, tout fonctionnait bien, mais sur iOS 8, rightCalloutAccessoryView est mal aligné dans certaines circonstances.

Première capture d'écran: correctement aligné Correctly aligned

Deuxième capture d'écran: mauvais alignement Wrong alignment

Comme vous pouvez le voir, le problème se produit lorsque l'InfoWindow a un titre long. Mais ce n'était pas le cas sur iOS 7 et je n'ai rien trouvé mentionnant que cela a changé?

J'ai essayé de comprendre pourquoi et de trouver un moyen de résoudre ce problème, mais je n'ai rien trouvé pour l'instant. Est-ce résoluble par nous-mêmes ou devons-nous déposer un problème pour Apple?

Toute aide/idée serait très appréciée car je suis en quelque sorte dépassé par ce problème.

Code qui ajoute les MKAnnotationViews

- (MKAnnotationView *)viewForStation:(id<MKAnnotation>)annotation {
      static NSString *stationIdentifier = @"stao";
      MKAnnotationView *annotationView = [self.mapView dequeueReusableAnnotationViewWithIdentifier:stationIdentifier];
      if (annotationView == nil) {
          annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation           reuseIdentifier:stationIdentifier];
          annotationView.image = [UIImage bundleImageNamed:PIN_IMAGE];
          annotationView.canShowCallout = YES;
          annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
      }
      return annotationView;
}

Comme vous pouvez être intéressé, j'ai (tout à l'heure) également ajouté cette question à la section iOS 8 Beta sur Apple.developer.com: https://devforums.Apple.com/thread/242282?tstart=

Si j'obtiens une réponse ici ou sur Apple.developer.com, je la refléterai afin que nous puissions la trouver sur les deux sites

38
byemute

J'ai résolu ce problème en définissant le masque de redimensionnement automatique pour corriger le bogue vertical et frame.size.width pour le bogue horizontal

UIButton* infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[infoButton setFrame:CGRectMake(0, 0, CGRectGetWidth(infoButton.frame)+10, CGRectGetHeight(infoButton.frame))];
[infoButton setAutoresizingMask:UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleTopMargin];
[annotationView setRightCalloutAccessoryView:infoButton];
18
Meerschwein Bob

Aussi affreux que ça, mais j'ai réussi à trouver une solution à ce problème.

Définissez la hauteur de la vue des accessoires sur une valeur égale à la hauteur de la vue de détail. J'ai utilisé des valeurs codées en dur:

  • pour les cibles iOS 7: 45,0 px
  • pour les cibles iOS 8: 54,0 px

(Vous avez probablement remarqué que la hauteur de la vue de détail des annotations par défaut est plus grande dans iOS 8 que dans iOS 7).

Dans votre code, ce serait:

- (MKAnnotationView *)viewForStation:(id<MKAnnotation>)annotation {
  static NSString *stationIdentifier = @"stao";
  MKAnnotationView *annotationView = [self.mapView dequeueReusableAnnotationViewWithIdentifier:stationIdentifier];
  if (annotationView == nil) {
      annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation 
                                                    reuseIdentifier:stationIdentifier];
      annotationView.image = [UIImage bundleImageNamed:PIN_IMAGE];
      annotationView.canShowCallout = YES;

      UIButton *detailButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];

      // N.B. In production code, you would need a more generic way to adjust 
      // height values instead of hard-coding values based on NSFoundationVersionNumber...

      CGFloat height = (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1) ? 55.f : 45.f;

      detailButton.frame = CGRectMake(0.f, 0.f, 32.f, height);
      annotationView.rightCalloutAccessoryView = detailButton;
  }
  return annotationView;
}

De plus, d'après ce que j'ai vu jusqu'à présent, si vous spécifiez à la fois les vues d'accessoires gauche et droite, vous devrez définir les deux leurs hauteurs à la même valeur pour obtenir la bonne alignement. Espérons que ce problème sera résolu dans les versions ultérieures d'iOS pour éviter d'écrire ce type de code ...

10
octy

Salut, j'avais exactement le même problème, voici ce que j'ai fait pour le résoudre:

Il semble que la vue Légende pose problème lors de l'affichage du texte du titre MKAnnotation lorsqu'il est trop long. Même à partir de votre capture d'écran, vous pouvez voir que le problème ne se produit que lorsque le titre a été tronqué et que les points de suspension sont ajoutés. Donc, la MKAnnotation standard ne présente pas correctement les vues et c'est un bug dans iOS8.

En attendant, vous pouvez créer votre propre légende personnalisée en suivant les étapes ici .

Je pensais que c'était trop de travail pour ce dont j'avais besoin, alors j'ai juste coupé la chaîne de titre et ajouté les points de suspension pour l'empêcher d'essayer de se faire lui-même. (Pas idéal mais c'est une solution rapide, et le texte serait quand même tronqué)

if (locTitle.length > 15) 
{
    locTitle = [NSString stringWithFormat:@"%@...", [locTitle substringToIndex:14]];
}
3
Iain Smith

Pour l'instant, je cache rightCalloutAccessoryView avec

pin.rightCalloutAccessoryView.frame = CGRectZero;

et cliquez sur la vue d'annotation qui fonctionne toujours, juste aucun bouton sur le côté droit. Testé sur iOS7 et iOS8, pas sûr d'iOS6.

0
kolyancz

J'ai mis le mien au travail en définissant le délégué de ma vue de carte avant d'ajouter l'annotation et je n'ai rien eu à changer dans la del.

En partant de ce qui suit:

    self.mapView = [[MKMapView alloc] init];
    NGAAnnotation *annotation = [[NGAAnnotation alloc] init];
    annotation.coordinate = coordinates;
    annotation.title = self.project.name;

    [self.mapView addAnnotation:annotation];
    self.mapView.delegate = self;

À:

    self.mapView = [[MKMapView alloc] init];
    NGAAnnotation *annotation = [[NGAAnnotation alloc] init];
    annotation.coordinate = coordinates;
    annotation.title = self.project.name;

    self.mapView.delegate = self;
    [self.mapView addAnnotation:annotation];

Fixé pour moi. J'ai remarqué que la méthode déléguée est appelée lorsque l'annotation est ajoutée, donc si le délégué n'est pas défini avant que vous ajoutiez l'annotation, elle ne sera pas appelée.

0
Jose Castellanos

Dans Swift 3:

let infoButton = UIButton(type: .detailDisclosure)
annotationView.rightCalloutAccessoryView = infoButton
0
Kaptain

Une curiosité que j'ai remarquée était que ma première légende à afficher alignerait correctement les vues des accessoires, mais pas les sélections suivantes. J'ai ajouté un appel à [view setNeedsLayout] avant de retourner la vue d'annotation retirée de la file d'attente, et tout a recommencé à s'aligner correctement.

Sans y consacrer plus de temps, ma meilleure supposition est qu'une nouvelle mise en page n'est pas déclenchée pour une vue qui a été retirée de la file d'attente car la hiérarchie des vues n'a pas changé.

Je recommande fortement de soumettre un radar pour ce problème. Il ne devrait pas être nécessaire d'implémenter des solutions de contournement pour un tel cas d'utilisation standard.

ÉDITER:

Bien que cela semble toujours meilleur dans de nombreux cas, je rencontre toujours ce problème avec des annotations dont le titre est suffisamment long pour être tronqué.

0
gyratory circus