UIView autoresizingmask not working for me - iphone

I have my app set up so that auto-rotate works. Things like tableviewcontrollers and tabbarcontrollers automatically resize them selves without the need for me to write any code. However I need my webview etc. to resize when the device is turned to landscape. I set:
webView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
but when I rotate the device it does not resize. I am implementing this incorrectly?

I think I finally figured this out. It seems that the root view of a NIB file does not allow you to specify flexible width and flexible height for the autoresizing mask in interface builder (at least not as of 3.2). Take a look. Putting the following code in your viewDidLoad seems to fix the problem:
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
I did it after the super call.

I implement the following in my view controller:
- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
[self.webView setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
}
Seems to work well.

Related

Programmatically zooming into small area of larger picture using UIScrollView

I'm trying to get my code to programmatically zoom into a small area of the larger picture. I'll add the tap code later, but right now I just want to see it work.
The zoomToRect in this code does absolutely nothing and I simply don't understand why. When I build it, the image just sits there at the 0,0 origin.
I've tried using:
setContentOffset and scrollRectToVisible and both these work fine -the image moves to the specified coordinates. But neither of these is what I want, because I need to move and zoom the image, not just move it.
But zoomToRect utterly refuses to do anything. I've read about 50 pages of examples and tutorials on this now and not a damn thing works. I'm tearing my hair out not knowing why. Clearly I'm missing some really fundamental or important point.
UIImage *myFirstImage = [UIImage imageNamed:#"manga_page.jpg"];
UIImageView *myFirstImageView = [[UIImageView alloc] initWithImage:myFirstImage];
[myFirstImageView setFrame:CGRectMake(0, 0, myFirstImage.size.width, myFirstImage.size.height)];
UIScrollView *myFirstScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[myFirstScrollView setContentSize:CGSizeMake(myFirstImage.size.width, myFirstImage.size.height)];
[myFirstScrollView addSubview:myFirstImageView];
[self.view addSubview:myFirstScrollView];
[myFirstScrollView zoomToRect:CGRectMake(300, 300, 300, 300) animated:YES];
The problem was that I hadn't defined the delegate for zooming - see viewForZoomingInScrollView (bottom of page) here:
https://developer.apple.com/library/ios/documentation/uikit/reference/uiscrollviewdelegate_protocol/Reference/UIScrollViewDelegate.html#//apple_ref/occ/intfm/UIScrollViewDelegate/viewForZoomingInScrollView
I don't have a code fragment in Objective C as I switched to the Xamarin framework. However the C# solution is as follows:
scrollView.ViewForZoomingInScrollView = delegate (UIScrollView sv) { return imageView; };
Where imageView is the UIImageView containing the image to be scrolled around.
Set the maximumZoomScale and minimumZoomScale properties for the UIScrollView.

iOS unable to autoresize subviews when device rotation

I tried several solutions found on other posts but still having problems to autoresize subviews when device rotation. My layout (IB) has three views and only apply resize to current view. If then, after rotating device, view is shown, was not resized and remains at previous dimensions. I set autoresize subviews and its mask... What am I doing wrong or missing? any help would be appreciated, thank you!
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view setAutoresizesSubviews:YES];
[self.view setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[vistaSocial setAutoresizesSubviews:YES];
[vistaSocial setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[vistaB setAutoresizesSubviews:YES];
[vistaB setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
I think you are not using a proper resizing properties on xib file. As per my understanding, you must have added 2-3 views on current controller; but auto-resizing is getting wrong somewhere. Try one by one and with a correct set.
You can share any screen shot for better understanding, if i am predicting it wrong.
You can set Autoresize property with the help of Nib file. Can you please check once you set it properly from NIB file?
For a given view to adjust its size upon device rotation, it is its superview that needs to have its autoresizesSubviews property set to YES. (It is not clear from your code fragment what your view hierarchy is.) Try changing
[vistaB setAutoresizesSubviews:YES];
to
[vistaB.superview setAutoresizesSubviews:YES];

UIView addsubview after orientation change: Tell view to resize

I have a UIView as a XIB in Portrait mode.
This view is added programmatically to the viewcontroller like this:
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"InputView" owner:self options:nil];
InputView *inputView = (InputView*)[nibObjects objectAtIndex:0];
[self.view addSubview:inputView];
This view has autoresizing masks set up properly and rotates fine when the orientation changes from Portrait to landscape.
However, if the orientation is already landscape and I create the view after the orientation change, it has its initial portrait orientation.
Is there a way to tell the view to initialize or resize itself to portrait by using its masks?
Thanks in advance for any reply!
EDIT:
Using the suggestions of occulus and Inder Kumar Rathore (thanks guys!), I altered the code to this:
InputView *inputView = (InputView*)[nibObjects objectAtIndex:0];
[self.view addSubview:inputView];
[self.view setNeedsLayout];
[self.view layoutSubviews];
[self.view layoutIfNeeded];
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
[self shouldAutorotateToInterfaceOrientation:orientation];
Unfortunately, there is no change at all.
I think I found someone asking the same question:
When adding a sub view the view does not resize if the app is in landscape mode
The answer identifies the problem correctly, but is not very encouraging...
Sure, I could create two nibs or resize the frame, but this seems so contrary to the idea of auto-resizing.
I find it hard to believe that there is no way to tell a nib after awakening and adding it to a view to use its autoresize features...something that works flawless when the device rotates.
EDIT 2:
The solution of idz works:
InputView *inputView = (InputView*)[nibObjects objectAtIndex:0];
[self.view addSubview:inputView];
inputView.frame = self.view.bounds;
[inputView show];
Thanks!
Often a NIB/XIB file contains a UIViewController that takes care of all of this. In this case, since their is no view controller (in the NIB/XIB) you need to take over its post-load duties.
Calling layoutSubviews directly, or indirectly via setNeedsLayout or layoutIfNeeded won't do you much good because the default implementation does nothing.
Assuming you want input view to fill the bounds of self.view you do the following:
InputView *inputView = (InputView*)[nibObjects objectAtIndex:0];
[self.view addSubview:inputView];
inputView.frame = self.view.bounds;
[inputView show];
All the resize masks of the sub-views must be correctly set for this to work and, obviously, if you don't want to fill the full bounds you may want to adjust the frame.
[self.view addSubview:viewSpinner];
viewSpinner.frame = self.view.frame;
[viewSpinner setNeedsLayout];
This works for me (Y)
I don't know if you still have this issue.
Let's say you have the following architecture:
window
subviewcontroller
(you implemented shouldautorotate correct to answering the wanted orientations)
Into this subviewcontroller you want to add the views of new UIViewControllers by just calling the addSubview function.
Instead of implementing the bounds manipulation in shouldautorotate, you should implement it in
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
self.newUIViewController.view.frame = self.view.bounds;
}
didRotateFromInterface... is called after shouldRotate. In this function the bounds are already setup correctly.
This way you don't need so much manipulation by code.
See this related question:
When do autoresizing masks take effect in iOS?
So after loading your new view from the nib, and adding as a subview to self.view, try calling setNeedsLayout.

EGOTableViewPullRefresh and landscape orientation

I am using Cocoanetic's implementation of EGOTableViewPullRefresh.
It's a cinch to implement. Love it:
http://www.cocoanetics.com/2009/12/how-to-make-a-pull-to-reload-tableview-just-like-tweetie-2/
The only problem I'm having is with rotation. When the view rotates, the refresh header doesn't adjust for landscape mode. It sits left aligned, 320.0f units wide.
I have tried everything I can think of to adjust this properly. I set it as a property in PullToRefreshTableViewController and tried to set the frame the same way it is done in init. This failed. I tried to do it in this same controller in viewWillAppear. Failed.
Beyond this, I tried about 6 other methods not worth detailing. The problem seems to be that I'm using the wrong bounds, even though I'm making them relative to the view.
Nothing I do replicates what is seemingly easy in viewDidLoad:
refreshHeaderView = [[EGORefreshTableHeaderView alloc] initWithFrame:
CGRectMake(0.0f, 0.0f - self.view.bounds.size.height,
320.0f, self.view.bounds.size.height)];
It seems all I really need to do is increase the width. I tried something along the lines of this:
refreshHeaderView.frame = CGRectMake(refreshHeaderView.frame.origin.x, refreshHeaderView.frame.origin.y, 480.0f, refreshHeaderView.frame.size.height);
No luck.
The link at the top has the full, unmodified source code for what I'm using.
What about just setting the UIView.autoresizingMask to UIViewAutoresizingFlexibleWidth?

iPhone OS: Tap status bar to scroll to top doesn't work after remove/add back

Using this method to hide the status bar:
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];
When setting "hidden" back to NO, the tap-to-scroll-to-top (in UIWebView, UITableView, whatever) doesn't work any more, and requires a restart of the app to get the functionality back.
Is this a bug (I filed a rdar anyhow) or have I missed a step? Should I perhaps expect this behavior since the statusBar "loses touch" somehow with the respective view?
You could try setting the ScrollsToTop property to true again after re-showing it:
[currentView setScrollsToTop:YES];
If that's not working, are you definitely only showing one view? If there is more than one scrolling view a scrollViewDidScrollToTop message is ignored...
In iOS 5.0 you can access the scrollview property of the UIWebView
webView.scrollView.scrollsToTop = YES;
The following fix by Alex worked for me. Thanks!
((UIScrollView *)[[webView subviews] objectAtIndex:0]).scrollsToTop = NO;
Being in a hurry this fix worked great, however given more time I might've subclassed the UIWebView and accessed the protected UIScrollView member directly.
The worry I have with Alex' method is that it assumes that UIScrollView is at index zero of the subviews (encapsulation allows private members to change). Which suggests another solution still:
for (UIView* v in [webView subviews])
{
if ([v isKindOfClass:[UIScrollView class]])
{
(UIScrollView *)v.scrollsToTop = NO;
}
}
I was having a similar problem where the scroll-to-top functionality was lost. Turns out this will only work when you have only one active view at a time (within the same scroll view). In my case I had a table view and another view which would fade in/out. Adding a removeFromSuperview at the end of the animation did the trick.
The answer was in the UIScrollView.h file comments:
/*
this is for the scroll to top gesture. by default, a single scroll visible scroll view with this flag set will get the call. if there is more than one visible with this
flag set or the delegeat method returns NO, the view isn't scrolled
*/
#property(nonatomic) BOOL scrollsToTop; // default is YES. if set, special gesture will scroll to top of view after consulting delegate
You can use the following code to have the UIWebView ignore scrollToTop without the extra UIScrollView:
((UIScrollView *)[[webView valueForKey:#"_internal"] valueForKey:#"scroller"]).scrollsToTop = NO;
I had a similar problem after playing a Youtube video within my app. scrollsToTop was still set to YES but tapping the status bar had no effect.
I finally realised that my app window was no longer the key window. After adding the following line to a UIWindow subclass (which I already had for other reasons) everything worked as it should again:
if (![self isKeyWindow]) [self makeKeyWindow];
I just ran across a similar behavior in the app I'm currently working on. In its case, if you load a YouTube video from within a UIWebView, scroll to top stops working for the rest of the application's life cycle. I kind of assume this might happen after loading the movie player as well, but haven't confirmed. That functionality has been around a lot longer and probably has fewer bugs.
When there are multiple scrollview, you can also set scrollUpToTop to NO for the others scrollview. cf:
setScrollsToTop with multiple UIScrollView classes and/or subclasses(UITableView)
I want to add my case, I add an UIWebView on an UIScrollView, as h4xxr had answered on the top:
If there is more than one scrolling view a scrollViewDidScrollToTop message is ignored
So, I get a simply way to make it work on webView: just set the scrollView·s scrollsToTop property false.
And when tap the status bar, it won`t got intercepted by the scrollView, and the webView scrolls to the top!
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.frame = self.view.bounds;
scrollView.scrollsToTop = false; //igore scrollView`s scrollsToTop
[self.view addSubview:scrollView];
UIWebView *webView = [[UIWebView alloc] init];
webView.frame = scrollView.bounds;
[scrollView addSubview:webView];