1

iPadアプリのメイン画面の上部にUIToolbarがあります。6つのUIBarButtonItemがあります。これらのアイテムのうち4つは、UIPopOversの表示をトリガーします。他の2つの項目は、別のビューに切り替えるか、現在のビューについて何かを変更します。

4つのUIPopOverのうち3つはタップされたUIBarButtonItemから表示され、4つ目は画面の中央に矢印なしで表示されます。

次の機能が欲しいのですが、うまくいきません。

  1. UIPopOversが表示されず、ユーザーがUIPopOverを生成するUIBarButtonItemsの1つをタップした場合、UIPopOverを表示します(非常に単純です。これが機能します)。
  2. UIPopOverが表示され、ユーザーがUIToolbarをタップしたら、そのUIPopOverを閉じます。(1回タップするUIGestureRecognizerを使用してこれを機能させました。)
  3. UIPopOverが表示され、ユーザーがUIBarButtonItemをタップしてUIPopOverが「タイ」になったら、UIPopOverを閉じます。(これが私にとっての問題です。)
  4. UIPopOverが表示され、ユーザーが別のUIBarButtonItemをタップしたら、現在のUIPopOverを閉じて、適切な新しいUIPopOverを表示します。(これは正常に機能しています。)

したがって、私が直面している問題は、ボタンをタップする前にUIGestureRecognizerが起動することです。また、ユーザーがUIBarButtonItemを押しているときにUIGestureRecognizerを「オプトアウト」する良い方法を見つけることができません(したがって、UIBarButtonItemではなくUIToolbar自体がタップされたときにのみUIGestureRecognizerのアクションを起動します)。この結果、UIPopOverが(UIBarButtonItemから)表示され、ユーザーが同じUIBarButtonItemをタップすると、UIPopOverが閉じられ、再び表示されます。

「toolbarTapped」フラグを0.10秒間YESに設定してから、NO(またはそのようなもの)に戻すという、ある種のタイミングの問題を回避しようとしています。

私はこれを本当にエレガントに(そしてハックではなく)行う方法を見つけたいと思っています。

UIGestureRecognizerが最初に起動し、UIBarButtonItemのフレームを取得するための適切な(非プライベート)方法がないように見えるため、UIGestureRecognizerがUIBarButtonItemタッチに基づいてトリガーされた時期を判断する方法が見つからないようです。

基本的に、私はUIToolbarとそのUIBarButtonItemsを合理的な人が期待するように動作させようとしていますが、壁に頭をぶつけています。

UIGestureRecognizerのコードは次のとおりです。

// Initialization
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(removeAllPopOvers)];
[tapRecognizer setCancelsTouchesInView:NO];
[tapRecognizer setNumberOfTapsRequired:1];
[tapRecognizer setNumberOfTouchesRequired:1];
[[self Toolbar] addGestureRecognizer:tapRecognizer];

// Tap handler
- (void)removeAllPopOvers {
    NSLog(@"removing all popovers");
    if ([self firstPopOver]) {
        [[self firstPopOver] dismissPopoverAnimated:YES];
        [self setFirstPopOver:nil];
    }
    // and so on with the rest...
}

そして、これが私のUIPopOversの1つがどのように表示されるかです:

- (IBAction)showSettings:(id)sender {
    NSLog(@"settings button tapped");
    if (![self SettingsPopOver]) {
        SettingsViewController *settingsVC = [[SettingsViewController alloc] initWithNibName:@"SettingsView-iPad" bundle:nil];
        UIPopoverController *popOver = [[UIPopoverController alloc] initWithContentViewController:settingsVC];
        [popOver setDelegate:self];
        [self setSettingsPopOver:popOver];
        [[self SettingsPopOver] setPopoverContentSize:CGSizeMake(320, 300)];
        [[self SettingsPopOver] presentPopoverFromBarButtonItem:[self Settings] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
    }
}

これらすべての正味の効果は、次の2つのオプションのいずれかを選択できることです(両方ではありません)。

  1. UIBarButtonItemがUIPopOverを閉じることを許可します。
  2. UIToolbarをタップして、UIPopOverを閉じます。

何か案は?

ありがとう!

4

3 に答える 3

0

今のところ、私は機能するものを実装しましたが、エレガントではありません(少なくとも、そうではないと思います)。

基本的に、私が行うことは、最初に「バッファ」メソッドに送信することにより、UIGestureRecognizerからのアクションを遅らせることです。

#pragma mark - PopOver Dismissal
// dismissAllPopOversBuffer is called as the action of my UIGestureRecognizer
- (void)dismissAllPopOversBuffer {
    NSLog(@"dismiss all popovers buffer...");
    [self performSelector:@selector(dismissAllPopOvers) withObject:nil afterDelay:0.1];
}
- (void)dismissAllPopOvers {
    NSLog(@"dismissing all popovers");
    // actual dismissal logic
}

ご覧のとおり、これにより実際の却下ロジックが0.1秒押し出されます。次に、ボタンを押す各方法で、次のようにします。

#pragma mark - UIBarButtonItem Press Event Handlers
- (IBAction)buttonPressed:(id)sender {
    [NSObject cancelPreviousPerformRequestsWithTarget:self
                                             selector:@selector(dismissAllPopOvers)
                                               object:nil];
    // The rest of the logic to dismiss/show UIPopOver
}

これまでのところ、私のテストはそれが機能することを示しています。NSLogタイムスタンプに基づくと、UIGestureRecognizerアクションとUIBarButtonItemイベントの間の実際の経過時間は通常1ミリ秒(0.001秒)でした。したがって、0.1秒(または通常の時間経過の100倍)を押し出すことはほとんどの場合安全であるはずですが、それでも私は気に入らない。

ユーザーがUIToolbarをタップしたが、UIBarButtonItemsはタップしなかった時期を判断する方法を見つけたいと思います。それは(論理的には)かなり簡単に思えますが、(実際には)かなり難しいです。

于 2012-02-24T17:12:15.323 に答える
0

問題3の場合:

if ([self.popoverController isPopoverVisible])
    [self.popoverController dismissPopoverAnimated:YES];
else

ポップオーバーが表示されている場合は、それを却下します。それ以外の場合は、ポップオーバーを作成します。

残りの部分については、ツールバーに触れた場合にのみポップオーバーを閉じますか?ユーザーが画面上の他の場所に触れた場合、ポップオーバーをそのままにしますか?

ポップオーバーコントローラーにはpassthroughViews、uiviewを追加できると私が信じている適切な機能があります。したがって、実際には、メインビューを追加してタッチしても、ポップオーバーの却下はトリガーされません。これがどのように機能するか完全にはわかりません。掘り下げる必要があります。

https://developer.apple.com/library/ios/#documentation/uikit/reference/UIPopoverController_class/Reference/Reference.html

于 2012-02-24T17:46:11.523 に答える
0

そこで、Gesture Recognizerデリゲートを実装し、以下のメソッドを呼び出すことで、2つのジェスチャを同時に認識させることを解決しました(これにより、スクロール用のパンジェスチャと、新しいビューを呼び出すスワイプジェスチャを使用して、同時に登録するためにポップアップすることができました時間):

(BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer      
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer
{
  return YES;
}
于 2015-03-20T21:13:58.927 に答える