22

scrollEnabledユーザーが MKMapView でピンチを開始すると、壊れやすいようです

1 本指でスクロールすることはまだできませんが、2 本指でズームインおよびズームアウトしながらスクロールすると、マップを移動できます。

私が試してみました :

  • をサブクラスMKMapKit化して、その中のスクロール ビューを無効にします。
  • –<code>mapView:regionWillChangeAnimated: を実装して中心を強制します。
  • 無効化scrollEnabled

しかし運がない。

MKMapViewでのみズームする確実な方法を誰か教えてもらえますか?そのため、中心点は常に中央に留まりますか?

4

6 に答える 6

31

次を使用して、ピンチ ジェスチャを自分で処理することができますUIPinchGestureRecognizer

最初にscrollEnabledzoomEnabledを設定NOし、ジェスチャ認識エンジンを作成します。

UIPinchGestureRecognizer* recognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self
                                                                                 action:@selector(handlePinch:)];
[self.mapView addGestureRecognizer:recognizer];

MKCoordinateSpanレコグナイザ ハンドラで、ズーム スケールに従って を調整します。

- (void)handlePinch:(UIPinchGestureRecognizer*)recognizer
{
    static MKCoordinateRegion originalRegion;
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        originalRegion = self.mapView.region;
    }    

    double latdelta = originalRegion.span.latitudeDelta / recognizer.scale;
    double londelta = originalRegion.span.longitudeDelta / recognizer.scale;

    // TODO: set these constants to appropriate values to set max/min zoomscale
    latdelta = MAX(MIN(latdelta, 80), 0.02);
    londelta = MAX(MIN(londelta, 80), 0.02);
    MKCoordinateSpan span = MKCoordinateSpanMake(latdelta, londelta);

    [self.mapView setRegion:MKCoordinateRegionMake(originalRegion.center, span) animated:YES];
}

これは Apple の実装のように完全には機能しないかもしれませんが、問題は解決するはずです。

于 2012-08-14T14:20:37.723 に答える
1

私はこれらの答えのどれにもあまり運がありませんでした. 私自身のピンチを行うことは、あまりにも衝突しました。通常のズームでは、自分のピンチでできるよりもズームインする場合がありました。

もともと、私は元のポスターとして次のようなことを試みました:

- (void) mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
    MKCoordinateRegion region = mapView.region;
    //...
    // adjust the region.center 
    //...
    mapView.region = region;
}

私が見つけたのは、それは効果がないということでした。また、プログラムでorNSLogを設定した場合でも、このメソッドが起動することを s で発見しました。これにより、「上記が無限に機能する場合、上記はありませんか?」という疑問が生じました。regioncenterCoordinate

したがって、ユーザーのズーム/スクロール/回転が発生している間、MapView は何らかの形で領域への変更を抑制または無視するという推測と仮説を立てています。仲裁に関する何かが、プログラムによる調整を無効にします。

それが問題である場合、おそらく重要なのは、regionDidChanged:通知の外で地域調整を取得することです。また、調整を行うと別の通知がトリガーされるため、いつ調整を中止するかを決定できることが重要です。これにより、次の実装にたどり着きました(ここでsubjectは、中央にとどまりたい中心座標を提供しています):

- (void) recenterMap {
    double latDiff = self.subject.coordinate.latitude self.mapView.centerCoordinate.latitude;
    double lonDiff = self.subject.coordinate.longitude - self.mapView.centerCoordinate.longitude;
    BOOL latIsDiff = ABS(latDiff) > 0.00001;
    BOOL lonIsDiff = ABS(lonDiff) > 0.00001;
    if (self.subject.isLocated && (lonIsDiff || latIsDiff)) {
        [self.mapView setCenterCoordinate: self.subject.coordinate animated: YES];
    }
}

- (void) mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
    if (self.isShowingMap) {
        if (self.isInEdit) {
            self.setLocationButton.hidden = NO;
            self.mapEditPrompt.hidden = YES;
        }
        else {
            if (self.subject.isLocated) { // dispatch outside so it will happen after the map view user events are done
                 dispatch_after(DISPATCH_TIME_NOW, dispatch_get_main_queue(), ^{
                    [self recenterMap];
                });
            }
        }
    }
}

スライドバックの遅延はさまざまですが、実際にはかなりうまく機能します. そして、それが起こっている間、マップの相互作用を Apple 風のままにします。

于 2015-05-14T00:32:45.143 に答える
1

–mapView:regionWillChangeAnimated:マップ ビューのデリゲートにorを実装–mapView:regionDidChangeAnimated:して、マップが常に好みの場所の中心に配置されるようにしてください。

于 2012-08-06T15:46:15.700 に答える
1

これについては以前に読んだことがありますが、実際に試したことはありません。境界のある MKMapView に関するこの記事をご覧ください。2 つのデリゲート メソッドを使用して、ビューがユーザーによってスクロールされたかどうかを確認します。

http://blog.jamgraham.com/blog/2012/04/29/adding-boundaries-to-mkmapview

この記事では、あなたが試したものと同様のアプローチについて説明しているため、既に見つけてしまった場合は申し訳ありません。

于 2012-08-09T13:48:53.237 に答える
1

私はこれを試してみましたが、うまくいきます。

最初にプロパティを作成します。

var originalCenter: CLLocationCoordinate2D?

次に、regionWillChangeAnimated で、このイベントが UIPinchGestureRecognizer によって引き起こされているかどうかを確認します。

func mapView(mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
    let firstView = mapView.subviews.first
    if let recognizer = firstView?.gestureRecognizers?.filter({ $0.state == .Began || $0.state == .Ended }).first as? UIPinchGestureRecognizer {
        if recognizer.scale != 1.0 {
            originalCenter = mapView.region.center
        }
    }
}

次に、regionDidChangeAnimated で、ピンチ ジェスチャによって領域が変更された場合は、元の領域に戻ります。

func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    if let center = originalCenter {
        mapView.setRegion(MKCoordinateRegion(center: center, span: mapView.region.span), animated: true)
        originalCenter = nil
        return
    }
// your other code 
}
于 2016-01-23T01:56:56.587 に答える