39

マップにいくつかのMKA注釈(およびそれらに対応するビュー)があり、非常に混雑することがあります。現在、私のアプリのアノテーションには2つの種類があります。1つは元の場所にとどまるようにバインドされているものもあれば、時間の経過とともに移動するものもあります。視覚的に安定したものを背景に置き、動くものは常に前を通過するようにしたいと思います。

おそらく、マップに最近追加された注釈は、最終的には前面(または少なくとも最後部)になると思われるかもしれませんが、これはルールではないようです。私の知る限り、最初にすべての非移動アノテーションを作成して追加し、次にいくつかの新しくインスタンス化された移動アノテーションを追加しますが、それらの多く(すべてではありませんが!)は、永続的にストックされたままのアノテーションの下に描画されます。

興味深いことに、時間が経ち、新しい移動アノテーションが作成されると、すべての移動アノテーションオブジェクトが、非移動パーツがすでにマップに追加された後にのみ作成された場合でも、最初のアノテーションよりも上に引き寄せられる傾向があります。

マップ上の注釈ビューのこの奇妙な自然な順序を変更するトリックを知っている人はいますか?Map Kit APIを検索しようとしましたが、そのようなことは話されていないようです。

4

7 に答える 7

40

さて、MKMapViewDelegateのソリューション使用メソッドについては


- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views
 

このメソッドでは、MapKitViewに追加された後にAnnotationViewを再配置する必要があります。したがって、コードは次のようになります。


- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
   for (MKAnnotationView * annView in views) {
      TopBottomAnnotation * ann = (TopBottomAnnotation *) [annView annotation];
      if ([ann top]) {
         [[annView superview] bringSubviewToFront:annView];
      } else {
         [[annView superview] sendSubviewToBack:annView];
      }
   }

}

これは私のために働きます。

于 2009-07-31T16:09:00.423 に答える
28

iOS 11では、の実装により、またはdisplayPriorityを使用するすべてのソリューションが壊れました。bringSubviewToFrontzPosition

注釈ビューのCALayerをオーバーライドすると、OSからzPositionの制御に取り組むことができます。

class AnnotationView: MKAnnotationView {

    /// Override the layer factory for this class to return a custom CALayer class
    override class var layerClass: AnyClass {
        return ZPositionableLayer.self
    }

    /// convenience accessor for setting zPosition
    var stickyZPosition: CGFloat {
        get {
            return (self.layer as! ZPositionableLayer).stickyZPosition
        }
        set {
            (self.layer as! ZPositionableLayer).stickyZPosition = newValue
        }
    }

    /// force the pin to the front of the z-ordering in the map view
   func bringViewToFront() {
        superview?.bringSubviewToFront(toFront: self)
        stickyZPosition = CGFloat(1)
    }

    /// force the pin to the back of the z-ordering in the map view
   func setViewToDefaultZOrder() {
        stickyZPosition = CGFloat(0)
    }

}

/// iOS 11 automagically manages the CALayer zPosition, which breaks manual z-ordering.
/// This subclass just throws away any values which the OS sets for zPosition, and provides
/// a specialized accessor for setting the zPosition
private class ZPositionableLayer: CALayer {

    /// no-op accessor for setting the zPosition
    override var zPosition: CGFloat {
        get {
            return super.zPosition
        }
        set {
            // do nothing
        }
    }

    /// specialized accessor for setting the zPosition
    var stickyZPosition: CGFloat {
        get {
            return super.zPosition
        }
        set {
            super.zPosition = newValue
        }
    }
}
于 2018-01-25T23:23:07.983 に答える
11

次の場所で注釈ビューレイヤーのzPosition(annotationView.layer.zPosition)を設定してみてください。

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views;
于 2013-05-03T10:40:20.620 に答える
5

スウィフト3:

APIからピンの場所を取得しましたが、同様の問題が発生していましたが、一番上にある必要のあるピンはそうではありませんでした。私はこのようにそれを解決することができました。

var count = 0 // just so we don't get the same index in bottom pins
func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {  
    for view in views {
        view.layer.zPosition = CGFloat(count)
    }
    count += 1
    if count > 500 {
        count = 250 // just so we don't end up with 999999999999+ as a value for count, plus I have at least 30 pins that show at the same time and need to have lower Z-Index values than the top pins. 
    }

}

お役に立てれば

于 2016-12-05T21:06:56.770 に答える
4

デリゲート機能では、ピンを選択して強制的に上に配置できます。

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?` {
    ...
    if my annotation is the special one {
        annotationView.isSelected = true
    }
    ...
}
于 2019-02-18T01:32:27.970 に答える
2

この注釈ビューの並べ替えにより、クリックしたときにポップアップするコールアウトがすべての注釈の上に表示されなくなることがわかりました。andの代わりにbringSubviewToFrontandsendSubviewToBackを使用するように改良してみましたが、2番目の引数はリストの最初のannotationViewです。これにより、前後の散乱がはるかに少なくなるように見えますが、一部の注釈の下にコールアウトがポップアップ表示されます。insertSubview:aboveSubviewinsertSubview:belowSubview:

于 2009-11-05T14:21:11.010 に答える
0

私は本当にこれを行う必要がありました、そして(現在の)答えのどれも信頼できる実装を提供するようには見えませんでした。それらはある程度機能しましたが、マップのパン、注釈の選択、またはズームインにより、順序が再び混乱する可能性があります。

最終的な、正常に動作するソリューションはそれほど簡単ではなかったので、ここで行った手順の概要を説明します。を使用する注釈の順序MKMapViewは、追加された順序、またはオーバーライドされたannotationsプロパティの順序さえも尊重しません。それで...


手順

•作成•すべてのフレームで、レイヤーzPositionと、スーパービューの配列内のビューの順序の両方CADisplayLink
を使用して注釈を並べ替えます。 •ビューが選択されている場合は、順序付けスキームの前面にプロモートします 。•注釈をタップすると、すでに変更が加えられているにもかかわらず、内部の順序付けが引き続き尊重されます。これに対抗するには、次を追加し ます。•デリゲートオブジェクトのメソッドで、選択したアノテーションが希望どおりかどうかを確認します 。•アノテーションに対してヒットテストを自分で実行し、独自の順序で正しい/優先度の高いアノテーションを把握できます。考慮に入れる •選択した注釈が正しければ、すばらしい。そうでない場合は、を使用して正しい注釈を手動で選択しますsubviews

MKMapViewMKMapViewDelegate
mapView:didSelect:

selectAnnotation:animated:


そして、あなたはそれを持っています。上記の方法はうまく機能しているようで、この各フレームを実行することによるパフォーマンスへの影響はそれほど悪くありません。MapBoxへの切り替えも検討できます。これは注釈の順序付けをサポートしていると思いますが、さまざまな理由から、これが常にオプションであるとは限りません。

于 2017-09-15T01:54:05.377 に答える