UIWebView on top of UITableView - how to switch between them? - iphone

OK, I have a situation, where a user looks up a word in my app. Static information about the word is displayed in the top 1/3 of the screen. The user can see more information about this word in the bottom 2/3 of the screen. This information is displayed via two different views...
The first view is a UITableView showing the users' activities, and the other is A UIWebView which looks the word up on the internet. I have simply put the UIWebView on top of the UITable view, and when the user presses a button, I simply hide/unhide the UIWebView.
All well and good, except that any user interaction is always with the UIWebView, even when it is hidden, so the user cannot scroll in the now visible UITableView.
Is there a simple way to 'deactivate' the UIWebView, thus allowing the user to scroll in the UITableView hidden below?
Relevant code right now is:
- (IBAction)pressDictionaryTab:(id)sender {
webView.hidden = NO;
}
- (IBAction)pressHistoryTab:(id)sender {
webView.hidden = YES;
}
Cheers :-)

In addition to hiding it, can you try sendSubviewToBack, like this:
- (IBAction)pressDictionaryTab:(id)sender {
webView.hidden = NO;
tableView.hidden = YES;
[self.view sendSubviewToBack:tableView];
}
- (IBAction)pressHistoryTab:(id)sender {
webView.hidden = YES;
tableView.hidden = NO;
[self.view sendSubviewToBack:webView];
}

From the UIWebView documentation:
Important You should not embed UIWebView or UITableView objects in UIScrollView objects. If you do so, unexpected behavior can result because touch events for the two objects can be mixed up and wrongly handled.
If you are under iPhone, push a new view controller with the web view. Under iPad, present a small view controller inside an UIPopoverController.

Related

UIBarButton item two methods / IBAction

I have a bottom toolbar button that contains a button which opens a UIWebView *webView
- (IBAction)rebateWebView:(id)sender {
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.google.com"]]];
}
Now, after the webView loads I want to change the title of the button and when the button is tapped again I want the webView to disappear or, in essence, reload the firstviewcontroller.
I know how to change the title and have that working. My biggest problem is dropping the webView. I just can't wrap my head around it.
[self.webView removeFromSuperView]; will remove your webView from the super view, which is almost certainly your view controller's self.view.
Then depending on whether you still need it or not you may want to nil it out and/or release it if you are not using ARC.
If you are trying to "reload" the view controller instead (which is completely different from dropping self.webView, you can call [self viewWillDisappear:NO]; [self viewWillAppear:NO]; if what you need is in those methods.
Edit
Jim's suggestion is also valid if you may want to re-show that self.webView in the future:
self.webView.hidden = YES to hide
self.webView.hidden = NO to show

iPhone: How to show UIWebview on top of UITableView?

In my Universal app which supports IOS4 and later, I have a UINavigationController and pushing UITableViews using UITableViewController.
Some pages may need to show some messages in HTML so I wanna use WebView. So I imagined like this;
When a new tableview is pushed I will check if it needs to show any messages if yes the new window will open up with a webview on top of the tableview covering maybe %80 of the screen and the tableview is disabled at that moment, when user is done reading the webview they will close it and tableview will be get activated again. Also there will be a message icon on the navigation bar to re-open and re-read the messages again.
How can I do this any ideas?
present the webview modally when the tableview appears:
create your viewcontroller (that has a webview):
UIViewController *webUIViewController = [[UIViewController alloc] init];
locate the navigation controller:
UINavigationController *myNavController = [self navigationController];
present your webview modally:
[myNavController presentModalViewController:webUIViewController animated:YES];
I'd probably only do this for web documents stored locally in the apps bundle though - as you want the user to get feedback of any network loading and what if they have no internet access?
you can use [[cell contantView] addSubview:aWebView].
For instance, you have a boolean : iMustShowAWebView
in cellforrowatindexpath
if (iMustShowAWebView) {
[[cell contantView] addSubview:aWebView]
}
in heighForRowAtIndexPath
if (iMustShowAWebView)
return 44;
else
return 0;

Landscape/Portrait conflict - iOS

Just when i thought I had everything figured out .. i got this problem.
the scenario.
I got a simple tableView. and with a search bar in navigation item's titleView. The SearchBar is added to navItems titleView via a uibarbuttonitem in view controllers toolbar.
NOW, normally
After initiating the searchbar with [beginResponder] the keyboard shows up. And It sends out a notification "KeyboardDidShow" which is where i calculate the UIKeyboard's height and set the tableView's height accordingly (Shorten it).
ON Rotation - to and fro landscape/portrait, everything works fine.
-(void)didRotateInferfaceOrientation is called and everythings kool.
Heres the problem.
When the keyboard is active, it has a Google "search" button, this pushes to a new view - webviewcontroller.
the problem is, this
When, [PORTRAIT]ViewController [SearchBar with keyboard active] --> taps Search --> [Portrait]WebViewController --> Change Device Orientation to [Landscape] --> [Landscape]WebViewController changes to landscape ---> HERES THE PROBLEM, user taps back to uiViewController[Landscape]
the method -didRotatefromInterfaceOrientation isnt called. and somehow the tableView height is messed up. Though the view is rotating perfectly.
Is there something im missing here..
would appreciate any help. .thanks
When user taps back, -didRotatefromInterfaceOrientation will not be called. You need to check orientation in viewWillAppear (or call viewDidLoad, prior to returning from tap on back), and then call the proper layout for the chosen orientation.
In all of your (BOOL)shouldRotate... methods, you should be call a separate method to ensure your layout is correct for the device orientation.
I got a similar problem in one of my applications recently, not exactly our problem but don't bother, you should see what I'm heading for: I wanted to simply rotate an viewController displayed using presentModalViewController...Unfortunatly it didn't really worked put, especially on old iPhone with OS prior to iOS 4...So I needed to rotate programatically! Just get your screen size, use CGAffineTransform or something like that and change the sizes and then you should be done...
If your interested I could post a bunch of code, so let me know!
EDIT:
UIScreen *screen = [UIScreen mainScreen];
myController.view.bounds = CGRectMake(0, 0, screen.bounds.size.height, screen.bounds.size.width - 20);
if(currentOrientation == UIDeviceOrientationLandscapeRight){
myController.view.transform = CGAffineTransformConcat(myController.view.transform, CGAffineTransformMakeRotation(degreesToRadian(-90)));
}else{
myController.view.transform = CGAffineTransformConcat(myController.view.transform, CGAffineTransformMakeRotation(degreesToRadian(90)));
}
myController.view.center = window.center;
[[UIApplication sharedApplication] setStatusBarOrientation:currentOrientation];
[self.window addSubview:self.tabBarController.view];
[self.window bringSubviewToFront:self.tabBarController.view];
[self.window addSubview:myController.view];
[self.window bringSubviewToFront:myController.view];
[self.tabBarController.view removeFromSuperview];`
This also includes removing a TabBar when rotating to landscape to get some more space...enjoy :)
You could call didRotateFromInterfaceOrientation manually on viewWillAppear and just pass an orientation yourself (i.e. [UIApplication sharedApplication].statusBarOrientation).

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];

UIWebview swipes to another UIWebiew

Total nooob here. I'm trying to figure out how to implement a
transition from one UIWebview to another with a swipe and still be able to scroll/zoom w/in each webview.
Each webview should respond normally to all touches/gestures unless a swipe is detected and the boundry of the view/content is at the corresponding edge of the screen (like a paging scroll view).
My content is an html string from a data object.
Any tips would be appreciated. Thanks.
Looks like putting a UIWebview in a UIScrollview works fine in iPhone 3.0 - 'Doh!!!
There may be reasons to put a UIWebView in a ScrollView, but supporting BOTH swipe and scrolling in UIWebView is not one of them. The UIWebView handles scrolling around on the page just fine by itself, and the view controller that owns it can support swipe to change to something else like another controller by doing the following:
1) In the viewController which owns the WebView implement the UIGestureRecognizerDelegate method:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gr shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGr
{
return YES;
}
This allows the gesture recognizer you implement in your webViewController to ALSO get gestures from the UIWebView. Else the UIWebView consumes all of them and will not pass them on to you.
2) To make a distinction between a Swipes and scrolling around on a page. On the actual gesture recognizer you are adding to the UIWebView set the number of touches required to be called a "Swipe" to something like 2 or 3. This allows one finger scrolling on a page and will only return a SwipeGesture when 2 or 3 fingers are used. Do it something like this:
UISwipeGestureRecognizer *swipeGR;
swipeGR = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeLeft)] autorelease];
swipeGR.direction = UISwipeGestureRecognizerDirectionLeft;
swipeGR.delegate = self;
swipeGR.numberOfTouchesRequired = 2;
[myWebView addGestureRecognizer:swipeGR];