0

私はストリーミング音楽アプリを書いていますが、音楽アプリと Pandora のユニバーサルな「再生中」ボタンがとても気に入っています。私はそれらを自分で実装しようとしています。残念ながら、私が試した方法は、私自身だけでなく、私を助けようとした人々を混乱させました. これは私がこれまでに試したことであり、すべてが機能しない/部分的に機能しない:

  • すべてのコントローラーでa を使用するstatic UIBarButtonItem(動作に一貫性がなく、場合によってはセグエがない)
  • Interface Builder のすべてのコントローラーにボタンを手動で追加する (機能しますが、遷移時にフェードアウト/フェードインのアニメーションが発生します)
  • すべてのコントローラがサブクラス化された を持つビュー コントローラを作成するstatic UIBarButtonItem(方法 1 からセグエなしの問題は解消されましたが、それでも動作に一貫性がありません)。

TL;DR: ユニバーサル右バー ボタン アイテムを実装する方法がわかりません。方法を教えてください。

階層を空白で表現したデモ プロジェクト。

編集: Pandora の開発者である Neil Mixがこの質問に回答しました。まったく同じ問題。しかし、私はそれを理解していませんでした。誰かが彼の方法を説明できれば素晴らしいでしょう。

4

3 に答える 3

3

私はあなたのためにソリューションを実装しました、それはデリゲートとしてBarButtonMangerカスタムサブクラスによって使用されるシングルトンを使用します。 ボタンのターゲットを決定する必要があります(VCナビゲート、ナビゲーションコントローラー、その他のシングルトン/アプリデリゲートなど)が、このソリューションが役立つはずです:http : //cl.ly/3M151o1i3z3O忘れないでくださいストーリーボードのナビゲーションコントローラーのクラスをCustomNavigationControllerに変更してください!UINavigationController

//  BarButtonManager.h
#import <UIKit/UIKit.h>

@interface BarButtonManager : NSObject <UINavigationControllerDelegate>

+ (BarButtonManager*)sharedInstance;

@end


//  BarButtonManager.m
#import "BarButtonManager.h"

@implementation BarButtonManager {
    UIBarButtonItem *_sharedItem;
}

+ (BarButtonManager*)sharedInstance
{
    static BarButtonManager *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[BarButtonManager alloc] init];
    });
    return instance;
}


- (UIBarButtonItem*)sharedButtonItem
{
    if (!_sharedItem) { // not thread safe, but let's assume this is only called from UI thread
        UIButton *nowPlayingButton = [UIButton buttonWithType:UIButtonTypeCustom];

        UIImage *background = [[UIImage imageNamed:@"nav-bar-now-playing-button-silver.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(4.0, 7.5, 5.0, 13.0)];
        UIImage *backgroundPressed = [[UIImage imageNamed:@"nav-bar-now-playing-button-pressed-silver.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(4.0, 7.5, 5.0, 13.0)];

        [nowPlayingButton setBackgroundImage:background forState:UIControlStateNormal];
        [nowPlayingButton setBackgroundImage:backgroundPressed forState:UIControlStateHighlighted];

        nowPlayingButton.frame = CGRectMake(0.0, 0.0, background.size.width, background.size.height);

        NSMutableParagraphStyle *centre = [[NSMutableParagraphStyle alloc] init];
        centre.alignment = NSTextAlignmentCenter;
        centre.lineBreakMode = NSLineBreakByWordWrapping;


        NSMutableAttributedString *nowPlayingTitle = [[NSMutableAttributedString alloc] initWithString:@"Now Playing"];
        [nowPlayingTitle addAttributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:9.5], NSParagraphStyleAttributeName : centre, NSForegroundColorAttributeName : [UIColor whiteColor]} range:NSMakeRange(0, nowPlayingTitle.length)];


        [nowPlayingButton setAttributedTitle:nowPlayingTitle forState:UIControlStateNormal];

        nowPlayingButton.titleLabel.lineBreakMode = NSLineBreakByCharWrapping;
        nowPlayingButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
        nowPlayingButton.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
        [nowPlayingButton setTitleEdgeInsets:UIEdgeInsetsMake(0, -3, 0, 5)];

        [nowPlayingButton addTarget:nil action:@selector(nowPlayingPressed) forControlEvents:UIControlEventTouchUpInside];

        _sharedItem = [[UIBarButtonItem alloc] initWithCustomView:nowPlayingButton];
    }
    return _sharedItem;
}

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    navigationController.topViewController.navigationItem.rightBarButtonItem = nil;
    UIBarButtonItem *sharedItem = [self sharedButtonItem];
    sharedItem.target = viewController;
    viewController.navigationItem.rightBarButtonItem = sharedItem;
}

@end


//  CustomNavigationController.h
#import <UIKit/UIKit.h>

@interface CustomNavigationController : UINavigationController

@end

//  CustomNavigationController.m
#import "CustomNavigationController.h"
#import "BarButtonManager.h"

@implementation CustomNavigationController

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        self.delegate = [BarButtonManager sharedInstance];
    }
    return self;
}

@end
于 2013-03-02T09:04:57.743 に答える
2

私は最近、この問題についてブログ投稿を書きました: http://www.codebestowed.com/ios-shared-barbuttonitems

Martin Ullrich と同じ戦略を使用していますが、ストーリーボードでこれを設定する方法についても詳しく説明しています。これには少しハックが必要です。SOでは単にリンクを投稿することは推奨されていないことを知っているので、ここで要約しようとします。

基本的に、問題は、NavigationController を Storyboard にドラッグすると、編集可能な NavigationBar が作成されないことです。これを回避するには、ViewController を作成し、[Editor] -> [Embed In] -> [Navigation Controller] を選択します。このメソッドを介して作成される NavigationController には、BarButtonItems をドラッグできる NavigationBar があります。この新しいコントローラーを UINavigationController のカスタム サブクラスにリンクすると、ナビゲーション バーの任意の IBOutlets を作成できます。

したがって、このハックと Martin Ullrich の回答を組み合わせて使用​​すると、必要な機能とストーリーボードの機能を使用できるようになります。

于 2014-03-15T05:28:31.197 に答える
0

あまり痛みはありません。「プレイヤー」ビューコントローラーがあるかもしれません。アプリのデリゲートで、変数カレンダー「universalPlayer」を作成します。「プレーヤー」オブジェクトを作成するときに、これを「universalPlayer」に割り当てる必要があります。次に、ナビゲーション コントローラーにバー ボタンを追加します。バー ボタンのアクションで、AppDelegate からプレーヤー ビュー コントローラーを取得するだけです。これは簡単な解決策です。

于 2013-03-02T09:19:48.437 に答える