I have a view controller with a UIScrollView embedded as a sub view. I embed it as follows:
CaptionViewController : UIViewController
Inside ViewDidLoad
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
scrollView.contentMode = (UIViewContentModeScaleAspectFit);
scrollView.contentSize = CGSizeMake(3200, 320);
scrollView.pagingEnabled = YES;
[self.view addSubview:scrollView];
Next I'm trying to wire up the scrollViewDidScroll event so I can execute some code each time the user swipes the scroll view. However, I can figure out how to access this event. I think the answer lies in delegation somehow. I tried importing UIScrollView.h and setting the scrollView delegate to the CaptionViewController as follows:
[scrollView setDelegate:self]
Still I cannot access scrollViewDidScroll. Can someone please point me in the right direction?
In addition to setting the delegate of the scroll view, you have to implement the delegate method in your CaptionViewController.m.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// handle scroll event
}
Also make sure your CaptionViewController conforms to the UIScrollViewDelegate protocol. In the .m file:
#interface CaptionViewController () <UIScrollViewDelegate>
#end
There is no need to import UIScrollView.h. You get this already.
Related
I have a chat that's setup as a UIViewController with a tableView added to it's view. This was working fine. I've since subclassed this viewController and added a childViewController as a header of the table:
- (void) createClassVideoView {
CGRect rect = CGRectMake(0.0f,
0.0f,
self.view.frame.size.width,
kWSClassVideoHeight);
WSClassVideoController *classVideoController = [[WSClassVideoController alloc] initWithFrame:rect mainUser:[[WSConversationManager shared] teacherObject] secondaryUsers:[[WSConversationManager shared] students]];
[self addChildViewController:classVideoController];
[self.view addSubview:classVideoController.view];
[classVideoController didMoveToParentViewController:self];
self.classVideoController = classVideoController;
}
It's not set as the actual tableHeaderView. It's just added as a childViewController to the subclass of the chat view controller, and I've just reset the frame of the tableView to accomodate it. This "header view" works fine and receives touches.
However, it's since disabled the superclass tableView's touches. The tableView displays, but I can't scroll it and tapping the UITextField does nothing.
I have a UITableViewController, that is embedded in a UITabBarController and also managed by a UINavigationController.
The only place that I have been able to customize the UITableViewController's table view frame is in viewDidAppear:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:YES];
[self customizeTableViewAppearance];
}
Here is the customizeTableViewAppearance method:
- (void)customizeTableViewAppearance
{
self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0);
if([UIScreen mainScreen].bounds.size.height == 568) {
[self.tableView setFrame:CGRectMake(0, 60, 320, 460)];
} else {
[self.tableView setFrame:CGRectMake(0, 60, 320, 370)];
}
}
This works perfectly when first using the app, but if you go to the device's home screen, and then resume using the app again, none of the usual view methods are called and the table view has been moved. So for whatever reason, even though view methods are not called, UITableViewController is changing the custom frame that I have set for it's UITableView.
Sure enough, if I move to a different tab, and then revisit the tab again, the view methods are called and the UITableView's frame is correct again.
How can I make it so that if the user leaves the app, and then resumes the app again later, that my frame will stay set and not be reset by the UITableViewController?
It's not really clear why you are manipulating the frame of your UITableViewController's tableView, but in most cases, you shouldn't.
From what you pasted, it seems like are trying to prevent the tableView or its content from appearing underneath your navbar, and your tabbar.
Instead of changing the tableView's frame, you should try one of the following things:
Try setting self.edgesForExtendedLayout = UIRectEdgeNone when initialising your UITableViewController
or:
Make sure self.automaticallyAdjustsScrollViewInsets = YES when initialising your UITableViewController
or, if for some reason you need to manage your tableView's contentInset manually:
Make sure self.automaticallyAdjustsScrollViewInsets = NO when initialising your UITableViewController. Now implement viewDidLayoutSubviews as follows
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
self.tableView.contentInset = UIEdgeInsetsMake(self.topLayoutGuide.length, 0, self.bottomLayoutGuide.length, 0);
}
Edit:
I just saw you're using a Storyboard. You can either set the edgesForExtendedLayout or automaticallyAdjustsScrollViewInsets from within your storyboard, or set them by implementing the -(void)awakeFromNib; method.
Without knowing why you are doing what you're doing, an easy solution to handle that case would be the following - Add this in your tableView's init method:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(customizeTableViewAppearance) name:UIApplicationDidBecomeActiveNotification object:nil];
That way, any time your application becomes active again your tableView will call that method.
The way to fix this was to override the viewDidLayoutSubviews method and place my customizeTableViewAppearance method inside of it:
- (void)viewDidLayoutSubviews
{
[self customizeTableViewAppearance];
}
The UITableView always has the correct frame now.
i've tried to create a custom view which works like a bottom bar and it worked
Right now this function is required on multiple classes, so i try writing it into a new class and import it which likes:
//BottomBarLauncher.h
#import <UIKit/UIKit.h>
#interface bottomBarLauncher : UIViewController
-(void)launchBottomBar;
#end
And implement it as :
//BottomBarLauncher.m
-(void) launchBottomBar{
for (UIView *subView in [topView subviews]) {
[subView removeFromSuperview];
}
UIView *btnBarView = [[UIView alloc]initWithFrame:CGRectMake(0, self.view.frame.size.height - 53.3, 320, 53.3)];
btnBarView.backgroundColor = [UIColor redColor];
[self.view addSubview:btnBarView];
}
Now here's the problem, while i try implement it on a new view like follows:
//NewView.m
#import "BottomBarProtocol.h"
#interface NewView()
{
BottomBarLauncher *btnBar;
}
#end
//blahblahblah
[btnBar launchBottomBar];
and nothing happens, i think the problem was with
[self.view addSubview:btnBarView];
but i have no idea how to select the current view as target which i can add subview onto.
First a suggestion, looking at your requirements/code I think you want to create custom view. For creating a custom view, create a class which inherits from UIView rather than creating a UIViewController.
Now moving to the code, your btnBar is a UIViewController which has its own view self.view so when you call this [btnBar launchBottomBar] internally you are adding the bottom bar on self.view that is your btnBar controllers view and not on NewView controllers view. Hope you understand what I am pointing out.
Here you are missing out few calls,
btnBar.view.frame = CGRectMake(0,self.view.bounds.size.height-40,self.view.bounds.size.width,40); // Add suitable frame.
//This call will add the btnBar's view as subview onto your current view controller's view.
[self.view addSubView:btnBar.view];
This is not correct/recommended way and you can face serious challenges regarding memory leaks. To avoid those mistakes, as I suggested, create a custom UIView instead. Take a look around on how to create custom views.
Hope that helps!
You can return the UIView form launchBottomBar method and add as a subView in your current ViewController class
Make custom class and delegate and add that view in window and set its frame so that it is not visible and set its frame and slide from bottom when needed so you can use it in all view controller.
Thanks.
I have a UIScrollView, created programmatically, inside of a UIView. What do I need to do to ensure that I can use the delegate method scrollViewDidEndDecelerating?
Here's what I have set up, please assume that within the UIScrollView, that there are three UIImageViews. When the page first loads, I am looking at the center UIImageView and I can scroll once backwards or once forwards. The reason why I need this delegate method is because I intend to use it to calculate which UIImageView I am currently looking at.
ViewController.h
#interface ViewController : UIViewController <UIScrollViewDelegate>
ViewController.m
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
scrollView.pagingEnabled = YES;
[self.view addSubview: scrollView];
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
NSLog(#"scrollViewDidEndDecelerating");
}
Add
scrollView.delegate = self
after the scroll view initialization.
In your delegate method, you can test each uiimageview center to see Which one match the uiview center, That's the uiimageview you are looking at.
My app is building purely programmatically on UITabBarController above a UINavigationController, which are both declared in my AppDelegate. Inside my navigationcontroller, I'm showing a UIViewController, a custom class. This custom class should show a custom UIView in a UIScrollView and a UIPageControl.
Heres my problem:
self.view seems to create an EXC_BAD_ACCESS error when I call it without declaring self.view = [[UIView alloc] init] (or similar). I was wondering if this was a problem with -(void) loadView but seems like it produces the same error in -(void)viewDidLoad. So I basically had to use self.view = scrollView to even show my scrollView, considering [self.view addSubview:scrollView] produced an error. My UIPageControl should stay on the page all the time, and actually be another part of the view than the UIScrollView. So I tried to add a container-view like this
Code:
container = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0,0,0,0)];
scrollView.pagingEnabled = YES;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.showsHorizontalScrollIndicator = NO;
// EDIT: ofcourse, I'm also resizing the frame with [scrollView setContentSize:] later, but this is farfetched code to add here.
[container addSubview:scrollView];
self.view = container;
Unfortunately, it seems that I don't get any result at all, and what appears is just an empty view. However, if I add a UILabel or similar, it shows:
[container addSubview:[[UILabel alloc] initWithFrame:CGRectMake(50,50,50,50)]]; // entered above or beneath the addSubview:scrollView line.
My question is: Why doesn't my scrollView appear in the UIView container?
I've noticed that some tutorials say that scrollView must have a delegate, and I agree with the logic - however I can't seem to find out how I set that delegate when I am in my CustomUIViewController-class instead of my AppDelegate.
after you change the UIScrollView size you should use:
[scrollView setNeedsDisplay:YES];
also you implement Delegates the same way you do in other classes:
.h:
#interface MyClass : NSObject <UIScrollViewDelegate>
Okay, the problem seemed to be the initialization - I didn't realize that frame and content was two different things. Seems like the frame that is initializing the view should be whatever size the view should fill, while content is the actual content of whatever should be scrolled. So when I was having problems with user interaction, it was really this.
The problem of why it didn't show in the first place was (stupid.) that the frame was initially, and never changed from, 0,0 so I really lied in my first post.
Thanks to UIScrollView and PageControl: space between views who solved my problem with user interaction.
My steps was to backtrace from self.view:
NSLog(#"%f\n%f",
((UIScrollView*) [[self.view subviews] objectAtIndex:0]).frame.size.width,
((UIScrollView*) [[self.view subviews] objectAtIndex:0]).frame.size.height);
when I realized these were 0 and 0, fixing the problem wasn't too hard :) thanks though, for your efforts Kristian.