35

UIPageViewController のパン ジェスチャ レコグナイザーを無効にしようとしています。

iOS 5 では、それらをループして無効にすることができます。

for (UIGestureRecognizer* recognizer in self.pageViewController.gestureRecognizers) {
    if ([recognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
        recognizer.enabled = NO;
    }
}

UIPageViewControllerTransitionStyleScroll を使用する iOS 6 では、Page View Controller から返されるジェスチャ レコグナイザーはありません。

明確化

これは次のように要約できます。

self.pageViewController.gestureRecognizers = 0 UIPageViewController の遷移スタイルがスクロールに設定されているため、ジェスチャ認識エンジンにアクセスできません。

これを回避する方法はありますか?curl トランジションは正常に動作するので、間違ったことはしていないと思います。

4

12 に答える 12

32

UIPageViewController.h でこれを見つけました:

// トランジション スタイルが 'UIPageViewControllerTransitionStylePageCurl' の場合にのみ設定されます。 @property(nonatomic, readonly) NSArray *gestureRecognizers;

したがって、バグではありません。設計上、スクロール スタイルが設定されている場合、pageViewController はジェスチャ認識機能を取得しません。

于 2012-11-10T17:50:21.993 に答える
28

ページビューコントローラーのサブビューでユーザーの操作をいつでも無効にすることができます:

for (UIScrollView *view in self.pageViewController.view.subviews) {
    if ([view isKindOfClass:[UIScrollView class]]) {
        view.scrollEnabled = NO;
    }
}
于 2013-07-11T00:09:27.370 に答える
26

この動作については、レーダーにバグが報告されています。したがって、Apple が修正するまで、これを解決する機会はないと思います。

One workaround that comes to my mind is laying a transparent subview on top of your UIPageViewController and add to it a UIPanGestureRecognizer to intercept that kind of gesture and not forward further. You could enable this view/recognizer when disabling the gesture is required.

I tried it with a combination of Pan and Tap gesture recognizers and it works.

This is my test code:

- (void)viewDidLoad {
  [super viewDidLoad];

   UIPanGestureRecognizer* g1 = [[[UIPanGestureRecognizer alloc] initWithTarget:self
                                                                      action:@selector(g1Pan:)] autorelease];
  [self.view addGestureRecognizer:g1];

  UITapGestureRecognizer* s1 = [[[UITapGestureRecognizer alloc] initWithTarget:self
                                                                      action:@selector(g1Tap:)] autorelease];

  [self.view addGestureRecognizer:s1];

  UIView* anotherView = [[[UIView alloc]initWithFrame:self.view.bounds] autorelease];
  [self.view addSubview:anotherView];

  UIPanGestureRecognizer* g2 = [[[UIPanGestureRecognizer alloc] initWithTarget:self
                                                                      action:@selector(g2Pan:)] autorelease];
  [anotherView addGestureRecognizer:g2];

}

When g2 is enabled, it will prevent g1 from being recognized. On the other hand, it will not prevent s1 from being recognized.

I understand this is hack, but in the face of a seeming bug in UIPageViewController (at least, actual behavior is blatantly different from what the reference states), I cannot see any better solution.

于 2012-11-08T16:48:21.230 に答える
19

UIPageViewController ヘッダー ファイルによると、データソースが nil の場合、ジェスチャー駆動のナビゲーションは無効になります。

したがって、スワイプを無効にする場合は datasource を nil に設定し、スワイプを有効にする場合はデータ ソースをリセットします。

すなわち

// turns off paging
pageViewController.datasource = nil

// turns on paging
pageViewController.datasource = self;
于 2013-11-13T20:25:23.627 に答える
9

UIPageViewController から UIScrollview を介して UIPanGestureRecognizer にアクセスできます。

for (UIView *view in self.pageController.view.subviews) {
    if ([view isKindOfClass:[UIScrollView class]])
    {
        UIScrollView *scrollView = (UIScrollView *)view;

        UIPanGestureRecognizer* panGestureRecognizer = scrollView.panGestureRecognizer;
        [panGestureRecognizer addTarget:self action:@selector(move:)];
    }
}
于 2013-10-09T08:00:24.670 に答える
2

UIPageViewControllers UIPanGestureRecognizer が他の PanGestureRecognizer からすべてのイベントを食べたり飲み込んだりしている場合 (例: スライド メニュー)。

Bernies ソリューションを簡単に拡張して、UIScrollViews PanGestureRecognizer に他の Recognizer の失敗を要求させることができます。このようなもの:

for (UIView *view in pageViewController.view.subviews) {
    if ([view isKindOfClass:[UIScrollView class]]){
        UIScrollView *scrollView = (UIScrollView *)view;

        [scrollView.panGestureRecognizer requireGestureRecognizerToFail:otherRecognizer];
    }
}

このように、スクロールする PanGestureRecognizer は、意図した領域でのみ起動します。

これは、Apple が UIPageViewControllers の UIScrollView の内部使用を変更しないことを要求しているため、将来的には最善の解決策ではない可能性があります。しかし...

于 2014-01-15T15:03:24.270 に答える
1

ジェスチャ認識機能を見つけて削除できると仮定すると、非常に脆弱です。Apple が UIPageViewController の実装を使用してアプリに機能を提供する方法について、前提知識を使用しています。これが変更された場合 (iOS 5 と iOS 6 の間など)、コード アプリは予期しない方法で動作し始めます。これは、プライベート API を使用するようなものです。次の OS リリースで動作するという保証はありません。

于 2012-11-08T17:01:52.863 に答える
1

KVC (Key Value Coding) メソッドを使用してレコグナイザーにアクセスするとどうなりますか? (私は現時点でこれをテストできる場所ではありません。)

簡単なテストとして、gestureRecognizer の数を取得することがあります。

[self.pageViewController countOfKey:@"gestureRecognizers"];

それが機能する場合は、認識エンジンの配列を取得するためにさらに進んでください。

NSArray *recognizers = [self.pageViewController
                        mutableArrayValueForKey:@"gestureRecognizers"];

薄いけど多分…

編集:最終的にテストできました。以下を使用しました:

NSArray *pvcGRsNoKVC = [[NSArray alloc]
                       initWithArray:self.pageViewController.gestureRecognizers];
NSArray *viewGRsNoKVC = [[NSArray alloc] initWithArray:self.view.gestureRecognizers];

NSArray *pvcGRsKVC = [[NSArray alloc]
                     initWithArray:[self.pageViewController valueForKey:@"gestureRecognizers"]];
NSArray *viewGRsKVC = [[NSArray alloc]
                      initWithArray:[self.view valueForKey:@"gestureRecognizers"]];

違いはありませんでした。curl スタイルは両方の方法でうまく機能しました。スクロール スタイルは、配列を nil ではなく空として示しました。ただし、興味深いのは、ビューもレコグナイザーを放棄しなかったことです-スクロール機能はありますが、少なくともパンレコグナイザーが必要です...

于 2012-11-08T17:21:30.340 に答える
-1

のデリゲート メソッドを使用してUIGestureRecognizer、ジェスチャをキャッチして無効にすることができます。たとえば、次のデリゲート コールバックを使用できますgestureRecognizer:shouldReceiveTouch:。すべてのレコグナイザーにデリゲートを設定するようにしてください。

于 2012-10-27T23:49:42.673 に答える