Customizing QLPreviewController - iphone

I have an issue in customizing the appearance of my QLPreviewController.
We can display a QLPreviewController by pushing it in a navigation controller, or presenting it in a ModalViewController. Since my navigationController's bar is customized a little (tintColor), I'm pushing the QLPreviewController to preserve my color scheme. But when I push it, the QLPreviewController seems to have some problems : I need to systematically call [qlpvc reloadData] so that my file is displayed.
In iOS [REDACTED], even with reloadData, nothing displays in the pushing way, (actually it displays but in a random way). So I decided it could be interesting to only use the reliable Modal way.
Soooo my point is that I want to present my QLPreviewController in a ModalViewController. It works great that way, but I can't customize the viewController appearance.
For example in a didSelectRowAtIndexPath if I do :
(I don't have my sources near to me so excuse me if I do a mistake)
QLPreviewController *qlpvc = [[QLPreviewController alloc] init];
qlpvc.dataSource = self; // Data Source Protocol & methods implemented of course
No need for delegate in my case so //qlpvc.delegate = self;
qlpvc.currentPreviewItemIndex = [indexPath.row];
// The following doesn't work :
[qlpvc.navigationController.navigationBar setTintColor:[UIColor redColor]];
// The following doesn't work too :
[qlpvc.modalViewController.navigationController.navigationBar setTintColor:[UIColor redColor]];
[self presentModalViewController:qlpvc animated:YES];
[qlpvc release];
tl ; dr version : How to manage to customize my modal QLPreviewController's appearance ? Especially the tintColor of the navigationBar ?
Thanks a lot.

This works, but I don't know if it will be rejected by Apple as it's not a published method and may break in future versions of the OS. Works in iOS6.
Add to the preview controller datasource method:
- (id <QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index
{
for (id object in controller.childViewControllers)
{
if ([object isKindOfClass:[UINavigationController class]])
{
UINavigationController *navController = object;
navController.navigationBar.tintColor = [UIColor colorWithRed:0.107 green:0.360 blue:0.668 alpha:1.000];
}
}
NSString *pathToPdfDoc = [[NSBundle mainBundle] pathForResource:#"MyPDFFile" ofType:#"pdf"];
return [NSURL fileURLWithPath:pathToPdfDoc];
}

Subclass QLPreviewController and change the tintColor, et al in viewDidLoad:.

If you are trying to maintain simple styling such as tintColor throughout your app, you should consider using UIAppearance selectors on many UIView classes. The following example customizes all instances of UINavigationBar, including those displayed in QLPreviewController:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
//..
[self initAppearance];
return YES;
}
-(void)initAppearance{
UINavigationBar* defaultNavigationBar = [UINavigationBar appearance];
UIImage *backgroundImage = [UIImage imageNamed:#"MY_IMAGE.png"]
NSDictionary *defaultNavigationBarDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:#"Futura-Medium" size:19], NSFontAttributeName,
[UIColor blueColor], UITextAttributeTextColor,
[UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.0f], UITextAttributeTextShadowColor,
[NSValue valueWithUIOffset:UIOffsetMake(0.0f, 2.0f)], UITextAttributeTextShadowOffset,
nil];
defaultNavigationBar.titleTextAttributes = defaultNavigationBarDictionary; //iOS5
//[defaultNavigationBar setBackgroundImage:backgroundImage forBarMetrics:UIBarMetricsDefault]; //iOS5
[defaultNavigationBar setBarTintColor:[UIColor redColor]]; //iOS7
[defaultNavigationBar setShadowImage:[[UIImage alloc] init]]; //iOS6, removes shadow
[defaultNavigationBar setTitleVerticalPositionAdjustment:0.0f forBarMetrics:UIBarMetricsDefault]; //iOS5
[defaultNavigationBar setBackIndicatorImage:[UIImage imageNamed:#"BACK_ARROW.png"]]; //iOS7
[defaultNavigationBar setBackIndicatorTransitionMaskImage:[UIImage imageNamed:#"BACK_ARROW.png"]]; //iOS7
}

Related

Custom UITabBarController -- Best Approach

What would be the best way to create a completely custom UITabBarController look alike.
I need full customization of its size, animate it, etc.
A solution that I have is just using a UIView for the tabbarcontroller that then replaces the UIView above it depending on what button is selected on that UIView.
What is the best approach?
This is a pretty good guide for doing just that:
http://www.felipecypriano.com/2012/02/27/how-to-customize-uitabbar-on-ios-5/
This example is taken from that site:
Basically create a backgroundImage, selectionIndicatorImage, adjust the fonts as appropriate.
// Probably put these in your AppDelegate, setup the background and selection image
[[[self tabBarController] tabBar] setBackgroundImage:[UIImage imageNamed:#"background"]];
[[[self tabBarController] tabBar] setSelectionIndicatorImage:[UIImage imageNamed:#"selected"]];
// In your VC which is inside the tab bar
- (id)init {
self = [super initWithNibName:#"MyNibName" bundle:nil];
if (self) {
self.tabBarItem = [[UITabBarItem alloc] initWithTitle:#"The Title" image:nil tag:0];
[[self tabBarItem] setFinishedSelectedImage:[UIImage imageNamed:#"tab_icon"] withFinishedUnselectedImage:[UIImage imageNamed:#"tab_icon"]];
[[self tabBarItem] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor], UITextAttributeTextColor, nil] forState:UIControlStateNormal];
}
}

how to customize QLPreviewController's navBar and toolbar tintColor

QLPreviewController * preview = [[QLPreviewController alloc] init];
preview.dataSource = self;
preview.currentPreviewItemIndex = sender.tag;
preview.editing= YES;
[self presentModalViewController:preview animated:YES];
[preview release];
These two lines does not work for me. so be careful before writing these lines.
[preview.tabBarController.tabBar setTintColor:[UIColor blackColor]];
[preview navigationController].navigationBar setTintColor: [UIColor blackColor]];
Since iOS5 you can theme controls based on instance, globally or when contained by specific container classes. Since iOS6 the former method of subclassing QLPreviewController to set the tintColor of the UINavigationBar stopped working.
Consider one of the following as an example of a workaround that is compatible with iOS5 and iOS6:
Any UINavigationBar contained within a QLPreviewController:
[[UINavigationBar appearanceWhenContainedIn:[QLPreviewController class], nil]
setTintColor:[UIColor blackColor]];
or globally set the tintColor of all UINavigationBar instances within your app with:
[[UINavigationBar appearance] setTintColor:[UIColor blackColor]];
This same strategy works with the UITabBarController.
set style of UINavigationController with this line..
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
and for change the color of TabBar just Add the below code in viewWillAppear of your class
CGRect frame = CGRectMake(0.0, 0.0, self.view.bounds.size.width, 48);
UIView *v = [[UIView alloc] initWithFrame:frame];
[v setBackgroundColor:[UIColor colorWithRed:0.1 green:0.2 blue:0.6 alpha:0.8]];
[v setAlpha:0.5];
[[self.tabBarController tabBar] insertSubview:v atIndex:0];
[v release];
If you want to change the tintColor of the navigationBar you can push your QLPreviewController instead present it modally:
//i assume that you already have a navigationController
[[self navigationController] pushViewController:previewer animated:YES];
[self.navigationController.navigationBar setTintColor:[UIColor blackColor]];
For the bottom bar i think that is a UIToolbar not a UITabBar, probably you cant change the color (i dont know), but surely you can't call preview.tabBarController.tabBar.
I found a solution , though it is not the correct way but it works:
Make subclass of QLPreviewController
MyQLPreviewController.h
#interface MyQLPreviewController : QLPreviewController
#end
and in .m of that new subclass, copy the following code
#implementation MyQLPreviewController
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
UIToolbar *toolbar = [self getToolBarFromView:self.view]; //NOTE: Not the correct apperoach! could not think better solution, as iOS does not allow to access the toolbar properties in QLPreviewController
toolbar.barTintColor = [UIColor redColor];
}
- (UIToolbar *)getToolBarFromView:(UIView *)view
{
for (UIView *subView in view.subviews)
{
if ([subView isKindOfClass:[UIToolbar class]])
{
return (UIToolbar *)subView;
}
else
{
UIToolbar *toolBar = [self getToolBarFromView:subView];
if (toolBar)
{
return toolBar;
}
}
}
return nil;
}

Transparent UITabBarController with changeable view in background

I want to have a UITabBarController, which is has an alpha of 0.5, whose transparency allows you to see a view in the background. The background view has to be accesible and changeable.
I'm able to add the background using this technique: https://gist.github.com/1157542
It's a Category which adds a subview to the UITabBarController, and sends the subview to the back. However, because it's a category, I can't make the subview a property. So I can't really access it.
Is there a way to make this background view more flexible and accessible? So I could, for instance, add other subviews to it easily from any of the tab bar controller's view controllers?
Instead of a category, you should subclass UITabBarController. This will allow you to have finer control over the object. Here's an example of a subclass.
// MPCustomTabBar.h
#interface MPCustomTabBar : UITabBarController
- (void) setBackgroundImage:(UIImage *)image;
#end
// MPCustomTabBar.m
#interface MPCustomTabBar
- (void) setBackgroundImage:(UIImage *)image {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,480)];
imageView.backgroundColor = [UIColor colorWithPatternImage:i];
[[self view] addSubview:imageView];
[[self view] sendSubviewToBack:imageView];
[[self view] setOpaque:NO];
[[self view] setBackgroundColor:[UIColor clearColor]];
[imageView release];
}
#end
Now you can do all the customization you want, alloc and init your new subclass by something like this:
MPCustomTabBar *bar = [[MPCustomTabBar alloc] init];
A solution to my problem might be simply this..
In my AppDelegate, just before [self.window makeKeyAndVisible];
self.theImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image1.png"]];
[self.tabBarController.view insertSubview:self.theImage atIndex:0];
I can then easily change this image, in any of the tab bar controller's view controllers, like:
AppDelegate *appDelegate= (AppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.theImage.image = [UIImage imageNamed:#"image2.png"];
.. no categories required.
Here's what worked for me:
Make TabBar transparent (either by Storyboard or programmatically) by setting the Tint- and Background to Clear Color and Opaque to No.
The black background color is actually the window's colour. Assign the image you want to use as the background to the window itself:
UIImage *i = [UIImage imageNamed:#"main_background.png"];
UIColor *c = [[UIColor alloc] initWithPatternImage:i];
[self.window setBackgroundColor:c];

Change the background color of UINavigationBar

I'd like to change the background color of an UINvaigationBar and I used tintColor property but it's not changing the color. You can checkout the code below.
In my Appdelegate I create a UITabBarController
tabbar = [[UITabBarController alloc] init];
Then I create a UINavigationController and attach my UITableViewController to it
UINavigationController *myNavigation = [[UINavigationController alloc] initWithRootViewController:myViewController];
Then attached the UINavigationControllers to my tabbar like this
[tabbar setViewControllers:viewControllers]; //viewControllers is an array of UINavigationControllers
I tried setting the property tintColor in myAppdelegate like this
[[myNavigation navigationBar] setTintColor:[UIColor redColor]];
But this didn't work as expected and so I tried the same in my ViewController
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController.navigationBar setTintColor:[UIColor blackColor]];
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
self.navigationItem.title = #"Test";
}
And still nothing happens. Please checkout the image below to see how navigation bar looks now.
Appreciate your help.
Cheers
Jugs
As a work around you may can use image on place of tint color please check below code for same.
if ([myNavigation respondsToSelector:#selector(setBackgroundImage:forToolbarPosition:barMetrics:)]) {
[myNavigation setBackgroundImage:[UIImage imageNamed:BAR_IMAGE_NAME] forbarMetrics:UIBarMetricsDefault];
}else {
[myNavigation insertSubview:[[[UIImageView alloc] initWithImage:[UIImage imageNamed:BAR_IMAGE_NAME]] autorelease] atIndex:0];
}

Change NavigationBar Title (font and color) in different View Controllers

I was trying to customize the look of the Navigation Bar Title in my app.
I had to build a Custom Navigation Controller (not just for this issue), so I thought to override the setTitle function like this
- (void)setTitle:(NSString *)title
{
NSLog(#"SETTING TITLE %#", title);
[super setTitle:title];
UILabel *titleView = (UILabel *)self.navigationBar.topItem.titleView;
NSLog(#"title view is %#", titleView);
if (!titleView) {
titleView = [[UILabel alloc] initWithFrame:CGRectZero];
titleView.backgroundColor = [UIColor clearColor];
titleView.font = [UIFont fontWithName:#"TradeGothicLTStd-Bold-Accent-Accent" size:20];
titleView.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5];
titleView.textColor = [UIColor whiteColor];
self.navigationBar.topItem.titleView = titleView;
[titleView release];
}
titleView.text = [title uppercaseString];
[titleView sizeToFit];
self.navigationBar.tintColor= [UIColor colorWithRed:130.0f/255.0f green:120.0f/255.0f blue:90.0f/255.0f alpha:1.0f];
}
Everything was working as expected.
Now the issue is that inside a navigation controller I have a TableView. When clicking a cell, the app drills down to another TableView, which should have again the custom title.
this is the code for the didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSString *category_id = [[managedObject valueForKey:#"category_id"] stringValue];
NSString *name = [[[managedObject valueForKey:#"name"] description] capitalizedString];
CategoryViewController *category = [[CategoryViewController alloc] initWithNibName:#"CategoryViewController" bundle:nil];
category.category_id = category_id;
category.name = name;
category.managedObjectContext = self.managedObjectContext;
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:category animated:YES];
[category release];
}
....but when the selected view appears, it shows with the standard font.
EDIT
I noticed that if in the second view I set the title in the viewDidAppear method, it happens something different.
if I write
- (void)viewDidAppear:(BOOL)animated
{
self.navigationController.title = name;
[super viewDidAppear:animated];
}
...the title in the navigation bar has the right (custom) font, but the title is like appearing only when the view has finished to slide in....?
Again, I'm obviously doing something wrong here, any help would be appreciated :)
Thx for your time!
The code snippet
[[UINavigationBar appearance] setTintColor:[UIColor colorWithRed:107.0/256.0 green:145.0/256.0 blue:35.0/256.0 alpha:1.0]];
Will change the color of the navigation bar of whole app.
Just place it in Appdelegate's didFinishLauncing method.
Since iOS 5 you can do that directly with an UINavigationBar
https://developer.apple.com/library/ios/#documentation/UIKit/Reference/UINavigationBar_Class/Reference/UINavigationBar.html
Customizing the Appearance of a Navigation Bar
Just set the titleTextAttributes dictionary
For iOS7 and later the solution is this:
[UINavigationBar appearance].barTintColor = [UIColor redColor];
paste this code in the AppDelegate (didFinishLaunching:) method, and everything should work just fine.
Instead of setting that in viewDidAppear method, please do that in viewDidLoad method.