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];
Related
Hi i am new to iOS programming.
I need to create an photo library like iPhone native photo app. I have found a library MWPhotoBrowser
that provides nearly same UI for photo browsing and its perfect for my requirement. But now i have 2 problems
First is that i need to create a grid layout with thumbnails. Clicking on an thumbnail should display image in full screen with browsing functionality. I tried to dynamically adding UIImageViews in UIScrollView, but UIScrollView is not scrolling and images are going out of screen.
Second is i could not get any tap handler on UIImageView so that i can open an image in full screen.
Looking for some tips here, i am really stuck here.
You can give a shot to this library, it has both features which you are looking for.
https://github.com/gdavis/FGallery-iPhone
Hope it helps :)
For ScrollView scrolling issue you have to increase scrlViewMain.contentSize dynamically. Create a for loop and put bellow code at the end of loop.
scrlViewMain.contentSize = CGSizeMake(0, incermentAsPerYourNeed);
For the tapping issue you have to add TapGesture. Put bellow code when your ImageView creates.
imgView.tag = giveAsPerYourRecordsID;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleImageTap:)];
tap.cancelsTouchesInView = YES;
tap.numberOfTapsRequired = 1;
tap.delegate = self;
[imgView addGestureRecognizer:tap];
[tap release];
And bellow your catch method for tapping.
- (void) handleImageTap:(UIGestureRecognizer *)gestureRecognizer {
UIImageView *tmpImgView = (UIImageView *)gestureRecognizer.view;
}
I have also developed similar functionality a few days ago for my project.
For tap issue you should use UIButton instead of UIImageView, it gives you tap action event. For Scrollview not scrolling, just make sure you update contentSize property of UIScrollView, otherwise it would not scroll according to your subviews.
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.
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
I am trying to get my view controller to detect swipes in the UINavigationBar that is automatically displayed by my app, but it refuses to detect swipes. Is there any way I can do it?
Supposing you want to detect swipes to the left in your navigation bar, you could do something like this when you create the navigation controller:
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(scrollViewSwipedLeft:)];
[swipeLeft setDirection:UISwipeGestureRecognizerDirectionLeft];
[self.navigationController.navigationBar addGestureRecognizer:swipeLeft];
and then create a method like the one below to handle it:
-(void) didSwipedLeft: (UISwipeGestureRecognizer *) gesture {
if (gesture.state != UIGestureRecognizerStateEnded) {
return;
}
//do something
}
OBS: As you navigation controller is a class that will remain alive for several steps of you application life cycle, it is important to pay attention to that and add the gesture recognizer only when you create the navigation controller (which means only add it once) so that you dont keep piling gestures recognizer one over each other, wich will lead not only to a memory leak, but also might make your method didSwipedLeft to be called more than once.
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];