iphone - QLPreviewController 删除或添加 UIBarButtonItems

标签 iphone objective-c ipad uibarbuttonitem qlpreviewcontroller

我在网上看到了很多这样的问题,但似乎没有人真正知道答案?

我正在使用 QLPreviewController 来显示 PDF 文档。我首先使用的是 UIWebView,但出于性能原因,我被推荐使用 QLPreviewController 而不是更大的文档。

我想要的是右上角的 4 个自定义 UIBarButtonItem(打印按钮所在的位置)。

我设法在底部获得了一个自定义工具栏,但这并不是我真正想要的。

考虑到不能在打印按钮的地方添加自定义按钮,我还是想去掉打印按钮,改用自定义工具栏。

编辑(解决方案): 我不久前找到了解决方案,但没有更新这篇文章,所以我是这样解决问题的:

我手动添加所有按钮:

// Create a toolbar to have the buttons at the right side of the navigationBar
UIToolbar* toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 180, 44.01)];
[toolbar setTranslucent:YES];

// Create the array to hold the buttons, which then gets added to the toolbar
NSMutableArray* buttons = [[NSMutableArray alloc] initWithCapacity:4];


// Create button 1
button1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSearch target:self action:@selector(button1Pressed)];
[buttons addObject:button1];

// Create button 2
button2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCompose target:self action:@selector(button2Pressed)];
[buttons addObject:button2];

// Create button 3
button3 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:@selector(button3Pressed)];
[buttons addObject:button3];

// Create a action button
openButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(openWith)];
[buttons addObject:openButton];

// insert the buttons in the toolbar
[toolbar setItems:buttons animated:NO];

// and put the toolbar in the navigation bar
[[self navigationItem] setRightBarButtonItem:[[UIBarButtonItem alloc] initWithCustomView:toolbar]];

最佳答案

我搜索了这个问题的解决方案几个月,终于找到了一种自定义 QLPreviewController 的导航栏的方法。以前我也使用 UIWebView 来显示文档,因为我不允许在我的应用程序中显示某些 secret 文档的 iOS 共享按钮,这就是 QLPreviewController 所做的。但是我想要那些不错的功能,例如带有小预览的目录和其他东西。所以我寻找一种可靠的方法来摆脱这个按钮。和你们一样,我首先考虑自定义 QLPreviewController 的导航栏。然而,正如其他人已经指出的那样,这在 iOS6 之后是绝对不可能的。因此,我们需要做的不是自定义现有的导航栏,而是创建一个自己的导航栏并将其放置在 QL-navigationbar 的前面,从而隐藏它。

那么如何做到这一点呢? 首先,我们需要继承 QLPreviewContoller 并覆盖 viewDidAppear 方法和 viewWillLayoutSubviews,如下所示:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.qlNavigationBar = [self getNavigationBarFromView:self.view];

    self.overlayNavigationBar = [[UINavigationBar alloc] initWithFrame:[self navigationBarFrameForOrientation:[[UIApplication sharedApplication] statusBarOrientation]]];
    self.overlayNavigationBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    [self.view addSubview:self.overlayNavigationBar];

    NSAssert(self.qlNavigationBar, @"could not find navigation bar");

    if (self.qlNavigationBar) {
        [self.qlNavigationBar addObserver:self forKeyPath:@"hidden" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:nil];
    }

    // Now initialize your custom navigation bar with whatever items you like...    
    UINavigationItem *item = [[UINavigationItem alloc] initWithTitle:@"Your title goes here"];
    UIBarButtonItem *doneButton  = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonTapped:)];
    item.leftBarButtonItem = doneButton;
    item.hidesBackButton = YES;

    [self.overlayNavigationBar pushNavigationItem:item animated:NO];
}

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    self.overlayNavigationBar.frame = [self navigationBarFrameForOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
}

qlNavigationBar 是 QLPreviewController 拥有的默认导航栏,overlayNavigationBar 是我们的自定义导航栏,它将隐藏默认导航栏。我们还向默认的 QL 导航栏添加了一个键值观察,以便在默认导航栏隐藏/重新出现时得到通知。在 viewWillLayoutSubviews 方法中,我们负责自定义导航栏框架。

接下来我们应该做的是监听 quicklook 导航栏的可见性变化:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    // Toggle visiblity of our custom navigation bar according to the ql navigationbar
    self.overlayNavigationBar.hidden = self.qlNavigationBar.isHidden;
}

所以现在我们需要实现我们需要的方法来获取 QL 导航栏和一个始终为我们的自定义导航栏提供当前框架的方法:

- (UINavigationBar*)getNavigationBarFromView:(UIView *)view {
    // Find the QL Navigationbar
    for (UIView *v in view.subviews) {
        if ([v isKindOfClass:[UINavigationBar class]]) {
            return (UINavigationBar *)v;
        } else {
            UINavigationBar *navigationBar = [self getNavigationBarFromView:v];
            if (navigationBar) {
                return navigationBar;
            }
        }
    }
    return nil;
}

- (CGRect)navigationBarFrameForOrientation:(UIInterfaceOrientation)orientation {
    // We cannot use the frame of qlNavigationBar as it changes position when hidden, also there seems to be a bug in iOS7 concerning qlNavigationBar height in landscape
    return CGRectMake(0.0f, self.isIOS6 ? 20.0f : 0.0f, self.view.bounds.size.width, [self navigationBarHeight:orientation]);
}

- (CGFloat)navigationBarHeight:(UIInterfaceOrientation)orientation {   
    if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        if(UIInterfaceOrientationIsLandscape(orientation)) {
            return self.isIOS6 ? 32.0f : 52.0f;
        } else {
            return self.isIOS6 ? 44.0f : 64.0f;
        }
    } else {
        return self.isIOS6 ? 44.0f : 64.0f;
    }
}

还有什么?当然,您需要定义属性,在 dealloc 中删除观察者,以及定义和设置 iOS6 属性(网络上有很多示例...)。您还需要自定义导航栏并收听按钮回调。就是这样。

我知道这有点 hacky ...通过将默认 QL 操作按钮隐藏在另一个导航栏下方来隐藏/替换它...但至少它对我来说是可靠的并且您不访问私有(private) API 等。

我在适用于 iOS 6.0 - 7.0 以及 iPad 2 和 3、iPhone 4S 和 5(后者安装了 iOS 7.0 Beta 6)的所有可用模拟器上测试了我的解决方案。

关于iphone - QLPreviewController 删除或添加 UIBarButtonItems,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6957091/

相关文章:

ios - 检测点击包含多个部分的 UITableView 的 UITableViewCell 中的按钮

iphone - iOS : cannot delete file

objective-c - 没有 bundleID 的 bundle ,SpriteKit

iphone - NSMutableURLRequest 在正文中添加额外信息,导致 Content-Length 不正确

iphone - 为 iOS 的 Facebook 帖子显示更高质量的图像

iphone - 如何重命名文档目录中的文件?

iphone - 使用 NSCoder 初始化静态单例对象

iphone - iOS Core 数据关系故障

ipad - MonoTouch UIAlertView 不显示

ios - 仅横向的 iPad 应用程序以纵向显示 UIImagePicker