QLPreviewController 删除或添加 UIBarButtonItems

2024-04-02

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

我正在使用 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 来显示文档,因为我不允许在我的应用程序中显示某些机密文档的 iOS 共享按钮,而这就是 QLPreviewController 的作用。不过,我想要拥有那些不错的功能,例如带有小预览的目录和其他内容。所以我寻找一种可靠的方法来摆脱这个按钮。和你们一样,我首先考虑自定义 QLPreviewController 的导航栏。然而,正如其他人已经指出的那样,自 iOS6 以来这是绝对不可能的。因此,我们需要做的不是自定义现有的导航栏,而是创建一个自己的导航栏并将其放置在 QL 导航栏前面,从而将其隐藏。

那么如何做到这一点呢? 首先,我们需要子类化 QLPreviewController 并覆盖 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]];
}

ql导航栏是 QLPreviewController 拥有的默认导航栏,覆盖导航栏是我们自定义的,它将隐藏默认的。我们还向默认 QL 导航栏添加了键值观察,以便在默认导航栏隐藏/重新出现时收到通知。在里面viewWillLayoutSubviews我们处理自定义导航栏框架的方法。

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

- (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 操作按钮隐藏在另一个导航栏下方来隐藏/替换默认的 QL 操作按钮...但至少它对我来说是可靠的,并且您不会访问私有 API 等。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QLPreviewController 删除或添加 UIBarButtonItems 的相关文章

随机推荐