How to add QLPreviewController as Subview in objective C - iOS8 - objective-c

In previous iOS versions I used to add the QLPreviewController as a subview. It is very handy to use my own app headers and navigation bar but in iOS 8 it adds a white space just below the header. It is the space for its own navigator bar.
You can see the attached img:
I use this code:
QLPreviewController *previewController = [[QLPreviewController alloc] init];
previewController.dataSource = self;
previewController.delegate = self;
previewController.currentPreviewItemIndex = 0;
previewController.view.frame = CGRectMake(0, 0, self.containerView.frame.size.width, self.containerView.frame.size.height);
[self addChildViewController:previewController];
[previewController didMoveToParentViewController:self];
[self.containerView addSubview:previewController.view];
How can i mantain the iOS7 funcionality? I only want to hide the qlpreviewcontroller navigationbar
Thanks

I'm solving the EXACT same problem. The only solution I found so far is the following:
// qlController.view.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds));//self.view.bounds;
// qlController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addChildViewController:qlController];
[self.view addSubview:qlController.view];
NSDictionary *bindings = #{#"qlPreviewController": qlController.view};
qlController.view.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[qlPreviewController]|" options:0 metrics:nil views:bindings]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[qlPreviewController]|" options:0 metrics:nil views:bindings]];
[qlController didMoveToParentViewController:self];
Commented lines are legacy code, that worked perfectly on iOs7. The main idea is stop using spring and struts and start using auto layout. Results looks good enough, but still there are some problems with rotations.
Works good:
Iphone 4s/5/6/6+ iOs7 portrait + landscape, iOs8 portrait
IPad all models iOs7,8 portrait + landscape
Works bad:
Iphone 4s/5/6/6+ iOs8 landscape : has some spacing between navBar and content. I think it is problem with Apple's QLPreviewController rather than my code.

Related

Translucent Viewcontroller over another Viewcontroller with different Orientation behaviour

For an app targeted at both iOS 7 and iOS 8, I'm using two ViewControllers which should have the following characteristics:
ViewController 1 (VC1) is in Portrait Mode
VC1 created ViewController 2 (VC2) which is in Landscape mode
VC2 has a translucent background so that VC1's contents are visible
I've referred to IOS 7: Transparent Viewcontroller Background over another Viewcontroller with different Orientation behaviour but the solution provided does not work. On iOS 8, I can either get landscape orientation or transparency for VC2 but not both
Here's what I'm doing:
self.view.backgroundColor = [UIColor clearColor];
UILabel* label = [[UILabel alloc] initWithFrame:self.view.frame];
label.text = #" I'M VC1";
[self.view addSubview:label];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
LandscapeViewController* lvc = [[LandscapeViewController alloc] init];
self.modalPresentationStyle = UIModalPresentationOverCurrentContext;
//Uncomment this line for transparency but loses orientation
//lvc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:lvc animated:YES completion:nil];
});
Any idea what's wrong and how can I make it work?

Set navigation bar separator color IOS

Hi I am developing IOS application in which I tried to set navigation bar separator color in different ways but it's not working for me. I tried in following ways:
[self.navigationController.navigationBar.layer setBorderWidth:2.0];// Just to make sure its working
[self.navigationController.navigationBar.layer setBorderColor:[[UIColor redColor] CGColor]];
using above I can change border color of full navigation bar but I want to change just separator color only.
I tried another method:
UIView *navBorder = [[UIView alloc] initWithFrame:CGRectMake(0,navBarCont.navigationBar.frame.size.height,navBarCont.navigationBar.frame.size.width, 1)];
[navBorder setBackgroundColor:[UIColor colorWithWhite:255.0f/255.f alpha:0.1f]];
[navBorder setOpaque:YES];
[navBarCont.navigationBar addSubview:navBorder];
This method work as I want but only thing is that when I rotate my device it will not change according to that. That mean if initially my device is in portrait mode it will show seperator in proper width but once I rotate my device to landscape it will not adjust width according to that.
So I tried to implement device orientation change listener also
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(deviceOrientationDidChangeNotification:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
- (void)deviceOrientationDidChangeNotification:(NSNotification*)note
{
[self setNavbar];
}
Above method causes one problem it keeps adding sublayer of separator view. So I have two options now one is put some auto layout constraints on added subview; or second one is every time remove old subview and then add new. But I dont know how to do that. Or is there any easy way to do this? Need some help. Thank you.
This provides a solution for not just any color, but also the height of the seperator:
- (void)viewDidLoad
{
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.shadowImage = [self imageWithColor:[UIColor redColor] size:(CGSizeMake(self.view.frame.size.width, 1.0f))];
self.navigationController.navigationBar.translucent = YES;
}
- (UIImage*) imageWithColor:(UIColor*)color size:(CGSize)size
{
UIGraphicsBeginImageContext(size);
UIBezierPath* rPath = [UIBezierPath bezierPathWithRect:CGRectMake(0., 0., size.width, size.height)];
[color setFill];
[rPath fill];
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}

UITextview text not showing top lines after rotation in iOS7

I have an app that contains a UITextview that displays static text. I used a UITextview to get scrolling for the text, which is much longer than can be displayed in a UILabel. For some reason, the text in a UITextview under iOS 7 does not stay scrolled to the top after a rotation. This works as expected when run under iOS 6.
This can be shown by creating a project with a UITextview that is centered on the storyboard with margins around 50. Then add constraints that pin the UITextview to the edges of the main view. Be sure the text field contains enough text to cause scrolling:
Now run the app and the text will be correctly positioned in the UITextview, with the first line show at the top. After rotation, the text will be shifted down:
After rotating back to portrait, the text is still scrolled down a few lines.
All of this works perfectly if you run it in iOS 6. I have tried have done a lot of research and have tried the following possible solutions in viewWillLayoutSubviews to make the text stay in position:
[textView sizeToFit];
[textView layoutIfNeeded];
[textView setContentOffset:CGPointMake(0.0, 0.0)];
[textView scrollRectToVisible:CGRectMake(0.0, 0.0, 1.0, 1.0) animated:NO];
Nothing seems to work. Does anyone know how to keep the text in position?
Try this:
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[self.textView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
}
I tested this on iOS 7.1.
Call the UITextView's scrollRangeToVisible: message from the delegate view controller's viewDidLayoutSubviews notification method. This will adjust the range after rotation as well as at first impression.
-(void)viewDidLayoutSubviews {
[self scrollToTop];
}
-(void) scrollToTop {
[self.textView setScrollEnabled:NO];
[self.textView scrollRangeToVisible:NSMakeRange(0.0f, 0.0f)];
[self.textView setScrollEnabled:YES];
}
i had the same problem. It looks like using UITextView from the storyboard create lots of small annoying bugs (like this). I managed to solve the problem by creating the UITextView programmatically:
-(void) viewDidLoad{
self.textView=[[UITextView alloc] init];
self.textView.translatesAutoresizingMaskIntoConstraints=NO;
[self.view addSubview:self.textView];
NSDictionary* views = #{#"textView": self.textView};
NSArray* vContrains=[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-50-[textView]-50-|" options:NSLayoutFormatAlignAllLeft metrics:nil views:views];
NSArray* hContrains=[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-50-[textView]-50-|" options:NSLayoutFormatAlignAllLeft metrics:nil views:views];
[self.view addConstraints:vContrains];
[self.view addConstraints:hContrains];
}
-(void)viewWillLayoutSubviews{
[self.textView layoutIfNeeded];
[self.textView sizeToFit];
}
have tried this on iOS 8.
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
self.textView.contentInset = UIEdgeInsetsMake(0,0,0,0);
}
Similar to some of the above:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
self.textView.scrollRectToVisible(CGRect(x:0,y:0,width:1,height:1),animated: false)
self.textView.layoutIfNeeded()
self.textView.sizeToFit()
}

applicationMusicPlayer volume notification

I am using an applicationMusicPlayer and when i try to change the volume appear the visual notification, as shown in the picture.
Here the code I am using:
[MPMusicPlayerController applicationMusicPlayer] setVolume:newVolune];
Anyone knows how to hide this notification?
I don't know where the docs says so, but if you add a MPVolumeView view to your app the system volume overlay goes away. Even if it is not visible:
- (void) viewDidLoad
{
[super viewDidLoad];
MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame: CGRectZero];
[self.view addSubview: volumeView];
[volumeView release];
...
}
You can use the hardware volume buttons, the setVolume method or directly interact with the control (if visible) that the overlay doesn't show up.
For iOS6 I had to set an image with alpha 0 and non-zero size to the MPVolumeView's image fields in order to get the default volume change notification to disappear.
// hide the hardware volume slider
UIImage *thumb = [[UIImage alloc] initWithCIImage:[UIImage imageNamed:#"volumeHider"].CIImage scale:0.0 orientation:UIImageOrientationUp];
MPVolumeView *hwVolume = [[MPVolumeView alloc] initWithFrame:self.frame];
[hwVolume setUserInteractionEnabled:NO];
hwVolume.showsRouteButton = NO;
[hwVolume setVolumeThumbImage:thumb forState:UIControlStateNormal];
[hwVolume setMinimumVolumeSliderImage:thumb forState:UIControlStateNormal];
[hwVolume setMaximumVolumeSliderImage:thumb forState:UIControlStateNormal];
[self addSubview:hwVolume];
This made the MPVolumeView be "visible" on the screen, but invisible to the user.
I encountered the same issue recently. Instead of adding the MPVolumeView to current view controller's view, I add it to the application's window once at the start of the app:
CGRect rect = CGRectMake(-500, -500, 0, 0);
MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:rect];
[self.window addSubview:volumeView];
This works in both iOS 7 and 8.
Swift 3
You can hide the System MPVolumeView using
override func viewDidLoad() {
super.viewDidLoad()
let volumeView = MPVolumeView(frame: CGRect.zero)
self.view.addSubview(volumeView)
}
I had success with this in iOS 6. Although it wouldn't perform well. It caused quite a bit of lag when sliding the thumbImage. I did have to take out the last 2 lines of code in order for this to work.
[volumeView release];
...
For me, on iOS 7, none of above solutions worked. Here is how I did it:
_volume = [[MPVolumeView alloc] initWithFrame: CGRectMake(-100,-100,16,16)];
_volume.showsRouteButton = NO;
_volume.userInteractionEnabled = NO;
[self.view addSubview:_volume];
[_volume release];
That is, simply set MPVolumeView's frame to an off-screen location such as (-100,-100).

iPad: UIModalPresentationFormSheet fails on landscape mode

We've the next problem in our iPad version.
I've a NavigationController inside a UITabBar. I want to show a Form with a look&feel similar than the e-Mail form.
I use the same code to show a model centered:
// View to be displayed in the modal
AdhocViewController *controller = [[AdhocViewController alloc] initWithNibName:#"AdhocViewController" bundle:[NSBundle mainBundle]];
controller.caller = self;
// The form will need a navigation bar to cancel or save the form
UINavigationController *modalViewNavController = [[UINavigationController alloc]
initWithRootViewController:controller];
// Configurate the modal presentation and transition
modalViewNavController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
modalViewNavController.modalPresentationStyle = UIModalPresentationFormSheet;
// Show the new view
[self presentModalViewController:modalViewNavController animated:YES];
This code works perfectly on portrait mode, but on landscape the view appears partially out of the screen ... and I didn't found yet the way to solve it.
I test some of the solutions I found here ...
And try to add the next lines after preset the model view to resize it, but doesn't work it out
controller.view.superview.frame = CGRectMake(0, 0, 600, 700);
controller.view.superview.center = self.view.center;
Any suggestion?
Thanks,
Ivan
References in StackOverflow:
iPad modalPresentationStyle UIModalPresentationFormSheet orientation problem
UIModalPresentationFullScreen not working in iPad landscape mode?
UIModalPresentationFormSheet on iPad in landscape mode
How to resize a UIModalPresentationFormSheet?
With iOS7 the trick is to set the modalTransitionStyle to UIModalTransitionCrossDissolve.
UIViewController *viewController = [[UIViewController alloc] init];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
navigationController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:navigationController animated:YES completion:nil];
navigationController.view.superview.frame = CGRectMake(0, 0, 800, 544);
navigationController.view.superview.center = self.view.center;
https://coderwall.com/p/vebqaq
Finally the code was the next:
// Remove the modalTransitionStyle to enable the default behaviour and change to PageSheet
modalViewNavController.modalPresentationStyle = UIModalPresentationPageSheet;
// Present the modal view and adapt the center depending of the orientation
[self presentModalViewController:modalViewNavController animated:YES];
UIDeviceOrientation _orientation = [controller interfaceOrientation];
if (UIDeviceOrientationIsPortrait(_orientation)){
modalViewNavController.view.superview.center = CGPointMake(768/2, 1024/2 + 10);
} else {
modalViewNavController.view.superview.center = CGPointMake(768/2 - 10, 1024/2);
}
The +10 and -10 is because by deafult the NavigationController of the modal was out of the screen on top.
It is ... a crappy solution :SS but works ... Although if anybody have suggestions would be nice to know.
Seams that if I need to include the same center for both orientation, maybe the orientation of the superview is not the expected one.
In this solution, when I dissmiss the modal view on Portrait orientation, at least on the iPad simulator, it rotate to portrait mode automatically ...
The final solution was to execute the presentModalViewController over the main controller, the UITabBar, and update the dismiss method to be executed also over it.
[tabbar presentModalViewController:modalViewNavController animated:YES];
UIDeviceOrientation _orientation = [controller interfaceOrientation];
if (UIDeviceOrientationIsPortrait(_orientation)){
modalViewNavController.view.superview.center = CGPointMake(768/2, 1024/2 + 10);
} else {
modalViewNavController.view.superview.center = CGPointMake(1024/2, 768/2 + 10);
}
Finally!!!!
Thank you,
Iván
In iOS 7, to solve the problem of the modal view controller to appear to the left after apparition of the keyboard (problem that I have when I present an EKEventEditViewController in UIModalPresentationFormSheet, I do :
[self presentViewController:modalViewController animated:YES completion:^{
modalViewController.view.superview.center = self.view.center;
}];