Set Scroll Boundaries UIWebView - objective-c

I have a UIWebView which displays a webpage. The problem is I only want it to display a part of the webpage. I tried using [[_menuWebView scrollView] setContentOffset:CGPointMake(0, 100)]; to set the content offset to where I want it, but the problem is that I don't want the user to be able to scroll around the rest of the webpage. I also cannot set the webpage to not be scrollable because the part that I need to be able to be seen is slightly bigger than the space available. Is there a way to either:
Resize the view to only show one small portion so I can set it to not be scrollable
Set the scrolling boundaries in some way so that the user cannot scroll to the top of the page and not too far to the bottom either.
Thanks in advance!
EDIT:
I have used the code in the answer to get the UIWebView to not scroll past the top, the problem is getting it not to scroll past the bottom. I use this code to check where the contentOffset should be if it has hit the bottom: _bottom_y = [[_menuWebView scrollView] contentSize].height - 20 - [_menuWebView frame].size.height;. When I NSLog _bottom_y it comes up with 68 as where the bottom offset should be. The problem is that the top offset I know to be 115 and that works. What is wrong with the code above? Why is it giving me this weird number?
Thanks

I think this will be a good answer to your question. UIWebView in its structure contains an UIScrollView, that is why you can set your UIViewController to be a delegate of UIScrollView. Thus you can implement a method called scrollViewDidScroll: where you check if the UIWebView reached its y offset and if yes -> not let it scroll past that point.
Here is an example, that I have used:
#interface ViewController : UIViewController <UIScrollViewDelegate>
#property (weak, nonatomic) IBOutlet UIWebView *webView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_webView.scrollView.delegate = self;
[_webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://google.com"]]];
_webView.scrollView.contentOffset = CGPointMake(0, 50);
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView.contentOffset.y < 50) {
scrollView.contentOffset = CGPointMake(0, 50);
}
}
#end
Hope this helps, cheers!

Related

UIImageView shifts left before animating to the right

Newbie here,
With this code in the .m file I aimed to animate an UIImageView to the right
#interface ViewController ()
#property (strong, nonatomic) IBOutlet UIImageView *myImageView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
self.myImageView.center = CGPointMake(self.myImageView.center.x + 100, self.myImageView.center.y);
}
completion:^(BOOL finished){
}];
}
But what actually happens is that the image view shifts 100 points to the left and then animates to the right by 100 points back to its original position. I don't know why this happens. How can I achieve an animation that moves directly to the right?
Note: I'm not sure if this has to do with anything, but I added constraints in the interface builder to center this UIImageView in the middle.
Create IBOutlets for the constraints you want change. Just like you would for any other UIKit element. Then in your code instead of doing:
self.myImageView.center = CGPointMake(self.myImageView.center.x + 100, self.myImageView.center.y);
Do something like this:
self.imageViewTralingSpaceConstraint.constant = 100; //Or whatever value makes sense
Then in your animateWithDuration block add [self.view layoutSubViews];
you probably want to put this code in your viewDidAppear method rather than your viewDidLoad. this would make the animation happen after the view appears rather than before it. the viewDidLoad method is called after the view hierarchy is loaded into memory but not neccessarily after it is all laid out.
here is a link to the uiviewcontroller reference. https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/
check out these two methods there. if you continue doing iOS development you will get to know these methods really well.

Embed ImageView in ScrollView with Auto Layout on iOS 6

I am trying to make very simple element with new iOS 6 SDK with auto layout.
I have an ImageView and Embed it in ScrollView. (everything build with Interface Builder). The .png file is set and imageView mode is set to "Top Left".
Implementation:
#import "ImaginariumViewController.h"
#interface ImaginariumViewController ()
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#end
#implementation ImaginariumViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.scrollView.contentSize = self.imageView.image.size;
self.imageView.frame =
CGRectMake(0, 0, self.imageView.image.size.width, self.imageView.image.size.height);
}
#end
When I run the app, the image is not scrolled. Doing all the same with auto layout turned off (with struts and springs), I have working scrolling.
I guess the problem is with constraints. Could anybody help me, please?
I just encountered the same issue in a tutorial that I was updating. I attempted programmatically deleting constraints, cursing, and banging my head against the wall - no luck.
About 5 minutes ago, however, I tried something that had fixed another issue I encountered, and, ta da! UIScrollView is working again! The solution was to move the old code that sets the UIScrollView contentSize property into an implementation of viewDidAppear, rather than viewDidLoad:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.theScroller.contentSize=CGSizeMake(200.0,2000.0);
}
I hope this helps someone else encountering some of the headaches that have appeared with Auto Layout.
Autolayout can be very confusing at first. You actually don't want to set the contentSize of the scrollview anywhere. With a pure autolayout approach the scrollview sets its own content size. See the section on autolayout and UIScrollView in the iOS 6 release notes:
The constraints on the subviews of the scroll view must result in a
size to fill, which is then interpreted as the content size of the
scroll view. (This should not be confused with the
intrinsicContentSize method used for Auto Layout.)
Note that this means that the constraints on the subviews of the scrollview must set explicit widths and heights and not use widths that vary based on aspects of the scrollview.
The second error here is that you set the frame of the UIImageView to the size of the image. With autolayout this is also unnecessary. The UIImageView actually has an intrinsicContentSize which is the size of the underlying image. (To change this you should set constraints for width and height with a high priority) That means that with auto layout to place an image in a scrollview and have it scroll the correct code should be the following:
** nothing at all!!! **
But theres still something you need to watch out for that could cause you to have an image that appears not to scroll and the hint is in the aforelinked release notes:
Note that you can make a subview of the scroll view appear to float
(not scroll) over the other scrolling content by creating constraints
between the view and a view outside the scroll view’s subtree, such as
the scroll view’s superview.
i.e. if you set constraints in interface builder and constrain the image view to a view above the scrollview in the hierarchy it will affect how the view appears to scroll. Mad!
Happy Coding...

Displaying a button at the bottom when scroll up

I'm a newbie to iOS and i'm trying to develop an application based on news.
In my application , I have a Root View Controller which is a Table View Controller to display news' title and news' images. Well, when users click on the table cell ,there is another View Controller to be displayed which is more detailed and scrollable.
In the View Controller,users can share the news in Facebook and Twitter so that i have two buttons at least. What i want to do is displaying these two button when users scroll up. When users scroll down,i want to make them disappear. There is something like in Pulse News. I have already looked Scroll View delegate methods,but i didn't make it work. How can i accomplish what i want to do ?
Thanks in advance.
Create button at the position where you want in scroll according to scroll position.
origin x of scrollview : scroll.frame.origin.x;
origin y of scrollview : scroll.frame.origin.y;
height of scrollview : scroll.frame.size.height;
width of scrollview : scroll.frame.size.width;
Now you can put the button as you wish on scroll view:
button = [[UIButton alloc] initWithFrame:CGRectMake(x,y,x1,y1);
UPDATED WITH WORKING CODE: Outside of having the buttons scroll off the page so they are not visible
I know you said you looked at the scrollview delegates but this how you would solve this issue. In looking at Pulse the only tricky action is when you scroll down, which is when what look like UIToolbars fade away. The most important thing you need to have is anything that inherits from UIView at the very bottom and top of the visible screen of iPhone so when the user scrolls down or up the contentoffset has a value.
Every other actions cause them to appear sooo Pulse probably did something like this.
#import <UIKit/UIKit.h>
#interface C1ViewController : UIViewController
{
CGPoint _y;
}
#property (weak, nonatomic) IBOutlet UIScrollView *scroller;
#property (weak, nonatomic) IBOutlet UIToolbar *toolbar;
#end
#import "C1ViewController.h"
#interface C1ViewController ()
#end
#implementation C1ViewController
#synthesize scroller = _scroller;
#synthesize toolbar = _toolbar;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.scroller.contentSize = CGSizeMake(self.scroller.frame.size.width, self.scroller.frame.size.height + 100);
self.toolbar.hidden = TRUE;
_y = [self.scroller contentOffset];
}
// this method is getting deprecated, so don't worry about it to much
// but don't forget to dealloc...which I did not include.
- (void)viewDidUnload
{
[self setScroller:nil];
[self setToolbar:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSLog(#"content offset %f", self.scroller.contentOffset);
if (_y.y < [self.scroller contentOffset].y){
self.toolbar.hidden = TRUE;
}
else {
self.toolbar.hidden = FALSE;
}
}
#end
What my view hierarchy looks like in Interface Builder

UITabBar height in iOS 5

With the new customization APIs in iOS 5, is it possible to increase the height of UITabBar? If not, what are some open source options if I want to target iOS 5?
Thanks
My way of customizing UITabBarController's tabbar is to customize UITabBarController itself first.
UITabBarcontroller has two subviews inside. A UITransitionView and a UITabBar. UITransitionView is the area on the top half of the screen where you put your view controllers in.
In order to customize the height of the UITabbar, you also need to edit UITransitionView's frame. So, for instance if you want to change the heights, you can do;
[[tabbarController.view.subviews objectAtIndex:0] setFrame:CGRectMake(0, 0, 320, 440)];
[tabbarController.tabBar setFrame:CGRectMake(0, 440, 320, 50)];
This will create a 50 px height tabbar, (by default it is 48 px)
You can write a category of UItabbar
here is the code :
.h file :
#import <UIKit/UIKit.h>
#interface UITabBar (NewSize)
- (CGSize)sizeThatFits:(CGSize)size;
#end
.m file :
#import "UITabBar+NewSize.h"
#implementation UITabBar (NewSize)
- (CGSize)sizeThatFits:(CGSize)size {
CGSize newSize = CGSizeMake(size.width,44);
return newSize;
}
#end
and then
#import "UITabBar+NewSize.h"
self.tabBarController = [[UITabBarController alloc] init];
[self.tabBarController.tabBar sizeThatFits:CGSizeMake(320, 44)];
self.tabBarController.tabBar.shadowImage = [[UIImage alloc]init]; //delete the default tabbar shadow!
You cannot do that with the UITabBar. I would suggest that you create your own UIToolBarand make it appear like a tabBar, and you can add UIButtons to it and make them appear like tabBarItems.
It will appear like a tabBar and gives you a lot of room for customizations and you can also add more than 5 tabs to it and implement a "scroll" animation between the buttons. :)
I would suggest the BCTabBarController. I used it in one of my projects and it works great. You would still have to customize it, though.
It's not possible with the UIAppearance proxy
The way I'd recommend doing it is using container ViewController methodology in UIViewController (It's under the heading Implementing a Container View Controller). Apple's docs basically tell you how to roll your own.

Default view (as UIScrollView) of UIViewController - Can't set its content offset

According to my project, I changed the default view that tied to one UIViewController from UIView to UIScrollView as it has to be changed its offset and content size. The way I change from UIView to UIScrollView was by Interface Builder > Custom Class
If I want to change its offset and content size programmatically within The Controller, It can't be done in usual way unless I cast it
[((UIScrollView *)self.view) setContentSize:CGSizeMake(1024, 2000)];
[((UIScrollView *)self.view) setContentOffset:CGPointMake(0, 150)];
But with other UIScrollView within the app, changing their offset and content size can be done like any other,
// Assume that sv is scroll view object
[sv setContentSize:CGSizeMake(1027, 2000)];
[sv setContentOffset:CGPointMake(0, 150)];
When I print that scroll view object, it shown as a UIScrollView
NSLog(#"%#", self.view);
NSLog(#"%#", [self.view class]);
-> <UIScrollView: 0x6d3d3f0; frame = (0 0; 1024 768); autoresize = RM+BM; layer = <CALayer: 0x6d52ce0>; contentOffset: {0, 0}>
-> UIScrollView
Anyone know what I did missing or forgot to do rather than change the view's custom class?
Best and Thank you,
Tar
P.S. Besides the extra code needed, everything works fine. But, I can't take the chance of possible bug in the future. This client is super crazy, no error will be accepted
An alternative to this (that would avoid the need for casting) would be to set the UIViewController custom class back to UIView in interface builder. Then, insert a new UIScrollView as a subview (simply drag and drop in Interface Builder), connecting the UIScrollView to the UIViewController subclass via an IBOutlet that looks something like:
#property (nonatomic, weak) IBOutlet UIScrollView *scrollView;
(When you connect the outlet that property declaration should be generated for you by XCode).
Then, in your UIViewController subclass, you can do something like:
[[self scrollView] setContentSize:CGSizeMake(1024, 2000)];
[[self scrollView] setContentOffset:CGPointMake(0, 150)];
I'm not sure what the best solution is but a quick workaround is to create a method that casts the view in the UIViewController. That is:
- (UIScrollView *)scrollView {
return (UIScrollView *)self.view;
}
Then, instead of referring to the view in the ViewController as self.view, refer to it as self.scrollView.