How to detect zoom scale of UIWebView - iphone

I want to increase height of UIWebView while user zoom in (like default mail app in iPhone).
So, I have tried the code below to find scrollview in webview and add UIScrollViewDelegate to use scrollViewDidZoom for detecting zoom scale to increase height of webview on this method.
// MessageAppDelegate.h
#interface MessageAppDelegate : NSObject <UIApplicationDelegate,UIWebViewDelegate,UIScrollViewDelegate> {
UIWebView *webview;
UIScrollView *scrollview;
}
//MessageAppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
[self.window makeKeyAndVisible];
webview = [[UIWebView alloc] initWithFrame:CGRectMake(0, 150, 320, 100)];
webview.delegate = self;
webview.scalesPageToFit = YES;
webview.userInteractionEnabled = YES;
[webview loadHTMLString:#"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=6.0 user-scalable=yes\">test test" baseURL:nil];
[self.window addSubview:webview];
// Find scrollview in webview
for (UIView *view in webview.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
// Get UIScrollView object
scrollview = (UIScrollView *) view;
scrollview.delegate = self;
}
}
return YES;
}
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale{
NSLog(#"scale %f",scale);
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView{
NSLog(#"scrollViewDidZoom %f",scrollview.zoomScale);
}
The problem is I cannot zoom in/out on the webview
but NSLog on scrollViewDisEndZooming method showed
scale 1.0
when I ended zooming
and scrollViewDidZoom method didn't show anything.
I want to detect zoom scale of webview for calculating its height on scrollViewDidZoom.
What I've done wrong?
Please help.
Thanks in advance.

I have done well for your code up,do following modificaitons:
you just get the scrollview class point ,then can get the scrollview.contentSize.width,which can change when you zoom in out,but scrollview.zoomScale always remains 1.so have to use contensize.width to calculate scale.
#interface dictViewController : UIViewController<UIWebViewDelegate,UITextFieldDelegate,UIGestureRecognizerDelegate,UIScrollViewDelegate>{
UIScrollView *scrollview;
......................
//scrollview.delegate = self;
for (UIView *view in webViewM.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
// Get UIScrollView object
scrollview = (UIScrollView *) view;
//scrollview.delegate = self;
}
}
/*
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale{
//NSLog(#"scale zooming %f",scale);
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView{
//NSLog(#"scrollViewDidZoom %f",scrollview.zoomScale);
}*/
- (void)swipeRightAction:(id)ignored
{
NSLog(#"wid=%f", scrollview.contentSize.width);
NSLog(#"zoomscale=%f", scrollview.zoomScale);
}

I don't think there's a proper way to do it from the exposed APIs, but there is a hacky way.
A UIWebView contains a UIScrollView which can be given a delegate. Then when zooming changes, you (the delegate) get a callback called scrollViewDidZoom:.
In order to find the scroll view, you can get the subviews collection from the web view and iterate to see which one isKindOfClass:[UIScrollView class].
Now, UIWebView also conforms to UIScrollViewDelegate. So that may mean you are changing the web view's implementation, and that could be a Bad Idea. Test well.

Related

How can i set content offset on multiple scrollviews with one method?

I am having a little problem. I want to make all my scrollview scroll to the top when I press a UITableViewCell. Following is the code in didSelectRowAtIndexPath:
[self.tableView setContentOffset:CGPointZero];
[verbTableView setContentOffset:CGPointZero];
[seinhabenScrollView setContentOffset:CGPointZero];
[mdhPresensScroll setContentOffset:CGPointZero];
[mdhPreteritumScroll setContentOffset:CGPointZero];
[mhdScroll setContentOffset:CGPointZero];
....
There are more of those scrollview, and I want to put the all in one single object or something... I have tried following code:
for (UIScrollView *scrolls in topLayer.subviews)
{
[scrolls setContentOffset:CGPointZero];
}
Thanks!
The basic idea is right. It just depends upon how you identify the scroll views. You could do something like the following, which explicitly tests whether the subview is a kind of UIScrollView:
for (UIScrollView *scrollView in self.view.subviews)
{
if ([scrollView isKindOfClass:[UIScrollView class]])
scrollView.contentOffset = CGPointZero;
}
Or you can explicitly reference the specific scrollviews in question (in which case the class membership test isn't strictly needed):
for (UIScrollView *scrollView in #[seinhabenScrollView, mdhPresensScroll, mdhPreteritumScroll])
{
scrollView.contentOffset = CGPointZero;
}
Or, if you create an IBOutletCollection in IB, you can use that, too:
for (UIScrollView *scrollView in self.scrollViews)
{
[scrollView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
}
(Note, in that final example, I'm scrolling to the location in question with animation, providing the user some visual cue as to what just happened; that's completely up to you.)
In a comment above, you say that topView has subviews which, themselves, have subviews that are scrollviews, you'd have to do something like the following to handle this subview-of-subview situation:
for (UIView *subview in topLayer.subviews)
{
for (UIScrollView *scrollView in subview)
{
if ([scrollView isKindOfClass:[UIScrollView class]])
scrollView.contentOffset = CGPointZero;
}
}
Avoiding the dynamic type check, just place the views that can scroll into an array. Then, a little fancier, add an extension to scroll view so they can scroll to zero using no params, that let's us do the scrolling with an NSArray one-liner (makeObjectsPerform...)...
#interface UIScrollView (ScrollToZero)
- (void)scrollToZero; // a no-param method for scrolling to zero offset
#end
#implementation UIScrollView (ScrollToZero)
- (void)scrollToZero {
[self setContentOffset:CGPointZero animated:YES];
}
#end
NSArray *allMyScrolls = #[verbTableView, seinhabenScrollView, // and so on. put ONLY scrollViews in here
// you can make this array a property, initialized when the views are created
[allMyScrolls makeObjectsPerformSelector:#selector(scrollToZero)];

Rendering content after zoomed in for UIScrollView

I've looked around and it seems like people say you can re-render the data after you zoom in now that you know the scale factor for UIScrollView. I've also seen some posts about making your layer to a CATiledLayer and set the levelsOfDetailBias and levelsOfDetail.
What I have is a UIScrollView, and in it, a ResultsView which is a subclass of UIView:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
CATiledLayer *tiledLayer = (CATiledLayer *)self.layer;
tiledLayer.levelsOfDetailBias = 3;
tiledLayer.levelsOfDetail = 3;
self.opaque = YES;
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
+ (Class)layerClass {
return [CATiledLayer class];
}
In my class where I have the UIScrollView and ResultsView, I do:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return self.ResultsView;
}
Is this enough to have the text rerendered (sharp)? Or do I need to implement something in
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
}
If so, I'm not sure how to do that. In my class with UIScrollView and ResultsView, in ResultsView (in the XIB), I just have a couple of UILabels and UIViews (UIViews used for headings/footers for the view). So I do not know how to redraw those from ResultsView. Although ResultsView has the UILabels and UIViews as children of it in the XIB, I'm not sure how I would redraw those from the ResultsView class, and what I would need to do anyway.
Or is this the wrong approach? Do I just need to resize the UILabel and UIView by the scale factor in the scrollViewDidEndZooming: delegate method? TIA
I think you are taking the wrong approach. If your view consists of UILabels and UIViews that do not do any custom drawing, I would not mess with using a CATiledLayer backed view. Instead implement the scrollViewDidEndZooming:withView:atScale: delegate method and do something like this:
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
scale *= [[[self.scrollView window] screen] scale];
[view setContentScaleFactor:scale];
for (UIView *subview in view.subviews) {
[subview setContentScaleFactor:scale];
}
}
I have something small to add to the accepted solution that caused me a few minutes of pain just in case anyone else runs into the same thing.
Looping through all subviews in the view you're zooming and calling setContentScaleFactor doesn't take into account if any of the subviews themselves have subviews. If you have a more complicated setup like that, make sure to also loop through the subviews of those container views and call
[subview setContentScaleFactor:scale];
on each. I made a method that I can invoke to call setContentScaleFactor on all the subviews of a given view and call that for each "container view" on the screen.
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
scale *= [[[self.scrollView window] screen] scale];
[view setContentScaleFactor:scale];
for (UIView *subview in view.subviews)
{
[self setContentSizeForView:subview andScore:scale];
//Loop through all the subviews inside the subview
for(UIView *subSubview in subview.subviews)
{
[self setContentSizeForView:subSubview andScale:scale];
}
}
}
- (void) setContentSizeForView:(UIView*) view andScale:(float)scale
{
[view setContentScaleFactor:scale];
}

Open a view on image Click in cover flow

I am using cover flow library in my project.My cover flow consist of many images.What I want to do is when I click on that image another View Controller should gets open.
Please tell me how to open another view on that image click.
Any help will be highly appreciated.
I had the same problem yesterday. I had to change something in the framework.
Add these two methods in the interface
#interface AFOpenFlowView : UIView
- (AFItemView *)selectedCoverView;
- (UIScrollView *)scrollView;
Add the implementations of these two methods inside of the .m file
#implementation AFOpenFlowView
- (AFItemView *)selectedCoverView {
return selectedCoverView;
}
- (UIScrollView *)scrollView {
return scrollView;
}
Set a UITapGestureRecognizer in the view controller where you're using the AFOpenFlowView
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(screenTapped:)];
[[self view] addGestureRecognizer:tapRecognizer];
[tapRecognizer release];
}
At the end implement the method to handle the tap on the screen
- (void)screenTapped:(UITapGestureRecognizer *)tap {
CGPoint point = [tap locationInView:[af scrollView]];
if (CGRectContainsPoint([[af selectedCoverView] frame], point)) {
// Write here the code to open your view
// Use [af selectedCoverView].number to get the index of the selected cover
NSLog(#"selected cover view: %d", [af selectedCoverView].number);
}
}
Hope it's going to save you some time! ;)
Please try other FlowCover this is very easy to use...
Thanks

dismissing the NumberPad keyboard from a UIScrollView

I have an application with UIScrollView added as a subview of UIView. This Scroll view has a textfield with keyboard type set to numberPad.
Now the problem is , i want to dismiss the keyboard when i tap anywhere else in the scroll view. how can i do this ... ?
Just call the textField's resignFirstResponder in the touch handler.
(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[myTextField resignFirstResponder];
}
When I added the gesture to a subclass of UIScrollView, I was having problems with the various gestures in my view tree interfering with each other, such as being able to click on subviews, scroll the view, and have the keyboard dismiss in all cases. I came up with this solution, which can be setup from a superclass of UIScrollView or from a UIViewController.
The DismissKeyboardTapGesture class uses ARC, works with any text fields under the view, and doesn't take over any clicks from subviews like buttons. Also takes advantage of iOS7 scrolling effect to dismiss keyboard.
Setting up from UISScrollView superclass:
_dismissKeyboard = [[DismissKeyboardTapGesture alloc] initWithView:self];
or from UIViewController:
_dismissKeyboard = [[DismissKeyboardTapGesture alloc] initWithView:self.view];
Here is the class:
#interface DismissKeyboardTapGesture : NSObject <UIGestureRecognizerDelegate>
#end
#implementation DismissKeyboardTapGesture
- (id)initWithView:(UIView *)view
{
self = [super init];
if (self) {
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTap:)];
singleTap.cancelsTouchesInView = NO;
singleTap.delegate = self;
[view addGestureRecognizer:singleTap];
if ([view respondsToSelector:#selector(setKeyboardDismissMode:)]) {
// Bonus effect to dismiss keyboard by scrolling
((UIScrollView *)view).keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
}
}
return self;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
// Don't stop any existing gestures in our view from working
if (otherGestureRecognizer.view == gestureRecognizer.view) {
return YES;
}
return NO;
}
- (void)singleTap:(UIGestureRecognizer*)gestureRecognizer
{
// Close keyboard for any text edit views that are children of the main view
[gestureRecognizer.view endEditing:YES];
}
#end

UIScrollView on scroll update method

is there a method / possibility to run a function when the scrollview is scrolling?
i found scroll start and scroll end solutions but nothing like a onIsScrolling ...
is there a built in solution? or whats the best workaround (nstimer)?
thanks
Alex
UIScrollViewDelegate provides the following:
– scrollViewDidScroll:
– scrollViewWillBeginDragging:
– scrollViewDidEndDragging:willDecelerate:
– scrollViewShouldScrollToTop:
– scrollViewDidScrollToTop:
– scrollViewWillBeginDecelerating:
– scrollViewDidEndDecelerating:
in particular:
– scrollViewDidScroll:
Thanks a lot for the scrollViewDidScroll tip.
heres the implemtation sample:
#interface YourClass : UIViewController <UIScrollViewDelegate>
{
UIScrollView *theView;
}
#end
in .m file:
- (void)loadView
{
theView = [[UIScrollView alloc] initWithFrame:
CGRectMake(0, 10, 300, 300)];
theView.delegate = self;
[self.view addSubview:theView];
theView.contentSize = CGSizeMake(500, 500);
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog(#"SCROLL SCROLL SCROLL YOUR BOAT");
}