I've noticed weird behaviour in my UIWebView using iOS 7.0 SDK. This behaviour wasn't there in iOS 6, and my code regarding this webview hasn't changed.
I have a storyboard, not using autolayout, autoresize mask for the webview is everything selected.
I have scale pages to fit set to YES.
When I load a local html file, it displays fine and upon scrolling, the webview will show the scroll indicator.
When I rotate the device, the webview resizes fine, it's rect is correct size, the page displays as expected, however the scroll indicator is not visible
Here's the kicker. If I don't scroll before I rotate, the scroll indicator is visible when I start scrolling AFTER the rotate.
If I DO scroll before the rotate, the scroll indicator is not visible after the rotate.
I checked the html, there is no jquery or js that will change the overflow in regards to orientation.
OK I found the solution, I was using a subclassed UIWebView and overriding the layoutSubviews to not draw the gradient shadows above and below the scrollview (as it has by default).
- (void)layoutSubviews
{
[super layoutSubviews];
// hide the shadows at the top and bottom of the webview's frame
for (UIView* shadowView in [self.scrollView subviews])
{
if ([shadowView isKindOfClass:[UIImageView class]]) {
[shadowView setHidden:YES];
}
}
}
Well guess what was a UIImageView? The Scroll Indicator! I removed this code and the problem went away
Related
UPDATED -- I have an iPad app that was originally designed and written for portrait mode only; I now want to add a UIScrollView so it will scroll in landscape mode. Auto Layout is checked and the different scenes are built using Storyboard. (I am following this tutorial). The major problem is when switching from portrait to landscape, the bounds of the frame change drastically, thereby causing problems with the logic of the scroll.
This is the image of the first scene (UIView) I am trying to add a UIScrollView to:
This is what it looks like in landscape mode (w/o scrolling):
This is my code in the -viewDidLoad method for that scene:
// create UIScrollView
UIScrollView *scroll = [[UIScrollView alloc]initWithFrame:CGRectMake(0,0,self.bookDetailView.frame.size.width, self.bookDetailView.frame.size.height)];
scroll.delegate = self;
scroll.pagingEnabled = YES;
scroll.scrollEnabled = YES;
scroll.showsVerticalScrollIndicator = YES;
CGSize scrollableSize = CGSizeMake(768, 1024); // size of portrait mode
scroll.contentSize = scrollableSize;
[self.view addSubview: scroll];
The scroll bar (as thin as it is) now shows, BUT although it moves like it should, the UIView doesn't move. Portrait mode works fine (no scrolling needed) but landscape mode doesn't scroll at all (even tho' the vertical scroll bar does move). I'm wondrering if I should abandon the idea of using scrolling for landscape mode and create separate scenes for landscape mode instead.
Is there any reason why you need a separate UIScrollView ? UITableView is already a scroll view. My guess is that the touch events from the UIScrollView you created are interfering with those of the UITableView.
I have a Mac OS X (10.9) application with a custom NSView for my main NSWindow's contentView property. The only thing the custom view does is override drawRect: so that it's transparent. Transparency is required so that my NSOpenGLView is visible (see below):
/* Transparent NSView Subclass */
- (void)drawRect:(NSRect)dirtyRect
{
NSLog(#"Drawing Rect");
[[NSColor clearColor] set];
NSRectFillUsingOperation(dirtyRect, NSCompositeClear);
}
The contentView has an NSOpenGLView as a subview, with its surface order set to -1 (it's 'below' the main NSWindow, which is also transparent):
/* NSOpenGLView subclass: */
GLint order = -1;
[self.openGLContext setValues:&order forParameter:NSOpenGLCPSurfaceOrder];
I then instantiate a WebView and place it as a subview of this custom view:
_webview = [[WebView alloc] initWithFrame:frame];
[_webview setMaintainsBackForwardList:NO];
[_webview setTranslatesAutoresizingMaskIntoConstraints:NO];
[_webview setDrawsBackground:NO];
[_window.contentView addSubview:_webview];
The WebView is a small box in the window (on top of the NSOpenGLView) which is used to login to a service. Once login happens it should disappear, showing only the NSOpenGLView.
Here's the problem: when I call [_webview removeFromSuperview]; the contentView does not redraw; therefore, the WebView is still drawn on the screen (although not responsive to mouse or keyboard). If I use my mouse to resize the window that everything is in, the contentView redraws (I see the message in the logs) and the WebView's content disappears.
Also, if I don't add the NSOpenGLView as a subview, the WebView goes away as it should.
Shouldn't the contentView fire a drawRect after a subview is removed? Even when I used setNeedsDisplay: or setNeedsLayout: after removing the WebView the contentView still didn't redraw.
Apple's advice these days is to use Core Animation layers to put normal views on top of OpenGL views.
I suspect that the content view has redrawn itself. It draws clear. What you're seeing is the OpenGL surface behind it. The nearly-raw-VRAM nature of OpenGL surfaces may mean that the web view that was drawn on top of it actually modified the contents of the surface. So, I recommend that you force the OpenGL view to redraw itself. If it draws in its -drawRect:, then it should be enough to send it -setNeedsDisplay:. If you do rendering outside of -drawRect: by manually making the context current, issuing rendering commands, and then calling -flushBuffer, then you'll need to do that.
I'm trying to scroll an NSScrollView to the bottom of the view using this code:
NSPoint newScrollOrigin;
if ([[self.chatScreen documentView] isFlipped]) {
newScrollOrigin=NSMakePoint(0.0,NSMaxY([[self.chatScreen documentView] frame])-NSHeight([[self.chatScreen contentView] bounds]));
} else {
newScrollOrigin=NSMakePoint(0.0,0.0);
}
self.chatScreen.backgroundColor=[NSColor redColor];
[[self.chatScreen documentView] scrollPoint:newScrollOrigin];
which came from here: Apple doucmentation on scrolling
When I run my program, it partially scrolls to the bottom of the view, where the screen shows the top of the view (default starting position) but when I attempt to scroll, it jumps to the bottom of the page, where I can then scroll normally.
If I scroll around to any part of the view, the next time it receives an update (which triggers it to jump back to the bottom) it looks like nothing happened, until you try to scroll, which again causes it to jump back to the bottom of the page.
Thanks in advance.
You need to scroll the clip view and not the document view.
The document view fills out the entire scroll view and the clip view is kind of an overlay which scrolls around deciding which parts are visible.
[[self.chatScreen contentView] scrollToPoint:newScrollOrigin];
Notice the scrollToPoint instead of NSView's layer backed scrollPoint
After you scroll a NSClipView its always good practice to reflectScrolledClipView so that the scrollers update.
- (void)reflectScrolledClipView:(NSClipView *)aClipView;
I can't figure out how to actually use NSScrollview. I dragged the scroll view object onto an NSWindow in the interface builder. I then dragged some NSButtons onto the scroll view. My question is:
How do I actually make it scroll down, for example, 2x the original height?
Of course the user can scroll automatically using their UI. I assume what you want to do is to scroll programmatically.
A bit of background: An NSScrollView has a documentView, which is the underlying view that the scroll view shows a part of, and a clipView, which is the view that is shown on the screen. So the clip view is like a window into the document view. To scroll programmatically you tell the document view to scroll itself in the clip view.
You have two options on how to scroll programmatically:
- (void)scrollPoint:(NSPoint)aPoint –– This scrolls the document so the given point is at the origin of the clip view that encloses it.
- (BOOL)scrollRectToVisible:(NSRect)aRect –– This scrolls the document the minimum distance so the entire rectangle is visible. Note: This may not need to scroll at all in which case it returns NO.
So, for example, here is an example from Apple's Scroll View Programming Guide on how to scroll to the bottom of the document view. Assuming you have an IBOutlet called scrollView connected up to the NSScrollView in your nib file you can do the following:
- (void)scrollToBottom
{
NSPoint newScrollOrigin;
if ([[scrollview documentView] isFlipped]) {
newScrollOrigin = NSMakePoint(0.0,NSMaxY([[scrollview documentView] frame])
-NSHeight([[scrollview contentView] bounds]));
} else {
newScrollOrigin = NSMakePoint(0.0,0.0);
}
[[scrollview documentView] scrollPoint:newScrollOrigin];
}
Not sure why this happens or how to stop it, my UIToolBar on the details viewcontroller is only visible during portrait view. I want it visible at all orientations. How do I do that? Thank you.
I encountered the same problem by just dragging a UIToolBar on to my view and docking it on the top of the window. It showed up in landscape but not portrait. Interface Builder - at least the one embedded in Xcode 4 - doesn't seem to do the right thing with the resize masks.
While Kshitiz's answer above will work, it has a couple of flaws. As coded, it does not support all four orientations. More importantly, it's not resolution independent.
A better solution is briefly described in enamrik's comment, so credit should go to him/her. Here are the steps:
Select the tool bar in Interface Builder.
Open the Size inspector.
In the Autosizing box, select the left, right and top "i-beams" on the exterior of the square. This keeps the position of the toolbar fixed relative to the sides of the view when the view is resized.
Inside the Autosizing square, select the horizontal line with arrows on both ends. This causes the size of the toolbar to change in sync with the parent view.
in your this function of view controller reset view frame bro
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Override to allow orientations other than the default portrait orientation.
if (interfaceOrientation==UIInterfaceOrientationLandscapeLeft || interfaceOrientation==UIInterfaceOrientationLandscapeRight) {
self.view.frame = CGRectMake(0, 0, 703,768);
} else {
self.view.frame = CGRectMake(0, 0, 768, 1024);
}
return YES;
}
and your tool bar frame too
good luck
Faced the same problem when I add UIPickerView programmatically and add UIToolBar for the PickerView. Just need to add [.flexibleWidth,.flexibleHeight] for the UIPickerView. eg:-
let statTypePicker = UIPickerView()
And then add
self.statTypePicker.autoresizingMask = [.flexibleWidth,.flexibleHeight]