How to let a overlay view turn/rotate with the underlying views? - ios

The code below works fine in one of two possible landscape orientations but when i turn the device 180 to the other lanscepe orientation the images i load are bottom up compared with the views that are underneath.
So what I have is a view (to overlay over the whole screen, that has images on it) created in code on-top of views created on a storyboard.
And the QUESTION IS : Can the top left corner of the semi-transparent-overlay-view be drawn at the same place that the top left corner of where a underlying view is?. I need the overlay view to turn with underlying views.
Here I let the view cover (overlay) the whole screen
self.overlayView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0,[[UIScreen mainScreen] bounds].size.width,[[UIScreen mainScreen] bounds].size.height)];
Then I load up the images I like to show on the view.
UIImage* image = [UIImage imageNamed:#"image.png"];
and here I set the image
[overlayView setImage:image];
I have tried everything with orientation with no luck. Note that my app auto-rotates 360° so the status bar is always up top.
Hope this makes sens to somebody!
Edit: Here is the whole code used
UIWindow* keyWindow = [UIApplication sharedApplication].keyWindow;
self.overLayView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0,[[UIScreen mainScreen] bounds].size.width,[[UIScreen mainScreen] bounds].size.height)];
[overLayView setImage:[UIImage imageNamed:#"someImage1.png"]];
overLayView.tag = 1; //Used to remove the view in another function
overLayView.backgroundColor = [UIColor colorWithWhite:0.5 alpha:0.5]; //Semi transparent
CGRect viewFrames = CGRectMake([[UIScreen mainScreen] bounds].size.width - 100, [[UIScreen mainScreen] bounds].size.height - 100, 75, 75);
self.exitHelpView = [[UIImageView alloc] initWithFrame:viewFrames];
[self.exitHelpView setImage:[UIImage imageNamed:#"imageOfXUsedToCloseWhenClicked.png"]];
self.exitHelpView.tag = 2; //Used to remove the view in another function
[keyWindow addSubview:overLayView]; //The view covering the whole screen
[keyWindow addSubview:self.exitHelpView]; //Image of an X
And in my .h file
#property (strong, nonatomic) IBOutlet UIImageView* overLayView;
#property (strong, nonatomic) IBOutlet UIImageView* exitHelpView;

Things you add to the UIWindow will not respect device rotations. This is one of the big features of the UIViewController--responding to rotation events automatically. If you can't find a way for it to work by adding the view to a UIViewController's view hierarchy, then you'll need to manually listen for rotation events and programmatically adjust the positioning of your UIView.

Related

How to change the size of your custom UIView in iOS

I want to use custom view as a toolbar at bottom of my view controller and then design it in my own way. I am using UIView for this purpose and then add as a subview. Somehow, the height of my custom tool bar is not changing. Even, I turned off constraints for it but somehow, it auto adjusts. How can, I do this? Below is my code snippet.
//CameraActivity.h class
#interface CameraActivity : UIViewController
//Custom UIView.
#property (nonatomic, strong) UIView *toolbar;
#end
//CameraActivity.m class, in viewDidLoad.
_toolbar.translatesAutoresizingMaskIntoConstraints = YES;
[self.view removeConstraints:self.view.constraints];
[_toolbar removeConstraints:_toolbar.constraints];
CGRect frame = CGRectMake(0, [[UIScreen mainScreen] bounds].size.height - 44, [[UIScreen mainScreen] bounds].size.width, 150);
_toolbar = [[UIView alloc]initWithFrame:frame];
[_toolbar setBackgroundColor:[UIColor colorWithRed:116.0/255.0 green:174.0/255.0 blue:220.0/255.0 alpha:0.75]];
[self.view addSubview:_toolbar];
Make an outlet of your UIView height constraint. Then try to change its height based on device's type as follow:-
In ViewController.h file, Create an outlet:-
#property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewHeightConstraint;
In ViewController.m file, Change your height's constraint like this:-
if (Device is iPhone 4s) {
viewHeightConstraint.constant = 30.0; //Your desired height
}
else if (Device is iPhone 5 || Device is iPhone 5s || Device is iPhone 5c) {
viewHeightConstraint.constant = 40.0; //Your desired height
}
else if (Device is iPhone 6) {
viewHeightConstraint.constant = 50.0; //Your desired height
}
else if (Device is iPhone 6 Plus) {
viewHeightConstraint.constant = 60.0; //Your desired height
}
Happy Coding!!
Before creating (i.e _toolbar = [[UIView alloc]initWithFrame:frame];) your view toolbar, using it will cause this issue.
Hence, change the line order to this :
CGRect frame = CGRectMake(0, [[UIScreen mainScreen] bounds].size.height - 44, [[UIScreen mainScreen] bounds].size.width, 150);
_toolbar = [[UIView alloc]initWithFrame:frame];
_toolbar.translatesAutoresizingMaskIntoConstraints = YES;
[self.view removeConstraints:self.view.constraints];
[_toolbar removeConstraints:_toolbar.constraints];
[_toolbar setBackgroundColor:[UIColor colorWithRed:116.0/255.0 green:174.0/255.0 blue:220.0/255.0 alpha:0.75]];
[self.view addSubview:_toolbar];
Also I suggest setting frame must done in
-(void) viewDidLayoutSubviews beacause viewDidLoad is not a good place for this! so,
-(void) viewDidLayoutSubviews
{
_toolbar.frame = CGRectMake(0, [[UIScreen mainScreen] bounds].size.height - 44, [[UIScreen mainScreen] bounds].size.width, 150);
}
I added UIView from objects library instead of adding it programmatically and then sets its width according to screen width of device and height to constant. Also assigned some constraints solve my problem.
//CameraActivity.h class
#interface CameraActivity : UIViewController
//This time not custom UIView but IBOutlet.
#property (nonatomic, strong) IBOutlet UIView *toolbar;
#end
//CameraActivity.m class
#import "CameraActivity.h"
#implementation CameraActivity
-(void)viewDidLoad
{
[super viewDidLoad];
//Get your device screen width.
CGFloat width = [UIScreen mainScreen].bounds.size.width;
_toolbar.frame = CGRectMake(0, 44, width, 150);
}

iOS: Is there a way to make a viewcontroller look inactive by having everything grayed out?

I want my ViewController and every object appear inactive by having it all grayed out (kind of like how the UIAlertView popup grays out everything in the background). I do not want to have to manually gray out every object there is.Is there an easy way to make this work?
UIView *grayView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
grayView.backgroundColor = [UIColor colorWithWhite:0.5 alpha:0.5];
[self.view addSubview:grayView];
You can mess with the white and alpha values to get exactly what you want, but that should put a gray tint over everything in your view controller's view.
As Patrick Goley pointed with his good answer - just put a gray UIView with alpha between 0.5 - 0.75 above your original view. But this method will disable all the user interactions with its subviews (buttons,etc). If you want to preserve user interactions with the elements but nevertheless mark the view as "inactive", you should subclass the view which you will put above your original view (which you want to mark as inactive) and in this subclass override this method:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
// Original "inactive" UIView will now respond to touch events if return NO:
return NO;
}
This code will cover also any parent controller: UINavigationController | UITabBarController.
Don't forget #import "AppDelegate.h".
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
UIView *grayView = [[[UIView alloc] initWithFrame:appDelegate.window.bounds] autorelease];
grayView.backgroundColor = [UIColor colorWithWhite:0.6 alpha:0.8];
[appDelegate.window addSubview:grayView];
I prefer to add a UIView that has a black background, and then lower the alpha.
UIView *grayView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
grayView.backgroundColor = [UIColor blackColor];
[grayView setAlpha:0.65];
And then do not forget to add the subview to your main view
[self.view addSubView:grayView];
Yes:
Set the alpha of the view
[self.view setAlpha:0.5];

iOS: Animate splash screen out on top of status bar

OK, I get the concept of adding a UIImageView as soon as the app launches, and animating it out to fake the splash animation. However, the status bar interferes.
I need a UIImageView on top of everything, including the status bar, and while it fades away, the app is shown with the status bar. Hence, settings the Status bar initially hidden, then animating it in is not a viable option.
What you require is a second UIWindow with a windowLevel of UIWindowLevelStatusBar or higher. You would create two UIWindow objects in your application delegate, one with your regular view hierarchy, the other with the image, and animate the second to fade out (or however else you need to animate). Both windows should be visible, with the splash window being on top.
This approach is complicated, as you might have problems with rotation, depending on your regular view hierarchy. We've done this in our software, and it works well.
EDIT:
Adapted Solution (window approach, very simple):
UIImageView* splashView = [[UIImageView alloc] initWithImage:[UIImage imageWithBaseName:#"Default"]];
[splashView sizeToFit];
UIViewController* tmpVC = [UIViewController new];
[tmpVC.view setFrame:splashView.bounds];
[tmpVC.view addSubview:splashView];
// just by instantiating a UIWindow, it is automatically added to the app.
UIWindow *keyWin = [UIApplication sharedApplication].keyWindow;
UIWindow *hudWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0.0f, -20.0f, keyWin.frame.size.width, keyWin.frame.size.height)];
[hudWindow setBackgroundColor:[UIColor clearColor]];
[hudWindow setRootViewController:tmpVC];
[hudWindow setAlpha: 1.0];
[hudWindow setWindowLevel:UIWindowLevelStatusBar+1];
[hudWindow setHidden:NO];
_hudWin = hudWindow;
[UIView animateWithDuration:2.3f animations:^{
[_hudWin setAlpha:0.f];
} completion:^(BOOL finished) {
[_hudWin removeFromSuperview];
_hudWin = nil;
}];
Finally, credit goes to this guy.
A more simple approach would be to launch your application with the status bar hidden, have the view you would like to animate on the top of the view hierarchy, and after the animation is finished, display the status bar using [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide]
You can add a subview to the App's UIWindow. Set the Y coordinate of the UIImageView's frame to -20 pixels in order to handle the status bar.
Add the Default PNG image to your window and tag it:
static const NSInteger kCSSplashScreenTag = 420; // pick any number!
UIImageView *splashImageView;
// Careful, this wont work for iPad!
if ( [[UIScreen mainScreen] bounds].size.height > 480.0f ) // not best practice, but works for detecting iPhone5.
{
splashImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Default-568h"]];
}
else
{
splashImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Default"]];
}
splashImageView.frame = CGRectMake(0.0f, -20.0f, splashImageView.image.size.width, splashImageView.image.size.height);
splashImageView.tag = kCSSplashScreenTag;
[self.window addSubview:splashImageView];
[splashImageView release];
[self _fadeOutSplaceImageView];
Then fade it out
- (void)_fadeOutSplashImageView
{
UIView *splashview = [self.window viewWithTag:kCSSplashScreenTag];
if ( splashview != nil )
{
[UIView animateWithDuration:0.5
delay:0.0
options:0
animations:^{
splashview.alpha = 0.0f;
}
completion:^(BOOL finished) {
[splashview removeFromSuperview];
}];
}
}

Multiple UIScrollViewControllers on the same window, some not showing their views

I am trying to display 3 UIScrollViewControllers in the same window as 3 horizontal stripes 3 times the screen wide scrolling indipendently. The code to achieve this is below but for some reason it doesn't work, showing only the upper stripe.
With the help of the additional white background view I placed on the window I can see the other 2 regions of the screen are scrollable as well, but for some reason their background color is not showing up...I can't figure out why.
Here is the code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Creating the window programmatically
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
CGRect bounds = [self window].bounds;
float x = bounds.origin.x;
float y = bounds.origin.y;
float w = bounds.size.width;
float h = bounds.size.height;
CGRect upperFrame = CGRectMake(x,y,w,h/3);
CGRect middleFrame = CGRectMake(x,y + h/3,w,h/3);
CGRect lowerFrame = CGRectMake(x, y + 2 * h/3, w, h/3);
// Creating the scroll view which will contain the 3 views
UIScrollView *upperScrollView = [[UIScrollView alloc] initWithFrame:upperFrame];
UIScrollView *middleScrollView = [[UIScrollView alloc] initWithFrame:middleFrame];
UIScrollView *lowerScrollView = [[UIScrollView alloc] initWithFrame:lowerFrame];
// ContentSize should be wide enough for 3 pages
[upperScrollView setContentSize:CGSizeMake(3 * w, h/3)];
[middleScrollView setContentSize:CGSizeMake(3 * w, h/3)];
[lowerScrollView setContentSize:CGSizeMake(3 * w, h/3)];
// Enforce the display of only one page at a time
[upperScrollView setPagingEnabled:YES];
[middleScrollView setPagingEnabled:YES];
[lowerScrollView setPagingEnabled:YES];
// UPPER SCROLLVIEW
// This will be the first view (red)
UIView *redViewU = [[UIView alloc] initWithFrame:upperFrame];
[redViewU setBackgroundColor:[UIColor redColor]];
// The second view will start horizontally when the first view ends
upperFrame.origin.x += w;
// This will be the second view (green)
UIView *greenViewU = [[UIView alloc] initWithFrame:upperFrame];
[greenViewU setBackgroundColor:[UIColor greenColor]];
// The third view will start horizontally when the second view ends
upperFrame.origin.x += w;
// This will be the third view (blue)
UIView *blueViewU = [[UIView alloc] initWithFrame:upperFrame];
[blueViewU setBackgroundColor:[UIColor blueColor]];
// Adding the 3 views to the scroll view
[upperScrollView addSubview:redViewU];
[upperScrollView addSubview:greenViewU];
[upperScrollView addSubview:blueViewU];
// Now creating the view controller, father of the scrollview
UIViewController *upperViewController = [[UIViewController alloc] init];
[upperViewController setView:upperScrollView];
// MIDDLE SCROLLVIEW
// This will be the first view (red)
UIView *redViewM = [[UIView alloc] initWithFrame:middleFrame];
[redViewM setBackgroundColor:[UIColor redColor]];
// The second view will start horizontally when the first view ends
middleFrame.origin.x += w;
// This will be the second view (green)
UIView *greenViewM = [[UIView alloc] initWithFrame:middleFrame];
[greenViewM setBackgroundColor:[UIColor greenColor]];
// The third view will start horizontally when the second view ends
middleFrame.origin.x += w;
// This will be the third view (blue)
UIView *blueViewM = [[UIView alloc] initWithFrame:middleFrame];
[blueViewM setBackgroundColor:[UIColor blueColor]];
// Adding the 3 views to the scroll view
[middleScrollView addSubview:redViewM];
[middleScrollView addSubview:greenViewM];
[middleScrollView addSubview:blueViewM];
// Now creating the view controller, father of the scrollview
UIViewController *middleViewController = [[UIViewController alloc] init];
[middleViewController setView:middleScrollView];
// LOWER SCROLLVIEW
// This will be the first view (red)
UIView *redViewL = [[UIView alloc] initWithFrame:lowerFrame];
[redViewL setBackgroundColor:[UIColor redColor]];
// The second view will start horizontally when the first view ends
lowerFrame.origin.x += w;
// This will be the second view (green)
UIView *greenViewL = [[UIView alloc] initWithFrame:lowerFrame];
[greenViewL setBackgroundColor:[UIColor greenColor]];
// The third view will start horizontally when the second view ends
lowerFrame.origin.x += w;
// This will be the third view (blue)
UIView *blueViewL = [[UIView alloc] initWithFrame:lowerFrame];
[blueViewL setBackgroundColor:[UIColor blueColor]];
// Adding the 3 views to the scroll view
[lowerScrollView addSubview:redViewL];
[lowerScrollView addSubview:greenViewL];
[lowerScrollView addSubview:blueViewL];
// Now creating the view controller, father of the scrollview
UIViewController *lowerViewController = [[UIViewController alloc] init];
[lowerViewController setView:lowerScrollView];
// A white background view to see at least the scroll indicators
UIView *whiteView = [[UIView alloc] initWithFrame:bounds];
[whiteView setBackgroundColor:[UIColor whiteColor]];
// Finally the window will hold the view controllers' views
[[self window] addSubview:whiteView];
[[self window] addSubview:upperViewController.view];
[[self window] addSubview:middleViewController.view];
[[self window] addSubview:lowerViewController.view];
// Displaying the window
[self.window makeKeyAndVisible];
return YES;
}
Solved: after succeeding doing the same thing with IB I realized that for some reason the views inside the UIScrollView want RELATIVE x,y coordinates for their frames, not ABSOLUTE.
Changing the frames of the views in the above code with the following (the same for every UIScrollView):
CGRect redViewFrame = CGRectMake(x,y,w,h/3);
CGRect greenViewFrame = CGRectMake(w,y,w,h/3);
CGRect blueViewFrame = CGRectMake(2 * w,y,w,h/3);
solved the issue, and now I can see the 3 scrolling backgrounds.
Hope it helps someone else :) I am done, for now.

iOS UIScrollView in UIView

I have a little bit specific question. It might not matter for most people but I have had to deal with it and I had to solve the issue described below. I tried to find some information about it using Google and the Apple SDK documentation but did not succeed.
I was a designing a screen where there were many images in horizontal scrolls. There three three same scrolls. Every scroll had title. I have implemented custom class derived from UIView and placed there UIScrollView for scroll and UILabel for title text:
#interface MyView : UIView {
UIScrollView *iScrollView;
UIView *iTitleView;
}
I then put objects of this class on the view of a UIViewController:
#implementation MyViewController
- (void) viewDidLoad {
[super viewDidLoad];
...
iScrollViewTop = [[MyView alloc] init];
[self.view addSubview:iScrollViewTop];
...
}
#end
When I filled the internal scroll view with images and ran my application it looked OK. But there was some strange behavior. First, scroll did not have bounces as if I had set
iScrollView.bounces = NO;
and second, when I swiped to scroll, after the scroll stopped, the scroll bar did not disappear within one second. It was strange for me, because when I usually create a UIScrollView and add it to the UIViewController's view it has bounces and scroll bar disappears immediately when it stops. I tried to change UIScrollView's properties, such as directionalLockEnabled, pagingEnabled, canCancelContentTouches, delaysContentTouches, decelerationRate and others. In fact, I have tried to change almost all properties of UIScrollView but I could not get the scroll bars to immediately disappear.
If I try to add UIScrollView instead MyView to the UIViewController.view, it bounces and scroll bar disappears immediately after it stops. Also I get correct behavior if I subclass MyView from UIScrollView but in this case I cannot manage the title label because it scrolls together with other content.
So here are my questions:
Do you know why I am seeing this behavior?
How can I get "usual" behavior for scroll encapsulated by UIView?
ok, hacky code follows, so ignore all my other issues, but follow this pattern (westie.jpg = image that was 360x200)
#interface MyView : UIView
{
UIScrollView *sv;
UILabel *l;
}
-(MyView*)initWithFrame:(CGRect)frame;
#end
#implementation MyView
-(MyView*)initWithFrame:(CGRect)frame;
{
self = [super initWithFrame:frame];
sv = [[UIScrollView alloc] initWithFrame:CGRectMake(0,0,360,200)];
sv.scrollEnabled = YES;
sv.contentSize = CGSizeMake(360*3,200);
[self addSubview:sv];
UIImage *i1 = [UIImage imageNamed:#"westie.jpg"];
UIImageView *iv1 = [[UIImageView alloc] initWithImage:i1];
iv1.frame = CGRectMake(360*0, 0, 360, 200);
[sv addSubview:iv1];
UIImageView *iv2 = [[UIImageView alloc] initWithImage:i1];
iv2.frame = CGRectMake(360*1, 0, 360, 200);
[sv addSubview:iv2];
UIImageView *iv3 = [[UIImageView alloc] initWithImage:i1];
iv3.frame = CGRectMake(360*2, 0, 360, 200);
[sv addSubview:iv3];
l = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 100, 20)];
l.text = #"Hello World";
l.backgroundColor = [UIColor blueColor];
[self addSubview:l];
return self;
}
#end
later, in your outer view creation:
[window addSubview:[[MyView alloc] initWithFrame:CGRectMake(0, 20, 360, 200)]];

Resources