UIVisualEffectView built in storyboard is opaque - ios

I've built an UIView in storyboard that is composed like this:
UIView (called _view)
UIVisualEffetView (dark)
UIVIew
Button
I've done like this for the ability to reuse it between several Navigation Controller. So for this I've set everything and I can show my view in my main controller called "ViewController" that is embedded in a navigation controller. But the issue is that the blur is opaque, for example the blue navigation bar of my view controller is not visible under the UIVIsualAffectView !
Here is the code I use for setting up the custom view :
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (void)setup {
_view.backgroundColor = [UIColor clearColor];
UIView *rootView = [[[NSBundle mainBundle] loadNibNamed:#"SideMenuView" owner:self options:nil] objectAtIndex:0];
CGRect newFrame = rootView.frame;
newFrame.size.width = [[UIScreen mainScreen] bounds].size.width / 2;
newFrame.size.height = [[UIScreen mainScreen] bounds].size.height;
[rootView setFrame:newFrame];
UIWindow* currentWindow = [UIApplication sharedApplication].keyWindow;
currentWindow.backgroundColor = [UIColor clearColor];
currentWindow.windowLevel = UIWindowLevelNormal;
[currentWindow addSubview:rootView];
}
And here is the code I use to call the view from my main controller:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.leftBarButton setTarget:self];
[self.leftBarButton setAction: #selector(test)];
}
- (void)test {
SideMenuView *test = [[SideMenuView alloc] init];
[self.view addSubview:test];
test.translatesAutoresizingMaskIntoConstraints = NO;
}
I've also tried to force the property "setOpaque" to No in my SideMenuView.m but without effect
Here is a screenshot of what it do:
Do you know guys what is wrong with my code ?
I've also added a button in the middle of the screen with a blue background but it's not visible under the blur so the issue is not navigation bar specific
Thanks in advance for your help !

I've resolved my issue by simply creating an UIView with clear background.
What I do for adding the blur effect is to create the UIVisualEffectView programmatically (doing this way it work perfectly !).
After that I'm adding my UIView as a subview of my UIVisualEffectView and voila :)

Related

Navigation controller with 2 navigation bars - how to adjust frame of pushed view controllers?

I have a UINavigationController to which I need to add a second UINavigationBar. Neither of those bars is translucent. Problem is, view controllers that I put inside this navigation controller are partially covered by my second navigation bar. Where do I adjust the frames of those view controllers' views so that I don't get a "blinking" effect of them changing frames while being visible?
EDIT:
This is in viewDidLoad:
UINavigationBar *secondaryNavBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.width, 50)];
secondaryNavBar.translucent = NO;
if ([secondaryNavBar respondsToSelector:#selector(setBarTintColor:)]) { //it has to work on iOS 6 as well
secondaryNavBar.barTintColor = [UIColor darkGrayColor];
secondaryNavBar.tintColor = [UIColor whiteColor];
}
else {
secondaryNavBar.tintColor = [UIColor darkGrayColor];
}
[self.view addSubview:secondaryNavBar];
self.secondaryNavBar = secondaryNavBar;
Here's a working solution. Certainly not the best, and I did not make it to support iOS 6, you'll have to work on it and test it.
CustomNavigationController.m :
#implementation CustomNavigationController {
UINavigationBar *bottomNavBar;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self showNavBar];
}
- (void)showNavBar {
UINavigationBar *secondaryNavBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.width, 50)];
secondaryNavBar.translucent = NO;
if ([secondaryNavBar respondsToSelector:#selector(setBarTintColor:)]) { //it has to work on iOS 6 as well
secondaryNavBar.barTintColor = [UIColor darkGrayColor];
secondaryNavBar.tintColor = [UIColor whiteColor];
}
else {
secondaryNavBar.tintColor = [UIColor darkGrayColor];
}
[self.view addSubview:secondaryNavBar];
bottomNavBar = secondaryNavBar;
[self layoutNavBar];
}
- (void)layoutNavBar {
// Get the currently displayed view
UIView *contentView = self.topViewController.view;
// Get its frame and height
CGRect contentFrame = contentView.frame;
float height = contentFrame.size.height;
// Adapt height and y origin with the new nav bar
contentFrame.size.height = height - bottomNavBar.frame.size.height;
contentFrame.origin.y = bottomNavBar.frame.origin.y + bottomNavBar.frame.size.height;
// Set the view's frame
contentView.frame = contentFrame;
}
#end
ViewController.m :
#implementation ViewController
-(void)viewDidAppear:(BOOL)animated {
CustomNavigationController *navigation = (CustomNavigationController*)self.navigationController;
[navigation layoutNavBar];
}
#end
Note that you have to call layoutNavBar on viewDidAppear, or the view's frame will be reset by your app. This is not a perfectly clean solution, but a pretty good fix.

How to have images that pinch-zoom in a paginating scroll view in iOS?

I'm trying to use a scroll view to have pagination with pages of subviews that are images that can be pinched zoomed on iOS. The pagination works, but as soon as an image is pinch-zoomed, the app crashes with EXEC_BAD_ACCESS(code=1,address=...)
I'm aware that it's a bit odd to swipe a zoomed image to pan the image and also swipe to paginate, but in the real app, the pagination will be done with a page control. Also I think it could work like the preview app. If an image is zoomed, panning will go down to the bottom of the image and then after that is reached, it goes to the next image.
Is this possible?
Here's an example:
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
ScrollerViewController *viewController = [[ScrollerViewController alloc] init];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
return YES;
}
ScrollerViewController.m - the outer pagination view controller
- (void)viewDidLoad {
[super viewDidLoad];
// outer scroll view for paging with two pages
CGRect frame = CGRectMake(0,0,self.view.bounds.size.width,self.view.bounds.size.height);
UIScrollView *pagingScroller = [[UIScrollView alloc] initWithFrame:frame];
pagingScroller.pagingEnabled = YES;
pagingScroller.scrollsToTop = NO;
pagingScroller.userInteractionEnabled = YES;
pagingScroller.contentSize = CGSizeMake(self.view.bounds.size.width*2,self.view.bounds.size.height);
// first page
ImageViewController *page1 = [[ImageViewController alloc] init];
page1.filename = #"cat.jpg";
page1.view.frame = CGRectMake(0,0,self.view.bounds.size.width,self.view.bounds.size.height);
[pagingScroller addSubview:page1.view];
// second page
ImageViewController *page2 = [[ImageViewController alloc] init];
page2.filename = #"dog.jpg";
page2.view.frame = CGRectMake(self.view.bounds.size.width,0,self.view.bounds.size.width,self.view.bounds.size.height);
[pagingScroller addSubview:page2.view];
self.view = pagingScroller;
}
ImageViewController.m - the pinch-zoom image
- (void)viewDidLoad {
[super viewDidLoad];
// scroll view for pinch zooming
CGRect frame = CGRectMake(0,0,self.view.bounds.size.width,self.view.bounds.size.height);
UIScrollView *zoomScroller = [[UIScrollView alloc] initWithFrame:frame];
zoomScroller.minimumZoomScale = 1.0;
zoomScroller.maximumZoomScale = 5.0;
zoomScroller.userInteractionEnabled = YES;
zoomScroller.delegate = self;
imageView = [[UIImageView alloc] initWithFrame:frame];
imageView.userInteractionEnabled = YES;
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.image = [UIImage imageNamed:filename];
[zoomScroller addSubview:imageView];
self.view = zoomScroller;
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return imageView;
}
The full project is at https://github.com/tomkincaid/ZoomScrollTest
I can test that the pinch zoom works by changing
ScrollerViewController *viewController = [[ScrollerViewController alloc] init];
to
ImageViewController *viewController = [[ImageViewController alloc] init];
viewController.filename = #"cat.jpg";
Its been quite a while that you posted your question. I bet you fixed it already yourself but I want to make sure other people can use your code.
However I downloaded your small GitHub project and found that you get the crash because you don't retain the ImageViewController's page1 and page2 in [ScrollerViewController viewDidLoad]. The views them selfs don't retain their controllers therefor the controllers get released after viewDidLoad in your case. Then when you pinch on the image scroll view it calls for its delegate but it is already deallocated.
To fix this I added two ImageViewController properties to the ScrollerViewController class and stored the controller objects there.
#interface ScrollerViewController ()
#property (strong) ImageViewController *page1;
#property (strong) ImageViewController *page2;
#end
In [ScrollerViewController viewDidLoad] I added at the end:
self.page1 = page1;
self.page2 = page2;
I hope that someone may find this information useful. Maybe you want to update your GitHub project so that it will compile and run.

Best Practices, addChildViewController, addSubview

I am creating an app using iOS 5, and I want to work as follows:
MainViewController w/ NavigationBar, and i set on viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
NavViewController *nav = [[NavViewController alloc] init];
[self addChildViewController:nav];
[self.view addSubview:nav.view];
}
Like a "partial view" with some nav controls (my own/custom toolbar), and at NavViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect viewRect = CGRectMake(0, 0, 320, 200);
self.view.frame = viewRect;
self.view.backgroundColor = [UIColor redColor];
}
At this point I have MainViewController with a navigation subview and still have space (in MainViewController view) that another subview can be added using the actions NavViewController.
Is there a serious flaw in this logic? or I can keep developing ?
Thnks a lot.

Show view from xib in ScrollView

firstly I want to say that I am newbie at iOS development. I have a problem with showing a view from xib file in ScrollView.
This MyView is only green background with one label. Here is a code from its controller:
#implementation MyView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
//init code
}
return self;
}
- (id) initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
[self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
}
return self;
}
#end
And here is a code from main controller where is the ScrollView:
- (void)viewDidLoad
{
[super viewDidLoad];
scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 67, self.view.frame.size.width, self.view.frame.size.height)];
scroll.pagingEnabled = YES;
scroll.frame = CGRectMake(0, 20, 320, 350);
scroll.contentSize = CGSizeMake(320, 350);
scroll.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
scroll.bounces = YES;
scroll.bouncesZoom = YES;
scroll.scrollEnabled = YES;
scroll.minimumZoomScale = 0.5;
scroll.maximumZoomScale = 5.0;
scroll.delegate = self;
scroll.pagingEnabled = YES;
NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:#"MyView" owner:self options:nil];
UIView *myView = [nibContents objectAtIndex:0];
myView.frame = CGRectMake(0,20,300,300);
[scroll addSubview:myView];
}
Only thing I want to do is that I want to see MyView (green background with one label) inside the ScrollView. If I run this app, scrollview is empty, nothing is shown inside.
Probably it is a stupid question but as I said, I am newbie at this. I have a PageControll app from Apple but for me this is quite complicated code in my iOS beginning. Of course I was googling... Please tell me where is a problem. Thank you
Where do you define scroll? Is it a property of your viewcontroller?
I think the problem here is that you don't add scroll view to your viewcontroller's view with
[self.view addSubview:scroll]
Everything seems to right. Just retain the view in your class that you are receiving from the following line and add that as a subview to your scrollview.
self.myView = [nibContents objectAtIndex:0];
Best Regards.

UIViewController subviews exist but I see black screen

I have 2 view controllers, the first is a storyboard (this is root) and the second with is nibless. When I press a button in the root view controller it should call the second controller.
Here the code for my second view controller:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
UILabel *sampleLabel = [[UILabel alloc] initWithFrame: CGRectMake(0,0,100,100)];
UIImageView * basketItem = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"B.jpg"]];
[self.view addSubview:sampleLabel];
[self.view addSubview:basketItem];
NSLog(#"%#",self.view.subviews);
sampleLabel.text = #"Main Menu";
}
return self;
}
self.view.sebviews query shows that 2 objects label and imageView objects exists, but in fact I see black screen only.
Here is transition method
- (void)transitionToViewController:(UIViewController *)aViewController
withOptions:(UIViewAnimationOptions)options
{
aViewController.view.frame = self.containerView.bounds;
[UIView transitionWithView:self.containerView
duration:0.65f
options:options
animations:^{
[self.viewController.view removeFromSuperview];
[self.containerView addSubview:aViewController.view];
}
completion:^(BOOL finished){
self.viewController = aViewController;
}];
}
Move the code in viewDidLoad. Here you are sure the view has been loaded into memory and hence can be further customized.
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel *sampleLabel = [[UILabel alloc] initWithFrame: CGRectMake(0,100,100,100)];
UIImageView * basketItem = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"B.jpg"]];
[self.view addSubview:sampleLabel];
[self.view addSubview:basketItem];
NSLog(#"%#",self.view.subviews);
sampleLabel.text = #"Main Menu";
}
If you are not using ARC, pay attention to memory leaks.
Note
I really suggest to read Apple doc for this. You should understand how things work. Hope that helps.
http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html
Edit
I don't know what the problem could be. To make it work, try to override loadView (in MenuViewController) method like the following:
- (void)loadView
{
CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame];
UIView *contentView = [[UIView alloc] initWithFrame:applicationFrame];
contentView.backgroundColor = [UIColor redColor]; // red color only for debug purposes
self.view = contentView;
}
Leave the viewDidLoad method as I wrote and see what happens.
When you create the view controller use only init method.
MenuViewController *vc = [[MenuViewController alloc] init];
Your UILabel's frame has size.width=0:
CGRectMake(0,100,0,100)
and if B.jpg is not added to the project you UIImageView will also be empty.
Also, if second UIViewController doesn't have a XIB, initialize it using the - (id)init method instead of - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil.

Resources