I have a simple ViewController that looks like this:
#interface MyViewController : UIViewController<UIScrollViewDelegate> {
UIScrollView *scrollView;
UILabel *label;
}
...
#property stuff
...
Now, what I'm trying to do with this Controller is have a ScrollView handle a really large label of text that I have. So in the viewDidLoad method of MyViewController.m I have:
scrollView.contentSize = CGSizeMake(1000,1000);
scrollView.delegate = self;
scrollView.clipsToBounds = YES;
[self.view addSubview:scrollView];
And I get a blank screen that I cannot scroll around on. It's just a white screen. Before adding the label part, I thought I would try to set up the scroll view first, and this is not even working. Shouldn't I see some scroll bars when I move my fingers around? How do I set up the scroll view so that it contains a label?
Thanks!
The scrollView wont be scrollable until you actually place content inside it which exceeds its frame. So, add your label to the scrollview and it should become scrollable.
Related
I am transiting my project to iOS7. I am facing a strange problem related to the translucent navigation bar.
I have a view controller and it has a tableview as subview (let's call it ControllerA) . I init a new uinavigationcontroller with the controllerA and present it modally using presentviewcontroller. The presented view controller's table view is blocked by the navigation bar. I set the automaticallyAdjustsScrollViewInsets to YES but the result did not change.
I knew I can set the edgesForExtendedLayout to UIRectEdgeNone, but it will make the navigation bar no more translucent.
After that, I tried to create a new view controller for testing. It contains almost the same elements. But the result is much different. The table view content does not get blocked.
Conclusion
Two View Controllers' automaticallyAdjustsScrollViewInsets set to YES
The project is not using storyboard
The first one is created at Xcode 4.6, The second one is newly created on Xcode 5
I have compared two classes xib and code, not much different
I have found the answer on apple developer forum.
There are two different case.
The first one, the view controller added is a UITableViewController.
And the issue should not be appeared since apple will auto padding it.
The second one, the view controller is NOT a UITableViewController.
And in the view hierarchy, it contains a UITableView. In this case, if the UITableview(or ScrollView) is the viewController's mainview or the first subview of the mainview, it will work. Otherwise, the view controller doesn't know which scroll view to padding and it will happen the issue.
In my case, the view controller is the second one. And there is a background image view as the first subview of the main view. So, it fails.
Here is the Apple developer forum link (need developer account to access):
https://devforums.apple.com/message/900138#900138
If you want the view to underlap the navigation bar, but also want it positioned so the top of the scrollview's content is positioned below the navigation bar by default, you can add a top inset manually once the view is laid out. This is essentially what the view layout system does when the top-level view is a scroll view.
-(void)viewDidLayoutSubviews {
if ([self respondsToSelector:#selector(topLayoutGuide)]) {
UIEdgeInsets currentInsets = self.scrollView.contentInset;
self.scrollView.contentInset = (UIEdgeInsets){
.top = self.topLayoutGuide.length,
.bottom = currentInsets.bottom,
.left = currentInsets.left,
.right = currentInsets.right
};
}
}
Based on Tony's answer I was able to get around this problem programatically with temporarily sending the table view to the back, let the adjustments be made and then send the background view back to the back. In my case there is no flickering to this approach.
In the View Controller:
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
[self.view sendSubviewToBack:self.tableView];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[self.view sendSubviewToBack:self.backgroundView];
}
Obviously if there are other subviews on self.view you may need to re-order those too.
There's probably too many answers on this already, but I had to take Christopher's solution and modify it slightly to support view resizing and allowing the content inset to be changed in a subclass of the UIViewController.
#interface MyViewController ()
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
#property (assign, nonatomic) UIEdgeInsets scrollViewInitialContentInset;
#end
#implementation MyViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setScrollViewInitialContentInset:UIEdgeInsetsZero];
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
if (UIEdgeInsetsEqualToEdgeInsets([self scrollViewInitialContentInset], UIEdgeInsetsZero)) {
[self setScrollViewInitialContentInset:[self.scrollView contentInset]];
}
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
UIEdgeInsets scrollViewInset = [self scrollViewInitialContentInset];
if (UIEdgeInsetsEqualToEdgeInsets(scrollViewInset, UIEdgeInsetsZero) {
if ([self respondsToSelector:#selector(topLayoutGuide)]) {
scrollViewInset.top = [self.topLayoutGuide length];
}
if ([self respondsToSelector:#selector(bottomLayoutGuide)]) {
scrollViewInset.bottom = [self.bottomLayoutGuide length];
}
[self.scrollView setContentInset:scrollViewInset];
}
}
#end
To explain the point:
Any subclass of MyViewController can now modify the contentInset of scrollView in viewDidLoad and it will be respected. However, if the contentInset of scrollView is UIEdgeInsetsZero: it will be expanded to topLayoutGuide and bottomLayoutGuide.
#Christopher Pickslay solution in Swift 2:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let topInset = topLayoutGuide.length
inTableView.contentInset.top = topInset
inTableView.contentOffset.y = -topInset
inTableView.scrollIndicatorInsets.top = topInset
}
Yeah - a bit annoying.
I have a nib with a single tableview within the main view, not using autolayout. There is a tabbar, navigationbar and a statusbar and the app needs to work back to 5.0. In Interface builder that neat 'see it in iOS7 and iOS6.1 side-by-side' thing works, showing the tables neatly fitting (once the iOS6/7 deltas were set properly).
However running on a device or simulator there was a large gap at the top of the table, which was as a result of a content inset (which pretty much matched by iOS6/7 vertical delta) that was set to zero in the nib.
Only solution I got was in viewWillAppear to put in [_tableView setContentInset:UIEdgeInsetsZero].
Another ugly hack with a pretty on-screen result.....
[self.navigationController setNavigationBarHidden:YES animated:YES];
in:
- (void)viewDidLoad
I have an scrollview in my app.
If I click on a Button on one Page, a Subview is added. I want to remove this subview when the user scrolls the view. This function is called:
-(void) DisableViews {
[Annimation removeFromSuperview];
NSLog(#"scroll");
}
I get the NSLog many times, but the view also is Subview when i come back to the page.
I think this will happen, because the view with the subview is not the present view at this time, so i can't remove the subview.
Is there any possibility to remove a subview from any view on the subview?
edit:
ViewController.h
#interface ViewController : UIViewController {
//...
UIView *Annimation;
}
#property (nonatomic,retain) UIView *Annimation;
Implementation:
ViewController.m
#import "ViewController.h"
#import "AppDelegate.h"
#implementation ViewController
#synthesize Annimation;
//...
- (void) Bild1ButtonKlickt{
Annimation = [[UIView alloc]initWithFrame:CGRectMake(0.0, 0.0, 320.0, 480.0)];
Annimation.backgroundColor = [UIColor blackColor];
[self.view addSubview:Annimation];
}
Most likely "Annimation" (which I assume is an ivar) is nil at this point, and so nothing is happening when you try to remove it.
(As a note, don't access your ivars directly this way. Your property should be called animationView (to make it clear it's a view and not an NSAnimation, and you should access it via self.animationView. Also, methods should always have a leading lowercase. ObjC is very sensitive to method and property naming. Proper naming matters for the runtime; it's not just stylistic.)
As requested as answer: Is that the only subview in that scrollview? Anyway, one of the answers from how to remove subviews from scrollview? should work.
Now which answer from the above page did fix it?
I'm trying to set up a scrollView in an app using storyboarding. I have done everything correctly but the scrollview won't scroll in simulator or on iPhone.
MoreViewController.h
#property(nonatomic, retain) IBOutlet UIScrollView *moreScroll;
MoreViewController.m
-(void)viewDidLoad{
[moreScroll setScrollEnabled:YES];
[moreScroll setContentSize:CGSizeMake(1220, 354)];
}
I have connected the scrollView to the files owner, can someone help please
Thanks in Advance
With autolayout is there a new method - (void)viewDidLayoutSubviews
Here is a quick info:
Notifies the view controller that its view just laid out its subviews.
When a view’s bounds change, the view adjusts the position of its subviews. Your view controller can override this method to make changes after the view lays out its subviews. The default implementation of this method does nothing.
You should be fine if you add this:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubViews];
[moreScroll setContentSize:CGSizeMake(1220, 354)];
}
Setting an scroll view’s scroller style sets the style of both the horizontal and vertical scrollers. If the scroll view subsequently creates or is assigned a new horizontal or vertical scroller, they will be assigned the same scroller style that was assigned to the scroll view..
You should be if you add this lines in your code:
This line in .h file
#interface Shout_RouteView : UIViewController<UIScrollViewDelegate>
{
}
#property (retain, nonatomic) IBOutlet UIScrollView *scrollViewMain;
This lines copy in .m file
-(void)viewWillAppear:(BOOL)animated {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
scrollViewMain.frame = CGRectMake(0, 0, 768, 815);
[scrollViewMain setContentSize:CGSizeMake(768, 1040)];
}else {
scrollViewMain.frame = CGRectMake(0, 0, 320, 370);
[scrollViewMain setContentSize:CGSizeMake(320, 510)];
}
}
I suggest that you try to pust the content setting code into the viewWillAppear or viewDidAppear method. Its always best not attempt changing UI features before it is ready for display.
I build an UIViewController, that higher than iPhone screen ( the height is 900px ), i build it using UIScrollView.
In the Interface Builder, how to put an View in the bottom part of the UIScrollview ? i've tried using freeform in the inspector -> Simulated Metrics, but every time i move back to the ipad/iphone screensize, the views are mess. And when i ran it in the simulator, the view still a mess
I'd add a view programmatically and make it subview for the scrollview, i don't know how to do it using IB.
If you want to try programmatically can try something like:
UIView*myView=[[UIView alloc ] initWithFrame:CGRectMake(0, 480, 320, 200)];
[myView setBackgroundColor:[UIColor redColor]]; // Just for testing purpose
[scrollView addSubview:myView];
You have to do a bit of it programatically I'm afraid but you can do most of it in a xib.
Your xib would contain a UIView that's your normal view, containing your scrollview.
It would also contain another UIView; this will be as long as you want and will be your scrollview's contents.
In your .h file, have a property like this and attach it to the second UIView in your xib
#property (nonatomic, retain) IBOutlet UIView *scrollingContents;
and in your viewDidLoad, that's where you attach the contents inside the scroll view
- (void)viewDidLoad {
[super viewDidLoad];
[self.scrollView addSubview:scrollingContents];
self.scrollView.contentSize = scrollingContents.bounds.size;
}
I have a probably nub question but i just can't get around this.
I have a UIScrollview on the top of the screen, below it there is a UITableView.
both are on my InterfaceBuilder, not done programmatically
and declared on my .h as:
#interface RootViewController : UIViewController <UIScrollViewDelegate, IconDownloaderDelegate>
{
IBOutlet UIScrollView *scrollview;
}
etc.
Inside the UIScrollView i have a long tabbar also in IB mi code is as follows for this:
[scrollview setScrollEnabled:YES];
[scrollview setContentSize:CGSizeMake(1100, 29)];
Everithing works perfectly the tabbar works and moves etc.
the problem is that when implementing scrollViewWillBeginDragging
it only registers the scrolling on my UITableView and not on the scrollview.
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
NSLog(#"done");
}
What am i doing wrong??
Thanks in advance!
You have to set the delegate to the class where you implement the delegate methods.
scrollview.delegate = self;
add [scrollview SetDelegate:self]; in the place you add scrollview