Make it so the user has to scroll in a UIWebView - iphone

I have an application that is running on the iPhone that has a UIWebView on it. I load a webpage into this view and the user can continue to the next page by pressing buttons that I have added to a UIToolBar at the bottom of the page. What I am after is to stop the user from pressing these buttons until they have scrolled half way or all the way down the page. Is this possible?

If it's going to be half way down the page and further then you could probably use the content offset of the scroll view of the webview.
I would create an instance variable in your controller that references the scrollview of the webview. In iOS 5 you can use the webview.scrollView property to access the scrollView but in previous versions you would have to search the subviews of the webView.
if([_webView respondsToSelector:#selector(scrollView)]) {
_webViewScrollView = _webView.scrollView;
}
else {
for (UIView *subview in _webView.subviews) {
if ([subview isKindOfClass: [UIScrollView class]]) {
_webViewScrollView = subview;
break;
}
}
}
Then I would set the scrollviews delegate to be the controller I'm interested in
_webViewScrollView.delegate = self;
and implement the following delegate method:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if( scrollView.contentOffset.y > someValue ) {
// Enable Buttons
}
else {
// Make / Keep buttons inactive..
}
}
An alternative method would be to use some javascript and do some funky stuff with stringByEvaluatingJavaScriptFromString

use scrollView property of UIWebView and use its delegation call back
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;
to handle the scrolling end event and UIScrollview property contentOffset can tell u that the scroll position with respect to its content size(actual size of ur webpage).

At the launch of application make your toolbar button disable. Then check for current scroll position by adding this line.
int position = [webView stringByEvaluatingJavaScriptFromString:#"window.scrollBy(0,180);"];
Once you scrolled your page to above specific position make your toolbar button enabled.
OR
You can use scroll view delegate methods.

Related

Infinite vertical scrollView with loading

Are there any examples of infinite vertical scrollview, something like Facebook and 9gag app. When you scroll it shows for example pictures, but it stops after lets say 10 pictures showing refresh/loading indicator, and then loading new pictures (so it doesn't have to download all pics at app start).
Thanks.
This amazing dev has made it easy to add infinite scroll with a UIScrollView category. You should probably give it a try.
when user scroll upside then it call the following method
#pragma mark -
#pragma mark - Scroll View Delegate Method
- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView == scrollObj) {
CGFloat scrollPosition = scrollObj.contentSize.height - scrollObj.frame.size.height - scrollObj.contentOffset.y;
if (scrollPosition < 30)
{
if ((!spinnerBottom.isAnimating) ) {
[spinnerBottom startAnimating];
[self getAPICall]; //your apicall function
}
}
}
}

check if UIWebView scrolls to the bottom

How do I check/call a method when a user is at the bottom of the UIWebView when scrolling? I want to popup a view (add a subiview) when the user is at the bottom of the content.
Building on other ideas here, UIWebView conforms to the UIScrollViewDelegate protocol. You could subclass UIWebView and override the appropriate UIScrollViewDelegate methods, calling [super ...] so the original behavior is still present.
#interface SpecialWebview : UIWebView
#end
#implementation SpecialWebview
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[super scrollViewDidScroll:scrollView];
// Check scroll position and handle events as needed...
}
#end
First get the reference to the UIWebView scrollView using this property:
#property(nonatomic, readonly, retain) UIScrollView *scrollView
Once you get the reference to it you could check for the contentSize of it and compare it with the contentOffSet. You cannot make yourself a delegate of it, since the UIWebView is already the delegate for the scrollView, but that trick should work.
The problem is that you don't get the callBack when the scrolling is happening... so you would have to check every so often. Otherwise you will have to make yourself the delegate of the scrollView, and implement all the methods that UIWebView is implementing and mimic that behavior, and then check on the didScroll for that condition.
Another option would be to inject some JavaScript into the web view and then use the window.onscroll event in JavaScript to detect when the user has scrolled to the bottom of the window (you can find plenty of examples online if detecting scroll events using JS).
Once you detect the the user is at the bottom, you could call back to the app by loading a fake url in the web view from the JavaScript by saying document.location.href = "http://madeupcallbackurl", then use the web view delegate to intercept that request and perform your native code logic.
Using the scrollview delegate is probably easier though if you can make that work!
Sorry, I was thinking UITableView. You are asking about a UIWebView. I don't know if this will work with the UIWebView.
I have code that does this using a UIScrollViewDelegate.
#interface myViewController : UIViewController_iPad <UIScrollViewDelegate> {
UITableView *myTableView;
...
}
- (void)viewDidLoad {
myTableView.delegate = self;
...
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// If necessary, verify this scrollview is your table:
// if (scrollView == myTableView) {
CGPoint offset = myTableView.contentOffset;
if (myTableView.contentSize.height - offset.y >= myTableView.bounds.size.height)
{
// The table scrolled to the bottom. Do your stuff...
}
// }
}
This is how I would do it.
UIWebView conforms to UIScrollViewDelegate. Use the - (void)scrollViewDidScroll:(UIScrollView *)scrollView callback to keep track of when your UIWebView is scrolling:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//The webview is is scrolling
int xPosition = [[webView stringByEvaluatingJavaScriptFromString: #"scrollX"] intValue];
int yPosition = [[webView stringByEvaluatingJavaScriptFromString: #"scrollY"] intValue];
}
Now this method will be invoked whenever your webView scrolls. Your webView will have scrolled to the bottom when:
webView_content_height - webView(y) = webView.frame.height; //pseudo code
Your delegate callback will now look like:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//The webview is is scrolling
int xPosition = [[webView stringByEvaluatingJavaScriptFromString: #"scrollX"] intValue];
int yPosition = [[webView stringByEvaluatingJavaScriptFromString: #"scrollY"] intValue];
if([webView stringByEvaluatingJavaScriptFromString: #"document.body.offsetHeight"] - yPosition == webView.frame.height)
{
//The user scrolled to the bottom of the webview
}
}
What the code translates to is that when the user scrolls to the bottom of the content, the difference between the webView's y Position (which is the y-coordinate of the webView's top left corner) and the bottom of the content will be equal to the height of the webview frame. The code acts upon this condition being satisfied to enter inside the if condition.
To be on the safe side, you could modify the if condition to have a margin for error (maybe + or - 10 pixels).

iPhone - UIWebView: Detect User Scrolling to Bottom of Page

So, I have a UIView with a UIWebView inside serving up a local HTML file (a document preview). I also have "Accept" & "Reject" UIButtons. I need these buttons to only appear after the user has scrolled to the bottom of the web page. Is there a way to capture an event for scrolling to the bottom of a UIWebView?
I have not seen any good answers for this, can anyone help?
Thanks in advance.
UIWebView conforms to UIScrollViewDelegate. As such, you can create a subclass of UIWebView (say, ScrollDetectWebView) and capture the calls to the UIScrollViewDelegate.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[super scrollViewDidScroll: scrollView];
// Whatever scroll detection you need to do
}
huh?
Why not just included the buttons on the bottom of the page?
JavaScript lets handle the scrolling event and send message to Objective-c.
- (void)viewDidLoad {
[super viewDidLoad];
self.webView.scrollView.delegate = self;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
CGSize fittingSize = [self.webView sizeThatFits:CGSizeZero];
CGFloat height1 = scrollView.bounds.origin.y + self.webView.bounds.size.height;
CGFloat height2 = fittingSize.height;
int delta = fabs(height1 - height2);
if (delta < 30) {
NSLog(#"HELLO!!! You reached the page end!");
}
}

Properly zooming a UIScrollView that contains many subviews

I created a zoomable UIScrollView and added 100 subviews to it (tiled). The view scrolls perfectly left and right. However, I'd like to allow zooming.
To do so I read that my delegate needs to implement:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return ???;
}
I have seen examples that have only one subview to zoom, so they return that subview in that method. In my case, however, I have a lot more. What is the proper way to do the zooming?
I tried creating another UIView and adding the 100 subviews to that one. And then return that one view on the method above, but I doesn't work (it zooms but once it stops, it's not interactive any more).
Exactly,
This is what Apple also is mentioning in the Scroll View Programming Guide:
Just create a view, add all subviews to this view and add the newly created view as a single subview to the scrollview...
Then in the viewForZoomingInScrollView delegate method return the object at Index 0:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return [self.scrollView.subviews objectAtIndex:0];
}
I created the view where I added everything using:
UIView *zoomableView = [[UIView alloc] init];
without setting its frame.
The problem was solved when, after adding all the subviews to it, I set its frame to something large enough to accommodate all the tiled subviews.
You have to return what your going to add views to scroll view as a subviews.
Ex: If you are adding image view to scroll view then write
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return imageView object;
}

Is there a way to create a scrollViewISZooming method similar to the scrollViewDidEndZooming?

I am looking for a way to create a scrollViewIsZooming method that is called while zooming is occuring. Does anyone know of a way to do this?
I am wanting to use it to keep the content centered in the scrollView while zooming. If I use the scrollViewDidEndZooming method, the content snaps back to the center after zooming is finished.
Thanks!
There's a zooming propriety on UIScrollView :
#property(nonatomic, readonly, getter=isZooming) BOOL zooming
If you check it in each
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
call it should work.
What about viewForZoomingInScrollView:
If you put a pinch gesture recogniser in the view then connect it to an action you can control zooming that way. I have an action "doPinch" and an outlet "pinchRecognizer" that I use like this:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.zoomableImage;
}
Then
- (IBAction)doPinch:(id)sender
{
NSLog(#"In the pinch action now with scale: %f", self.pinchRecognizer.scale);
[scrollView setZoomScale:self.pinchRecognizer.scale animated:NO];
}
Might be easier. Note that scrollView is my outlet connected to the scroll view.