I have seen this kind of question a lot on the internet but it seems no one really knows the answer?
I am using QLPreviewController for displaying PDF documents. I first used a UIWebView but I was recommended to use QLPreviewController instead for performance reasons with bigger documents.
what I want is 4 custom UIBarButtonItem's in the top right (so where the print button is).
I managed to get a custom toolbar at the bottom, but that's not really what I want.
Considering that it is not possible to add custom button at the place of the print button, I still want to remove the printbutton and use the custom toolbar instead.
EDIT (Solution): I found the solution a while ago but didn't update this post so here is how I solved the problem:
I add al the buttons manually:
// 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]];
By mixing a bit out of the existing answers/comments I was able to get this working for my use case: I needed to display files inside a
UINavigationController
and keep the ability of hiding/showing theUINavigationBar
when the file content is tappedBased on the answer from Lukas Gross and the comment from nacross here's what I ended up doing:
QLPreviewController
as a child view controller. This will show two navigation bars: one for the main navigation controller and one from theQLPreviewController
containerTop
in the code)UINavigationBar
plus the status bar, so that theQLPreviewController
'sUINavigationBar
remains hidden under the mainUINavigationBar
.hidden
property of theUINavigationBar
so that we can (1) hide/show our mainUINavigationBar
and (2) reset the top constraintI ended up with something like this:
The animations might need a little tweaking and it is hacky, but it's better than not having this possibility. It should be possible to adapt this strategy to other scenarios without the
UINavigationController
Note: If you have a crash when implementing the container view for the
QLPreviewController
from a storyboard, subclass theQLPreviewController
and implement the initializer:Update:
This no longer works in iOS 6. Quick Look runs in another process using XPC. See here for more details. I don't foresee any way to customize QLPreviewController. The following answer remains for anyone interested for pre-iOS 6.
I answered an almost identical question the other day here. The question pertained to removing the print button, which isn't too hard. One thing to note about
QLPreviewController
is that it's not meant to be customized. I have built a subclass ofQLPreviewController
that can be customized. I've put it here on Github. It's designed to easily remove the action button, among other features too. It wouldn't take much effort at all to replace the button with a custom one.The biggest thing to watch out for is that the action button is re-added to the navigation bar anytime a new document is displayed. You should notice this in my code. Anytime
RBFilePreviewer
removes the action button, you just need to re-add your custom buttons. To add your custom buttons, you should create aUIBarButtonItem
that holds a custom view with four buttons in it. Then set the right bar button item as the customUIBarButtonItem
you created.Update:
I've updated
RBFilePreviewer
to allow you to set a custom right bar button item right out-of-the-box. Just call-setRightBarButtonItem:
onRBFilePreviewer
and it just works.I understand that this answer is a little late for this. But I really do find a solution for this.
Add this as a Category and import this into your QLPreviewController's subclass and just call the
It works for me. I learn this from http://nshipster.com/method-swizzling/ and thoughts from http://codego.net/507056/
Good luck, guys.
I took the response from Lukas Gross and applied it in Swift on iOS 8 and came up with this solution that worked for me:
NOTE: I have the QLPreviewController embedded in a UINavigationController!
Code:
And applying this code like this:
I searched for a solution to this problem for months and finally found a way to customize the navigationbar of a QLPreviewController. Previously I was also using UIWebView to display documents as I'm not allowed to display the iOS-share button for certain confidential documents within my app and this is what the QLPreviewController does. However I wanted to have those nice features such as the table of contents with the little previews and stuff. So I looked for a reliable way to get rid of this button. Like you guys I was first looking into customizing the navigationbar of the QLPreviewController. However, as others already pointed out this is absolutely not possible since iOS6. So instead of customizing the existing navigation bar what we need to do is creating an own one and placing it in front of the QL-navigationbar, thus hiding it.
So how to do this? First of all we need to subclass QLPreviewContoller and overwrite the viewDidAppear method and viewWillLayoutSubviews like this:
qlNavigationBar is the default navigationbar owned by the QLPreviewController, overlayNavigationBar is our custom one which will hide the default one. We also add a key-value observation to the default QL navigationbar to get notified when the default navigation bar gets hidden / reappears. In the viewWillLayoutSubviews method we take care of our custom navigationbar frame.
The next thing we should do is listen for visibility changes of the quicklook navigationbar:
So now we need to implement methods we need to get the QL navigationbar and one that always gives us the current frame for our custom navigation bar:
What else? Well of course you need to define properties, remove the observer in dealloc as well as define and set the iOS6 property (there are plenty of examples on the web...). Also you need to customize your navigationbar and listen to the button callbacks. That's it.
I know this is a bit hacky ... hiding / replacing the default QL action button by hiding it beneath another navigationbar ...but well at least it works reliable for me and you don't access private APIs etc.
I tested my solution on all available simulators for iOS 6.0 - 7.0 as well as on iPad 2 & 3, iPhone 4S & 5 (the latter with iOS 7.0 Beta 6 installed).