UIWebView, scrolling enabled but not bounces - objective-c

In my UIWebView I want to enable scrolling, but also disable the bounce effect (when I'm at the top and move my fingerdown and see a black block).
I tried a lot of combinations, but it seems that when I write:
myUIWebView.scrollView.bounces = NO;
this also disables scrolling entirely.
How can I do this?

Try this:
for (id subview in myUIWebView.subviews) {
if ([[subview class] isSubclassOfClass:[UIScrollView class]]) {
((UIScrollView *)subview).bounces = NO;
}
}
As I know, that line, what you wrote, works only in iOS 5.0.

Related

iOS 7 UITextView - layoutSubviews infinite loop

I have UITextView:
textView = [[UITextView alloc] init];
textView.scrollEnabled = NO;
I have a problem only on iOS7:
On every keyboard keystroke, layoutSubviews is called on superview. After writing several characters, it gets stuck in infinite loop and keeps calling layoutSubviews constantly.
When I remove textView.scrollEnabled = NO; line of code, everything works the way it is supposed to.
I would really like to disable scrolling on my text view. Does anybody have an idea how to do it?
In the end I hacked the whole thing by placing a Pan Gesture on UITextView. This way all functionalities of editing text view were preserved and scrolling was disabled.
When I wanted to disable scrolling of text view, I didn't set scrollEnabled = NO. Instead I added Pan Gesture recognizer on UITextView. When I wanted to enable scrolling, I just removed that same Pan Gesture recognizer from text view.
Like this:
init method...
_scrollDisablerGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(textViewScrollAction:)];
// method textViewScrollAction does nothing, empty implementation
[_textView addGestureRecognizer:_scrollDisablerGR];
somewhere else in code:
if (shouldEnableScrolling) {
[self.textView removeGestureRecognizer:_scrollDisablerGR];
} else {
if (!_scrollDisablerGR.view) {
[self.textView addGestureRecognizer:_scrollDisablerGR];
}
}
Works great ;)

Added whitespace in UIWebview - removing UIWebView whitespace in iOS7 & iOS8

Im loading local html files, since iOS7 there is added white space on top in the UIWebView.(I cant post an image as i do not have enough points.)
image can be seen here- snap shot from iPhone simulator, uiwebview surrounded by black frame, the html content is grey, but there is white added above it
I have tried to adjust the zoom using
[webView stringByEvaluatingJavaScriptFromString:#"document. body.style.zoom = 5.0;"];
webView.scalesPageToFit = NO;
credit to: Srikar Appal
I also set tried to remove white spacing:
NSString *padding = #"document.body.style.margin='0';document.body.style.padding = '0'";
[webView stringByEvaluatingJavaScriptFromString:padding];
credit to: thenextmillionaire
still no luck. In the desktop chrome browser there is no whitespace. The html files are Google Swiffy files - containing html and JSON.
edit: updated Image
Try self.automaticallyAdjustsScrollViewInsets = NO; in ViewDidLoad.
ios 7 add 64px automatically for scroll view. (status bar and nav bar)
This problem only affects the UIWebView if it is the first subview of the parent view. One alternative way to work around this problem is to add another non-visible empty view to the parent view as the first view. In Interface Builder add a zero size subview and use the Editor->Arrange->Send to Back menu command.
If you're not using Interface Builder, but instead are subclassing the UIWebView, then it can be done by creating a UIView instance variable called scrollFixView and overriding the following methods:
- (void)didMoveToSuperview
{
[super didMoveToSuperview];
if ([self superview].subviews.firstObject == self) {
_scrollFixView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
_scrollFixView.hidden = YES;
[[self superview] insertSubview:_scrollFixView belowSubview:self];
}
}
- (void)removeFromSuperview
{
if (_scrollFixView) {
[_scrollFixView removeFromSuperview];
_scrollFixView = nil;
}
[super removeFromSuperview];
}
I had the same problem so I tried a few things:-)
This worked for me, but correct me please if there is a better way.
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
if(self.navigationController.navigationBar.translucent == YES)
{
_webView.scrollView.contentOffset = CGPointMake(_webView.frame.origin.x, _webView.frame.origin.y - 54);
}
}
So basically you need to :
1) Add the UIWebView delegate method - webViewDidFinishLoad:
2) Then I setup an if statement to check if the translucent option is active.
The last one you only need to do of course if you give the user the option within your app.
The number after the _webView.frame.origin.y is just for my app. It may differ for you.
I solved this problem by simply setting a constraint on the WebView, setting the top space between it and the View top to 0, causing the NavBar to overlap the whitespace.
One alternative to Jeff Kranenburg's method is to subclass and override the UIWebView subclasses' UIScrollViewDelegate method scrollViewDidScroll:. This is only appropriate if scrolling is turned off for your subclass.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if ([[self superclass] instancesRespondToSelector:_cmd]) {
[super scrollViewDidScroll:scrollView];
}
[self fixUpScrollViewContentOffset];
}
- (void)fixUpScrollViewContentOffset
{
if (!CGPointEqualToPoint(self.scrollView.contentOffset, CGPointZero)) {
self.scrollView.contentOffset = CGPointZero;
}
}
I already got it .
here my logic code, When the application open the website you must get the size of your webview then set it on height
here my code
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) webpage.getLayoutParams();
p.height = webpage.getHeight();
// check if how long you need to set your height for webpage then set it :)
Log.e(" webpage.getHeight()", String.valueOf(webpage.getHeight()));
webpage.setLayoutParams(p);
Hope you will take my code and my answer to :) works on any devices even tabs too :)

Disable double tap zoom in MKMapView (iOS 6)

in ios 5 i was able to disable the double tap zoom by just overriding it with a new double tap gesture. But it seems that the double tap gesture is no longer in the gesturerecognizer array that comes with the mkmapview.
NSArray *gestureRecognizers = [_mapView gestureRecognizers];
for (UIGestureRecognizer *recognizer in gestureRecognizers) {
NSLog(#"%#", recognizer);
}
returns nothing in ios 6, where in ios 5 it would return 2 recognizers, one for single tap and one for double tap.
I'd look through the gesture recognizers of MKMapView's subviews. It's probably still there somewhere.
Of course, messing around with another view's GRs is slightly dubious and will likely break the next time Apple changes something about MKMapView...
EDIT: For the benefit of anyone else reading this, please check that it's a UITapGestureRecognizer and that numberOfTapsRequired == 2 and numberOfTouchesRequired == 1.
Also, instead of disabling double-taps on the map entirely, consider adding a double-tap GR on the annotation and then do [mapDoubleTapGR requireGestureRecognizerToFail:annotationDoubleTapGR]. Again, hacky — don't blame me if it breaks on the next OS update!
This worked for me:
[_mapView.subviews[0] addGestureRecognizer:MyDoubleTapOverrider];
Do you want to let the user do anything with the view? If not, it sufficient to set userInteractionEnabled to NO. If so, what specific interactions do you need to allow? Everything but double-tapping? Why disable that one interaction?
The more we know about your use case, the better the answers we can provide.
This works for me:
//INIT the MKMapView
-(id) init{
...
[self getGesturesRecursive:mapView];
...
}
And then let the recursive function loop through the subviews and find the GR:s.
-(void)getGesturesRecursive:(UIView*)v{
NSArray *gestureRecognizers = [v gestureRecognizers];
for (UIGestureRecognizer *recognizer in gestureRecognizers) {
if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]) {
[v removeGestureRecognizer:recognizer];
}
}
for (UIView *v1 in v.subviews){
[self getGesturesRecursive:v1];
}
}
This example removes all tap-GR:s. But I guess you can specify to remove whatever you'd like.
You can use a long tap gesture instead, that works.

UITableViewCell subclass, drawn in code, animate Delete button in

I'm working on a custom UITableViewCell subclass, where everything is drawn in code rather than using UILabels etc. (This is part learning exercise and partly because drawing in code is much faster. I know that for a couple of labels it wouldn't make a huge difference, but eventually I'll want to generalise this to more complex cells.)
Currently I'm struggling with the delete button animation: how to animate the cell shrinking as the delete button slides in.
Firstly, I am drawing in a custom subview of the cell's contentView. Everything is drawn in that one subview.
I am setting the subview's size by catching layoutSubviews on the cell itself, and doing:
- (void)layoutSubviews
{
[super layoutSubviews];
CGRect b = [self.contentView bounds];
[subcontentView setFrame:b];
}
I'm doing this rather than just setting an autoresizing mask because it seemed more reliable in testing, but I can use the autoresizing mask approach in testing if needed.
Now, the default thing that happens when someone hits the minus is the view gets squished.
I can avoid that by, when setting up my cell, calling
subcontentView.contentMode = UIViewContentModeRedraw;
That gives me the correct end result (my custom view redraws with the new size, and is laid out properly, like the first image I posted), but the animation of the transition is unpleasant: it looks like the cell stretches and shrinks back to size.
I know why the animation is working like that: Core Animation doesn't ask your view to redraw for each frame, it gets it to redraw for the end position of the animation and then interpolates to find the middle bits.
Another solution is to do
subcontentView.contentMode = UIViewContentModeLeft;
That just draws the delete button over my cell, so it covers part of it.
If I also implement
- (void) didTransitionToState:(UITableViewCellStateMask)state
{
[self setNeedsDisplay];
}
then once the delete button has slid in the cell 'jumps' to the correct size. That way there's no nice slidey animation, but at least I get the correct result at the end.
I guess I could run my own animation in parallel with the delete button appearing, temporarily creating another view with a copy of the image of my view in the old size, setting mine to the new size, and fading between them — that way there would be a nice cross fade instead of a sharp jump. Anyone use such a technique?
Now, you might ask why I can't use the contentStretch property and give it a region to resize. The problem with that is I'm making something to be reasonably generic, so it's not always going to be possible. In this particular example it'd work, but a more complex cell may not.
So, my question (after all of this background) is: what do you do in this situation? Does anyone have the animating delete button working for custom drawn cells? If not, what's the best compromise?
This worked for me finally. in subclass of UITableViewCell
subDrawContentView.contentMode = UIViewContentModeLeft;
overide layout subviews method
- (void)layoutSubviews {
CGRect b = [subDrawContentView bounds];
b.size.width = (!self.showingDeleteConfirmation) ? 320 : 300;
[subDrawContentView setFrame:b];
[subDrawContentView setNeedsDisplay];
[super layoutSubviews];
}
So I will paste the code first and then I will explain:
-(void)startCancelAnimation{
[cancelButton setAlpha:0.0f];
[cancelButton setFrame:CGRectMake(320., cancelButton.frame.origin.y, cancelButton.frame.size.width, cancelButton.frame.size.height)];
cancelButton.hidden=NO;
[UIView animateWithDuration:0.4
animations:^(void){
[progressView setFrame:CGRectMake(progressView.frame.origin.x, progressView.frame.origin.y, 159.0, progressView.frame.size.height)];
[text setFrame:CGRectMake(text.frame.origin.x, text.frame.origin.y, 159.0, text.frame.size.height)];
[cancelButton setFrame:CGRectMake(244., cancelButton.frame.origin.y, cancelButton.frame.size.width, cancelButton.frame.size.height)];
[cancelButton setAlpha:1.0f];
} ];
}
-(void)stopCancelAnimation{
[UIView animateWithDuration:0.4
animations:^(void){
[cancelButton setFrame:CGRectMake(320., cancelButton.frame.origin.y, cancelButton.frame.size.width, cancelButton.frame.size.height)];
[cancelButton setAlpha:0.0f];
}completion:^(BOOL completion){
cancelButton.hidden=YES;
[cancelButton setAlpha:1.0f];
[progressView setFrame:CGRectMake(progressView.frame.origin.x, progressView.frame.origin.y, DEFAULT_WIDTH_PROGRESS, progressView.frame.size.height)];
[text setFrame:CGRectMake(text.frame.origin.x, text.frame.origin.y, DEFAULT_WIDTH_TEXT, text.frame.size.height)];
}
];
}
-(void)decideAnimation{
if([cancelButton isHidden]){
[self startCancelAnimation];
}
else{
[self stopCancelAnimation];
}
}
So what I have there is a button that looks like this:
I have an IBOutlet to it. And what I am doing is resizing a UIProgressView and a UITextField (you can resize whatever you want). As for the code is pretty simple, but if you need any help to understand what's going on, please ask. Also, don't forget to add the Swip Gesture to the UITableView... Like this:
UISwipeGestureRecognizer *gesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(didSwipe:)];
gesture.numberOfTouchesRequired=1;
gesture.direction = UISwipeGestureRecognizerDirectionRight;
[table addGestureRecognizer:gesture];
[gesture release];
Finally the method that does it all:
-(void)didSwipe:(UIGestureRecognizer *)gestureRecognizer {
if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {
//Get the cell of the swipe...
CGPoint swipeLocation = [gestureRecognizer locationInView:self.table];
NSIndexPath *swipedIndexPath = [self.table indexPathForRowAtPoint:swipeLocation];
UITableViewCell* swipedCell = [self.table cellForRowAtIndexPath:swipedIndexPath];
//Make sure its a cell with content and not an empty one.
if([swipedCell isKindOfClass:[AMUploadsTableViewCell class]]){
// It will start the animation here
[(AMUploadsTableViewCell*)swipedCell decideAnimation];
// Do what you want :)
}
}
}
So as you can see the whole animation is created manually, so you can control exactly what you want. :)

How to disable horizontal scroll in uiwebview?

I am using uiwebview in my code and implemented swipe function on uiwebview. For swipe function i have set YES for scaleToFir property for webview, when we give, scaleToFit=YES, content get shrinked. But for my case both needed. swipe aswell as content should not shrink. But disable horizontal bar is fine. can you please help me out?
Srini
for (UIScrollView *scroll in [webview subviews]) {
// Make sure it really is a scroll view and reset the zoom scale.
if ([scroll respondsToSelector:#selector(setZoomScale:)]){
scroll.bounces=FALSE;
}
}
Try This:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSLog(#"loaded");
[webView.scrollView setContentSize: CGSizeMake(webView.frame.size.width, webView.scrollView.contentSize.height)];
}