UIScrollView does white space and doesn't scroll - ios

I have a scenario in mind, which I tried to implement but to no avail- Put a scrolling view with a text box, all of that within page controller.
Here's what I've done- UIPageViewController->ViewController with data ->UIView ->UIScrollView -> UITextView.
What it does? Well, other than scrolling a bit (not to show all of the text) and showing a weird white bar at the bottom, nothing.
Useful snippets of code- basically I linked my height constraint, and then in code:
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
//CGSize sizeThatShouldFitTheContent = [_textView sizeThatFits:_textView.frame.size];
self.theScrollView.frame = CGRectMake(self.theScrollView.frame.origin.x, self.theScrollView.frame.origin.y, 320, 2000);//[_theScrollView sizeThatFits:_theScrollView.frame.size];
_heightOfText.constant = 2000; //sizeThatShouldFitTheContent.height;
//_textView.frame = CGRectMake(_textView.frame.origin.x, _textView.frame.origin.y, sizeThatShouldFitTheContent.width, sizeThatShouldFitTheContent.height);
_textView.scrollEnabled = NO;
NSLog(NSStringFromCGRect(self.theScrollView.frame));
self.theScrollView.scrollEnabled = YES;
}
But nope.
Thanks in advance

This solved my issue- apparently I should call a selector...
-(void)viewDidLoad
{
// Change the size of page view controller
self.pageViewController.view.frame = CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height + 40);
[self performSelector:#selector(adjustScrollViewContentSize) withObject:nil afterDelay:0.1];
}
-(void)adjustScrollViewContentSize
{
_scrollView.contentSize = CGSizeMake(4000, 4000);
}

Related

UI Screen becomes black after UIAnimation

My problem is...
I have the object of parent view controller and i wanted to animate second view controller over that.
So i added a subview called backgroundview over the view of parentvc.view and then the view which needs to be drawn over the backgroundView.
But after animation completes for a second, i can see the views the way i want them to be but then it is replaced by a complete black screen.
I think my topmost view is redrawn so how do i rectify this issue.
Code :-
- (void)viewDidLoad {
[super viewDidLoad];
//_colorCaptureOptions = [NSArray arrayWithObjects: #"Camera", #"Color Slider / Color Wheel", nil];
mExtractionQueue = [[NSOperationQueue alloc] init];
[mExtractionQueue setMaxConcurrentOperationCount:1];
CGRect screenRect = [[UIScreen mainScreen] bounds];
//CGRect screenRect = self.view.frame;
self.backgroundView = [[UIView alloc] initWithFrame:screenRect];
self.backgroundView.backgroundColor = [UIColor clearColor];
[self.parentVC addChildViewController:self];
[self.parentVC.view addSubview:self.backgroundView];
//[self didMoveToParentViewController:self.parentVC];
UITapGestureRecognizer *guideTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleScrimSelected)];
[self.backgroundView addGestureRecognizer:guideTap];
[self.backgroundView addSubview:self.view];
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat viewHeight = 150;
self.backgroundView.alpha = 0.0;
self.view.alpha = 1;
self.view.frame = CGRectMake(0, screenRect.size.height, screenRect.size.width, viewHeight);
[UIView animateWithDuration:0.2
delay:0
options: UIViewAnimationOptionCurveEaseInOut
animations:^{
self.backgroundView.alpha = 1.0;
self.view.frame = CGRectMake(0, screenRect.size.height - viewHeight, screenRect.size.width, viewHeight);
}
completion:^(BOOL _finished) {
}];
}
}
Well, for clarity you'd better to provide few screenshots.
For all the rest:
Possibly, your background view is simply black that leads to black screen. Or it even is [UIColor clearColor]
better not use childViewController, it breaks MVC
better not change frame inside animation directly
If you want present another controller with animation, use this UIViewControllerTransitioningDelegate and this UIViewControllerAnimatedTransitioning in your objects, so do not reinvent transitions. Refer to this custom controller transition tutorial
Hope this may help you
EDIT:
[UIColor clearColor] removes colour entirely, so that means you will have no color at all.
The best solution for you now is rewrite those controllers, split up one from another, get rid of container for viewControllers, change animation to custom and than problem will disappear as a magic. If you solve you problem, do not forget to mark question as resolved, please

Cannot see added UIScrollView in UIViewController

I added a UIScrollView to my main UIViewController but for some reason i can't see anything. I painted the scroll view in grey in order to see the actual size, but all i get is a white screen.
Here is my very simple code:
-(void) viewDidLoad{
[super viewDidLoad];
UIScrollView *scroll;
[scroll setBackgroundColor:[UIColor grayColor]];
CGRect screenRect = [[UIScreen mainScreen] bounds];
_orientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsPortrait(_orientation)){
scroll.showsHorizontalScrollIndicator = YES;
}else{
scroll.showsVerticalScrollIndicator = YES;
}
scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(screenRect.origin.x,
screenRect.origin.y,
screenRect.size.width,
screenRect.size.height)];
[self.view addSubview:scroll];
}
The view size might change, i'm working on a changing iOS device size.

How to start an animation when a child view controller's view actually appears?

I am building a tutorial that uses custom subclasses of UIViewController to supply views for the tutorial. I would like to have a subview with instructions appear and then slowly fade out. I am trying to do it this way: a wrapper page controller class, custom UIViewController classes added as child view controllers, and an animation added to the custom UIViewController class's view.
Here is an example of how I add a child view controller to a tutorial page view:
else if(index==2)
{
FollowTutorViewController *next1 = [[FollowTutorViewController alloc] init];
next1.view.userInteractionEnabled = NO;
next1.typeDisplay = 1;
next1.index = index;
[page addChildViewController:next1];
next1.view.frame = page.view.frame;
[page.view addSubview:next1.view];
}
And here is an example of how I do the animation within the subclassed UIViewController:
- (void)messageTutorial
{
CGFloat height = [[UIScreen mainScreen] bounds].size.height;
CGFloat width = [[UIScreen mainScreen] bounds].size.width;
UILabel *directionsLabel = [[UILabel alloc] initWithFrame:CGRectMake(width/2, height/2, 100, 100)];
directionsLabel.backgroundColor = ORANGE_COLOR;
directionsLabel.textColor = BACKGROUND_COLOR;
directionsLabel.text = #"Follower pages show who you're following and who's following you\n\nYou can also see a list of most-controversial posters when you look for New People \n\nBuzz and Judge to gain followers";
directionsLabel.font = [UIFont systemFontOfSize:SMALL_FONT_SIZE];
[directionsLabel setLineBreakMode: UILineBreakModeWordWrap];
[directionsLabel setNumberOfLines:0];
CGSize constraint = CGSizeMake(width*.8 , 200000.0f);
CGSize size = [directionsLabel.text sizeWithFont:[UIFont systemFontOfSize:SMALL_FONT_SIZE] constrainedToSize:constraint];
directionsLabel.alpha = .8;
CGRect f = directionsLabel.frame;
f.size = size;
directionsLabel.frame = f;
directionsLabel.center = self.view.center;
[self.tableView addSubview:directionsLabel];
[UIView animateWithDuration:15 animations:^{
directionsLabel.alpha = 0;
} completion:^(BOOL finished) {
[directionsLabel removeFromSuperview];
}];
}
I would like to make the label disappear slowly starting when the user sees that view, but now when I run this code, regardless of where I call it, the view is gone by the time the user looks at the page. I have tried running this code in viewWillAppear, viewDidAppear, viewDidLayoutSubviews of the child custom UIViewController. Any other suggestions?

Place a label on the bottom of the screen

I made the following code to get a label on the bottom of the screen, depending if the device is a iphone5 or iphone4/4s.
I like to know I there is another way.... for instance with auto-layout?
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
CGRect frame;
if ([UIScreen mainScreen].bounds.size.height == 568) {
frame = CGRectMake(140, 500, 320, 100);
} else {
frame = CGRectMake(140, 410, 320, 100);
}
UILabel *iconAdLabel = [[UILabel alloc]init];
iconAdLabel.frame = frame;
iconAdLabel.font = [[UIFont preferredFontForTextStyle:UIFontTextStyleBody] fontWithSize:11.0];
iconAdLabel.text = #"SOME NICE TEXT HERE";
[self.view addSubview:iconAdLabel];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
UILabel *iconAdLabel = [[UILabel alloc]init];
iconAdLabel.frame = CGRectMake(0,self.view.frame.size.height-100,320,100);
iconAdLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
[self.view addSubview:iconAdLabel];
}
Yes indeed. You definitely DO NOT want to hard code in position values. Use interface builder to add constraints to the label. Apple's documentation on Auto-layout is quite good and can give you ideas as well.
Instead of hardcoding values or using constraints and interface builder, you could use a simple math expression like so:
CGFloat const labelHeight = 100;
CGRect frame = CGRectMake(0, CGRectGetHeight([[UIScreen mainScreen] bounds]) - labelHeight, 320, labelHeight);

How to dynamically position a UIDatePicker control for iPhone

I'm programatically adding a UIDatePicker control to a view. I want the DatePicker to appear docked to the bottom of the screen, in the standard way...
I'm setting the frame for the DatePicker and need to be aware of the different screen sizes for 3.5-inch iPhones and 4-inch iPhones.
The following code is producing the desired result, but I have a couple of questions...
// In ViewDidLoad
CGRect defaultFrame = CGRectMake(0,0,0,0);
_datePicker = [[UIDatePicker alloc] initWithFrame:defaultFrame];
CGRect bounds = [self.view bounds];
int datePickerHeight = _datePicker.bounds.size.height;
int navBarHeight = 44;
CGRect datePickerFrame = CGRectMake(0, bounds.size.height - (datePickerHeight + navBarHeight), 0, 0);
[_datePicker setFrame:datePickerFrame];
// In method responding to user tap
[self.view addSubview:_datePicker];
Q1. Is there a more elegant way to do this? Something other than, creating the DatePicker with a frame, checking its height, then setting its frame...
Q2. The view is a UITableView, sitting inside a UINavigationController. When I get the bounds of self.view, the size includes the whole view, including the 44 for the navbar. Yet, when I add the DatePicker with addSubview, if I don't include the offset for the navBar, it's off the bottom by 44...
Why does addSubview work within the smaller bounds when [self.view bounds] returns the full bounds?
Cheers,
Gavin
After looking into this some more, I've realised my original question was flawed. It wasn't clear where I was adding the UIDatePicker as a sub view. I've updated the question.
I now have two answers:
1) Position and add the UIDatePicker in ViewDidLoad. Use Autoresizing to deal with the view size change. Then make it visisible in response to the user tapping a control:
- (void)viewDidLoad
{
[super viewDidLoad];
_tableView = (UITableView*)self.view;
_tableView.backgroundColor = [UIColor colorWithRed:0.941 green:0.941 blue:0.913 alpha:1.000];
_tableView.backgroundView = nil;
_datePicker = [[UIDatePicker alloc] init];
CGRect bounds = [self.view bounds];
int datePickerHeight = _datePicker.frame.size.height;
_datePicker.frame = CGRectMake(0, bounds.size.height - (datePickerHeight), _datePicker.frame.size.width, _datePicker.frame.size.height);
_datePicker.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
_datePicker.isHidden = YES;
[self.view addSubview:_datePicker];
[_datePicker addTarget:self action:#selector(datePickerChanged:) forControlEvents:UIControlEventValueChanged];
}
2) Just set the frame for the UIDatePicker as required, not in ViewDidLoad:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
switch (indexPath.row) {
case RowDate:
{
CGRect bounds = [self.view bounds];
int datePickerHeight = _datePicker.frame.size.height;
_datePicker.frame = CGRectMake(0, bounds.size.height - (datePickerHeight), _datePicker.frame.size.width, _datePicker.frame.size.height);
[self.view addSubview:_datePicker];
break;
}
default:
break;
}
}
Thanks,
Gavin
The problem is that navigation bar pushes all the view downwards, after view did load initialized.
autoresizing mask may help.
For UIDatePicker, you don't need to specify its size. Because most of the time you will want it as wide as the screen and its height is fixed. But you need still to put it in the correct position. That is, you need to compute the correct position for it, set its frame.
Because most of the time you won't want your UIDatePicker to overlap your navBar. So Apple will let the addSubview work as if the bounds is "smaller".

Resources