iPad のポップオーバー ツールバー ボタンのアクション メソッドにフックするにはどうすればよいですか?
-
24-09-2019 - |
質問
私は分割ビュー テンプレートを使用して、もちろんポートレート モードのポップオーバーを持つ単純な分割ビューを作成しています。ツールバー項目を追加/削除し、ポップオーバーコントローラーを設定して削除するテンプレートによって生成されたデフォルトのコードを使用しています。これら 2 つのメソッドは、splitViewController:willShowViewController:... です。そして、splitViewController:willHideViewController:...
ポップオーバーが表示されているときにユーザーがツールバーボタンをタップした場合にポップオーバーを非表示にする方法を見つけようとしています。ポップオーバーの外側のどこかをタップすると、項目を選択せずにポップオーバーを消すことができますが、ユーザーがボタンを再度タップするとポップオーバーが消えるようにしたいと考えています。
私が行き詰まっているのは次のとおりです。ツールバー ボタンのアクションにフックする明確で簡単な方法はないようです。デバッガーを使用すると、ボタンで呼び出されるアクションが showMasterInPopover であることがわかります。そして、私はプログラムでセレクターを扱うのが初めてであることを認めます。
すでに存在するアクションをオーバーライドせずに、何らかの方法でアクションを作成してツールバー項目に設定することはできますか?例えば現在存在するアクションを呼び出すアクションを追加しますか?それとも、ポップオーバーを表示/非表示にするアクションを自分で作成する必要がありますか (この動作は、現在、おそらく Split View コントローラーによってバックグラウンドで実行されています。???)。
それとも、設定されている既存の動作を変更せずに、この動作をこのボタンに追加する簡単な方法が欠けているのでしょうか?
ありがとう!
解決
ポップオーバーを閉じます:
- (void) splitViewController:(UISplitViewController *)svc
popoverController: (UIPopoverController *)pc
willPresentViewController: (UIViewController *)aViewController
{
if (pc != nil) {
[pc dismissPopoverAnimated:YES];
}
}
他のヒント
だから、barButtonItemは、ターゲットとshowMasterInPopoverとしてUISplitViewControllerを持つことになります。以下のように、私はそれを呼び出すために大丈夫ではありません少し心配ですが、私は自己(ビューコントローラ)とカスタムメソッドのアクションにターゲットを変更することにより、仕事にそれを得たので、私は、ドキュメントでそれを見つけることができませんこの:
- (void)showMasterInPopover:(id)sender {
// ...insert custom stuff here...
[splitViewController showMasterInPopover:sender];
}
は、実際のコメントをする担当者を持っていません。 : - (
@Jann - 私はエリザベスが何をしたいのかかなり確信していることはかなり標準です。あなたはコーナー左上のツールバーのボタンを押すと、例えば、ノートでは、アプリケーションに発送していることのiPadが閉じにあらかじめロードされ、ポップオーバーを開きます。
以下は、私のソリューションです。それはUISplitViewController
のツールバーボタンのイベントハンドラをフックして、greenisusのソリューションと同様にして開始します。私は、ポップオーバーが開いているかいないかどうかを追跡するために私のコントローラにフラグを使用します。最後に、ユーザは、ポップオーバーの外側をクリックして、それを閉じて、その後、ポップオーバーを開く場合に対処するために、私はUIPopoverControllerDelegate
プロトコルを実装します。
まず、コントローラインタフェース
@interface LaunchScene : NSObject <UISplitViewControllerDelegate, UIPopoverControllerDelegate>
{
UISplitViewController* _splitViewController; //Shows list UITableView on the left, and details on the right
UIToolbar* _toolbar; //Toolbar for the button that will show the popover, when in portrait orientation
SEL _svcAction; //The action from the toolbar
id _svcTarget; //The target object from the toolbar
UIPopoverController* _popover; //The popover that might need to be dismissed
BOOL _popoverShowing; //Whether the popover is currently showing or not
}
-(void) svcToolbarClicked: (id)sender;
私は彼が右の関数を呼び出していない可能性がありますことを心配addessのgreenisusに_svcActionと_svcTargetを使用します。
以下は、私の実装です。 の簡潔さのために、私はUISplitViewControllerとサブビューをインスタンス化するコードを省略している。の全ての表示/非表示に関連するコードが表示されます。
//the master view controller will be hidden so hook the popover
- (void)splitViewController:(UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController:(UIPopoverController*)pc
{
_popoverShowing = FALSE;
if(_toolbar == nil)
{
//set title of master button
barButtonItem.title = @"Title goes here";
//Impose my selector in between the SVController, and the SVController's default implementation
_svcTarget = barButtonItem.target;
_svcAction = barButtonItem.action;
barButtonItem.target = self;
barButtonItem.action = @selector(svcToolbarClicked:);
//create a toolbar
_toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 1024, 44)];
[_toolbar setItems:[NSArray arrayWithObject:barButtonItem] animated:YES];
}
//add the toolbar to the details view (the second controller in the splitViewControllers array)
UIViewController* temp = [_splitViewController.viewControllers objectAtIndex:1];
[temp.view addSubview:_toolbar];
}
ここに私の機能は、ツールバーのクリックに応答すること、です。このハンドルユーザータップして、ツールバーのボタンを再タップケース。
-(void) svcToolbarClicked: (id)sender
{
if(_popoverShowing)
{
[_popover dismissPopoverAnimated:TRUE];
}
else
{
//Perform the default SVController implementation
[_svcTarget performSelector:_svcAction];
}
//Toggle the flag
_popoverShowing = !_popoverShowing;
}
UISplitViewControllerDelegate からいくつかの機能
//the master view (non-popover) will be shown again (meaning it is going to landscape orientation)
- (void)splitViewController:(UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)button
{
//remove the toolbar
[_toolbar removeFromSuperview];
}
// the master view controller will be displayed in a popover (i.e. the button has been pressed, and the popover is about to be displayed.
//Unfortunately triggers when the popover is ALREADY displayed.
- (void)splitViewController:(UISplitViewController*)svc popoverController:(UIPopoverController*)pc willPresentViewController:(UIViewController *)aViewController
{
_popover = pc; //Grab the popover object
_popover.delegate = self;
}
は、上記のコードは、ほとんどの場合に十分です。ユーザーがポップオーバーを開いた場合は、その後、_popoverShowing
ブールが再オープンポップオーバーに二回、ツールバーのボタンをタップするようにユーザーを強制的に正しくない値が含まれていますが、画面上の他の場所でクリックすることで解任。この問題を解決するには、以下のようなスニペットUIPopoverControllerDelegate
メソッドを実装します。
//UIPopoverControllerDelegate method
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
_popoverShowing = FALSE;
_popover = nil;
}
これはStackOverflowの上UISplitViewControllerの質問のほとんどを、把握する永遠に連れて行ってくれたドキュメントを掘りと(と思います)。私は、誰かがそれを有用見つけた願っています。もしそうなら、私は切望の評判ポイント。 ; - )
たぶん、あなたはすべてあまりにも多く、それを複雑か、私はあなたたちがやってみたかったとは非常に異なるものを読んだことがある...おそらく、これはあなたがすべてがそうhardish把握しようとしていたものです。
-(void)togglePopOverController {
if ([popOverController isPopoverVisible]) {
[popOverController dismissPopoverAnimated:YES];
} else {
[popOverController presentPopoverFromBarButtonItem:bbiOpenPopOver permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
}
エリザベートはこう書いています。
ポップオーバーの外側のどこかをタップすると、項目を選択せずにポップオーバーを消すことができますが、ユーザーがボタンを再度タップするとポップオーバーが消えるようにしたいと考えています。
まず最初に断っておきますが、私がこれから言おうとしている内容はいずれも個人的に受け取られるものではありません。そのような意味ではありません。それはすべて、何年にもわたるプログラミング インターフェースの設計と Apple ヒューマン インターフェース ガイドラインの研究 (そして常にグラフィック デザイナーを雇うこと) から来ています。 試しています 物事の正しいやり方を教えてくれる)。これは反対の視点を意味しており、暴言ではありません。
あなたが提案していることは、私にとってUI的に問題であり、Appleがアプリをレビューするときに問題を引き起こす問題になるでしょう。既知の UI オブジェクトに、通常実行されない機能を実行させることは決して想定されていません (たとえば:ボタン 一度もない ショー その後 ビュー/オブジェクト/ウィンドウを解放します。トグルでこれを行います)。
たとえば、ナビゲーション バーの虫眼鏡は (Apple の定義による) 検索を意味します。彼らはこれまで、インターフェースのズームにこれを使用するアプリを拒否してきましたし、今後も拒否し続けるでしょう。例えば: Apple、ConvertBotを拒否 または オデッセイ:涙の軌跡 (ページを検索してください)。拒否の文言は常に同じです (使用法として引用される内容を太字で示します)。
「…標準的な iPhone/iPod の画面イメージを非標準的な方法で使用しているため、ユーザーの混乱を招く可能性があります。iPhoneの標準グラフィックスの動作を変更し、 行動, 、画像、またはそれらのグラフィック、アクション、または画像の失敗をシミュレートすることは、アプリケーションがヒューマン インターフェイス ガイドラインに従うことを要求する iPhone 開発者プログラム契約に違反します。」
また、この機能が本当に必要な場合は、次のように自問してください。"なぜ?"。あなた自身がそれが好きだからなら、私は本当にスキップします。ほとんどのユーザーはこの動作に混乱し、実際には使用しないでしょう。 彼らはそれが使用できるオプションであることを知らないでしょう. 。Apple は過去 3 年間、iPhoneOS ユーザーに OS とインターフェイス要素の使い方をトレーニングしてきました。プログラマーやデザイナーとして、アプリの使用方法をユーザーにトレーニングするのに時間を費やすことは最も避けたいことです。彼らは通常、強制的に学習する代わりに、デバイスからアプリを削除し、別の同様のアプリに移動します。 あなたの 物事のやり方。
私の 0.02 ドルだけ