I'm trying to set a background image for the entire app following this suggestions: set background image for entire iPhone / iPad app
But in iOS 7 (don't know about other versions) it doesn't work well at all.
I've created a simple repository so you can understand better what's is going on.
There are some glitches in the transitions.
When you tap on a row in the first view, the second view is pushed into the navigation controller but there's a weird effect. It seems that the rows transparency played into this.
Also the other problem is when you turn back to the previous view controller there's a subtle shadow of the view controller that is popped from the navigation stack. As I stated before you can get what I mean by running the simple Xcode project.
Repo: https://github.com/socksz/FixedBackgroundImage
Any ideas? I've already tried to set the background image for each controller but it isn't what I want because in that way the image "overlaps" the previous background image and it's not the desired effect.
Hope I explained well.
EDIT 1
It seems that the problem occurs because of the way iOS 7 manages the transitions between two view controllers. In you are in the second view controller and try to turn to the previous controller with the swipe gesture you can see that as you begin the gesture the first controller appears below the second controller (the controller you're seeing) and, since the UITableViewCells have transparent backgrounds, you already see the first controller. Actually I'm afraid that there's not a solution. What a pity that I cannot have a fixed background image without setting the background image on each controller.
I had a requirement in an iPhone app to set the background image of a page based on a user's preferences. The way I dealt with it was to add a UIImageView with the background image as a sub-view of the view, like so -
UIImageView *bgImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background-image"]];
bgImageView.frame = self.view.bounds;
[self.view addSubview:bgImageView];
[self.view sendSubviewToBack:bgImageView];
I cloned your Github repository and added the above piece of code in viewDidLoad of both the view controllers. I also added the following line of code in the same method -
self.tableView.opaque = NO;
I commented out the code in didFinishLaunchingWithOptions where you set the background color. With these changes, the artifacts while navigating between view controllers are gone. I tested with iPhone Retina (3.5-inch) as well as iPhone Retina (4-inch) simulators.
The reason why the artifacts are seen while navigating to and from the ViewController in the storyboard require some investigations. My suggestion may or may not work for your requirements, but, you can try this as a solution.
P.S. The method requires some tweaks to autolayout constraints.
You Just have to write only one line in
appdelegate.m file's applicationdidFinishLaunchingWithOptions: method
[self.window setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"MainBackground.png"]]];
and put below line in every screen's viewDidLoad method
[self.view setBackgroundColor:[UIColor clearColor]];
I did not find a way to put this globally. However, and you will probably find this useful for static/fixed images (instead of the moving images you get when you set the backgroundColor property), Use the backgroundView property for every screen.
self.tableView.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background.jpg"]];
I did it myself by creating a UtilTableViewController which does all theme and custom things I need it to do, putting this code there, then subclassing all my views. It's not a globally set image, but I only have to set it once and all of my TableViews will use it.
Put this code in your appdelegate.m file applicationDidFinishLaunching method.
UINavigationController *navigationController = [[UINavigationController alloc]initWithRootViewController:rootViewController];
windowBackground=[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"background_window.png"]];
windowBackground.frame=CGRectMake(0, 0, 320, 568);
[window addSubview:windowBackground];
[windowBackground release];
window.frame = CGRectMake(0, 0, window.frame.size.width,568);
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
Add this code in every viewController class viewDidLoad method.
self.view.backgroundColor = [UIColor clearColor];
Late post...
If you are using a NavigationController you might try overriding the TopViewController "get" portion to automatically set the BackGroundColor to your image. Appologies, we use Xamarin which converts from C# to objective C for us (not sure of the specific syntax). In C# it will look something like this within your NavigationController class.
public override UIViewController TopViewController
{
get
{
if (base.TopViewController.View.BackgroundColor != "Your Image")
{
base.TopViewController.View.BackgroundColor = "Your Image";
}
return base.TopViewController;
}
}
Write this code in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method
UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"YourImageName.png"]];
self.window.backgroundColor = background;
you can set the background image through below code ... wew can put this code in viewdidload method in viewcontroller.m file
[self.window setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"bg.png"]]];
Related
When an iOS app rotates it will reveal a black background when the app is between portrait and landscape. Is it possible to change this color from the default black to white? Changing the UIWindow's background color will not help. Here is an example of the black background in Safari during rotation:
I have done something similar but I couldn't find the source now, but here is the idea:
Create and add a significantly larger view as backing view and center it.
Add the UIWebView as subview of this large view whose background is white.
Re-position the center of the UIWebView, too.
You can do this way:
Add a UIViewController and set it as initial VC (in screenshot it is MainVC).
Add two UIViewContainer: first for holding your background view , and second for your other vcs.
Override viewDidLayoutSubviews in implementation file of background VC (in this case the .m file of red VC)
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
//Some hardcode :)
self.view.frame = CGRectMake(-100, -100, 1136, 1136);
}
After doing this you will have something like this:
I know this is not the best solution, but you can do this way until you find the best one.
I got the same issue. As I understand that you want to remove the black background. The easiest solution that I used is set you window clipsToBounds = true instead of your rootViewController.
window?.clipsToBounds = true
You can solve the problem by adding empty general view controller with oversized bounds into your root viewController and make it the lowest in the view hierarchy:
CGFloat length = 2*MAX(rootViewController.view.bounds.size.height, rootViewController.view.bounds.size.width);
UIView *oversizedBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, length, length)];
oversizedBackgroundView.center = vc.view.center;
oversizedBackgroundView.backgroundColor = [UIColor whiteColor];
rootViewController.view.clipsToBounds = NO;
[rootViewController.view addSubview:oversizedBackgroundView];
[rootViewController.view sendSubviewToBack:oversizedBackgroundView];
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
The key point here is to set clipsToBounds to NO
I am pushing a view controller via:
[self.navigationController pushViewController:[[UIViewController alloc] init] animated:YES];
But the animation lags/pauses a for half a second mid way through. The animation is not complete. Here's the gif;
With out more detail I can think of 2 possible problem with that.
Is there Shadow added in code to the view that will be covered by the new ViewController. If it is the case, use ShadowPath or an translucent view instead (the property Shadow is expensive while animating, been there done that)
Is the backgroundColor of new ViewController "clearColor" ? I've seen strange rendering problem with that kind of thing.
Try:
UIViewController *vc = [[UIViewController alloc] init];
vc.view.backgroundColor = [UIColor whiteColor];
[self.navigationController pushViewController:vc animated:YES];
That is the 2 possible problems I can think of the top of my head with so few detail.
Never rely on the default background color, it has change with iOS version and is not consistant across controls and can even be different if the view is created in code or from a Xib (in the same iOS version).
In app delegate, set your window's background color to white.
window?.backgroundColor = .white
Also in the the pushed view controller, set its view to white.
view.backgroundColor = .white
I experienced the same issue when programmatically embedding my view controller in a UINavigationController.
While setting the background color as suggested by VinceBurn solved the pausing, it made the entire animation white, fading in the actual content only when the animation finished.
For me the problem was solved by making sure the content was correctly sized in -viewDidLoad.
In my app, I use a navigation controller to switch between different views. Each of my views has an image for a background, but when I go from one to another, a little bit of white shows up in between them while transitioning. Is there a way to change that?
In the Table View Class I have this in the viewDidLoad:
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"parchment.png"]];
self.tableView.backgroundColor = [UIColor clearColor];
self.tableView.backgroundView = imageView;
[imageView release];
In the detail view I have just a standard loadrequest for an HTML. The HTML itself has the code for the parchment paper to be a background image. Here is what they look like:
But, going back from the detail view with the verses to the table view, I get this:
In your:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
method of AppDelegate. assign background color to window like this:
self.window.backgroundColor = [UIColor blackColor]; // or anycolor
Have you tried changing the background color property of the view?
[[self view] setBackgroundColor:[UIColor redColor]];
The issue was in the viewWillDisappear of the web view controller. It was set to change webpage to about:blank page, which made it white. I got rid of that code, and it worked fine.
Try to set the background color of the navigation controller's view.
In your navigation controller's root view controller (I guess it's the table view controller)
self.navigationController.view.backgroundColor = // any color ;
I'd like to place an ADBannerView object onto my UITableView screen statically, what means that I want it to always stay above my toolbar (self.navigationController.toolbar), even when the user is scrolling the tableview. I've solved this by adding by ADBannerView as a subview to my toolbar and given it negative values for the frames origin:
[self setBannerViewSize];
[self.navigationController.toolbar addSubview:bannerView];
The only problem is: I can't click and open the iAd this way - I can see the banner but nothing happens when I tap on it.
Since I'm also using a refreshControl, the option to use a UIViewController instead of UITableViewController and add a tableView manually wouldn't work for me. Is there any other way I can get my ADBannerView statically showing in my table view controller AND still being tappable?
Thank you in advice!
Yay!! After all I succeeded in solving this (really annoying) problem by myself (and a lot of reading around)!
First, I found this really world-changing post. Basically this post handles with the topic that a UITableViewController uses self.view for its tableView property, so overriding the tableView property (or synthesizing it manually) plus giving self.view a new view (from application) and adding tableView as its subview would make it possible to reach the real superview of tableView.
But this still didn't solve my problem, although I was sure it would, because it all made sense. My bannerView appeared in the right place (and was fixed) but it still didn't do anything when clicked. But there was a second minor thing I didn't know about:
As I read in this post the superview of a subview doesn't only have to be userInteractionEnabled but also have a non-transparent backgroundColor. Because my superviews background color was set to [UIColor clearColor] it all didn't work - but setting its backGroundColor to e.g. blackColor solved the whole problem: the bannerView got finally tappable! :)
So, my code is now looking like this:
#synthesize tableView;
- (void)viewDidLoad
{
[super viewDidLoad];
if (!tableView && [self.view isKindOfClass:[UITableView class]]) {
tableView = (UITableView *)self.view;
}
self.view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
self.tableView.frame = self.view.bounds;
[self.view addSubview:self.tableView];
[self resizeTableToFitBanner];
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:bannerView];
// some other code
}
BannerViewController in Apple's iAdSuite sample code solves this problem very elegantly:
https://developer.apple.com/library/ios/samplecode/iAdSuite/Introduction/Intro.html
I think you should use a container view, and set things up in IB. You can add a tool bar and ADBannerView to the bottom of the view of your navigation controller's root view controller. Fill the rest of the space with a container view - this will give you an embedded view controller automatically. You should delete this one and then drag in a tableViewController and control drag from the container view to the tableViewController to hook up the embed segue.
I have a Navigation Controller as the root of my app and I am using the appearance proxy to customise the look on iOS 5, but for iOS 4 I was hoping to use a category to override drawRect:, this was fine, except that all the Navigation bars were affected as you would expect from a category.
I don't want to tamper with the "system" popups, such as the Mail composer, or the SMS composer, I want their bars to stay blue and system-like.
I Tried to create my own UINavigationController with it's xib and change the class of the NavigationBar to my custom sub lass of UINavigationBar. But the results are not taking affect at all on screen.
I am aware of the following post but couldn't get any solutions to run as expected.
How to subclass UINavigationBar for a UINavigationController programmatically?
My first attempt which does work but uses an undocumented setNavigationBar: method:
_myNavigationController = [[UINavigationController alloc] initWithRootViewController:someVC];
if([[BT_NavigationController class] respondsToSelector:#selector(appearance)]){
// some iOS 5 magic in here !
[_myNavigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"topbar.png"];
}else{
// Probably looking at app store refusal
CustomBar * bar = [[CustomBar alloc] init];
// [_myNavigationController setNavigationBar: bar];
[bar release];
}
[parentView presentModalViewController:_myNavigationController animated:YES];
To avoid that I created a UINavigationController, which I also had a xib for, reassigning the class of the navigation bar to my custom class, but placing breakpoints in drawRect: method, I can see that this isn't being called.
Why would that be, it seems that my code is not loading the nib, and therefore not realising the nab bar should be my custom class and not the UINavigationBar.
Any tips would be helpful, thanks.
If your modification is just about adding an image, you can simply insert it from the view controllers you want to customize:
UIImageView *bgImageView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"topbar.png"]] autorelease];
[self.navigationController.navigationBar addSubview:bgImageView];
You have to tweak a little based on what other elements you have in your UINavigationBar for your UIImageView to be at the lowest index of the subviews but still above the background. Worked for us.
Good luck.