How can I get the final height of the UICollectionView after loading data? - uiscrollview

I have a UIScrollView and a UICollectionView in it.
I want to know the final height of the UICollectionView after date loading finished so that I can update UIScrollView's height and it can scroll.
How can I do that?

You would have to use the UICollectionView's layoutIfNeeded method to correctly get the content size. This code might work fine:
[self.collectionView reloadData];
[self.collectionView layoutIfNeeded];
CGSize collectionViewSize = self.collectionView.contentSize;
CGFloat heightOfCollectionView = collectionViewSize.height;
CGFloat widthOfCollectionView = collectionViewSize.width;
Note: layoutIfNeeded synchronously calls to update all the subviews of the collectionView and doesn't return until the views are properly layouted.

Related

initWithCoder is returning 0 values for frame property

I have sub-classed uiscrollview and used initWithCoder to prepare my uiscrollview with all the subviews. I have used below code to set it up:
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
NSLog(#"%f", self.frame.size.height);
self.contentSize = CGSizeMake(5000, self.frame.size.height);
labelContainerView = [[UIView alloc] init];
labelContainerView.frame = CGRectMake(0, 0, self.contentSize.width, self.contentSize.height/2);
labelContainerView.backgroundColor = [UIColor yellowColor];
[self addSubview:labelContainerView];
}
But this keeps failing because the self.frame property always return 0 values. Its super important for me to use self.frame property because I want to use storyboard to do any height adjustments for the frame of the scrollview.
I have tried the same thing using xib files instead of using the storyboard and it works fine. But in my project I dont want to use xib files.
It'll be really great if anyone can explain me why I get 0 values in initWithCoder: method when I use storyboard? and if using storyboard how to achieve this?
PS: I notice layoutSubviews method return correct frame information but I cannot create my subviews here since it get called for each frame change (when I scroll)
Are you using Autolayout in your Storyboard?
If you are really not taking advantage of it, you can disable it and your -initWithCoder: method will return your frame again.
If you do need Autolayout, try the following:
-(void)awakeFromNib
{
[super awakeFromNib];
[self setNeedsLayout];
[self layoutIfNeeded];
// self.frame will now return something :)
}

Resize UICollectionView Height

I'm trying to resize a UICollectionView height by setting it to 0 when the view controller is loaded, then increasing its size with an animation when a button is pressed. I've tried a few different things but it doesn't change in size at all. Here's all the different things I've tried to change its height to 0:
CGRect bounds = [self.collectionView bounds];
[self.collectionView setBounds:CGRectMake(bounds.origin.x,
bounds.origin.y,
bounds.size.width,
bounds.size.height - 100)];
....
CGRect frame = [self.collectionView frame];
[self.collectionView setFrame:CGRectMake(frame.origin.x,
frame.origin.y,
frame.size.width,
frame.size.height - 100)];
....
CGRect frame = self.collectionView.frame;
frame.size.height -= 100;
self.collectionView.frame = frame;
....
self.collectionView.clipsToBounds = YES;
self.collectionView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
If you are using Interface Builder for UICollectionView initialisation, switch off "Use Autolayout" from the File Inspector in the xib file where the your CollectionView is created. Then you can change the height with setFrame or setBounds methods.
You can avoid disabling Autolayout by creating an outlet for the height constraint and then adjusting the constraint's constant in code.
Outlet
#IBOutlet weak var collectionViewVerticalConstraint: NSLayoutConstraint!
Adjustment
collectionViewVerticalConstraint.constant = 0

Disable Subview of UITableview from Scrolling

(xCode 4.3.2, ARC, Storyboard) I have a Master/Detail project and the MasterViewController is a UITableViewController, as usual. It has a navigation bar at the top and a toolbar at the bottom. I've created a custom subview that I load programmatically in viewDidLoad.
It loads fine, and is on top just like I want, but when the user scrolls the tableview, the subview scrolls too. I need the subview to "stick" to the bottom.
Here is the code I used to add the subview:
CGRect totalFrame = CGRectMake(0, 314, 320, 58);
UIView *totalBG = [[UIView alloc] initWithFrame:totalFrame];
totalBG.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"totalBG.png"]];
[self.view addSubview:totalBG];
CGRect totalLabelFrame = CGRectMake(12, 12, 80, 40);
totalLabelBG = [[UILabel alloc] initWithFrame:totalLabelFrame];
totalLabelBG.backgroundColor = [UIColor clearColor];
totalLabelBG.text = #"Total:";
[totalLabelBG setFont:[UIFont boldSystemFontOfSize:22]];
totalLabelBG.userInteractionEnabled = NO;
totalLabelBG.textColor = [UIColor whiteColor];
totalLabelBG.shadowColor = [UIColor blackColor];
totalLabelBG.shadowOffset = CGSizeMake(0, 1);
[totalBG addSubview:totalLabelBG];
I tried setting userInteractionEnabled to NO in viewDidLoad and detecting a
touch, and setting the totalLabelBG.center property, and neither worked.
I've also read through a lot of threads on disabling scrolling for webviews, but found nothing relevant.
I found another SOF question with a response that may or may not work, but the user did not explain the answer. "The trick is to adjust the frame of the "non-scrollable" subview inside -layoutSubviews."
I achieved the desired result by adding the subview to the UINavigationController container like this:
[self.navigationController.view addSubview:totalBG];
Like in the answer above. Just add that particular subview to any subview outside on the UIScrollView instance. If its not suppose to scroll then it doesn't make sense to put it inside the scroll view to begin with. Instead make the scroll view only take up the height up to the top of the totals subview

CGGradient isn't visible (not using interface builder) and UIButtons can't be triggered

I have created a view that contains a CGGradient:
// Bar ContextRef
CGRect bar = CGRectMake(0, screenHeight-staffAlignment, screenWidth, barWidth);
CGContextRef barContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(barContext);
CGContextClipToRect(barContext,bar);
// Bar GradientRef
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat components[16] = { 1.0,1.0,1.0,0.0, 0.0,0.0,0.0,1.0, 0.0,0.0,0.0,1.0, 1.0,1.0,1.0,0.0};
CGFloat locations[4] = {0.95,0.85,0.15,0.05};
size_t count = 4;
CGGradientRef gradientRef = CGGradientCreateWithColorComponents(colorSpace, components, locations, count);
// Draw Bar
CGPoint startPoint = {0.0,0.0};
CGPoint endPoint = {screenWidth,0.0};
CGContextDrawLinearGradient(barContext, gradientRef, startPoint, endPoint, 0);
CGContextRestoreGState(barContext);
This code is called in the drawRect method of the UIView. I then use a UIViewController to access the created view.
- (void)loadView {
MainPageView *mpView = [[MainPageView alloc] initWithFrame:[window bounds]];
[self setView:mpView];
[mpView release];
}
and displayed on the screen through the appDelegate:
mpViewController = [[MainPageViewController alloc] init];
[window addSubview:[mpViewController view]];
[window makeKeyAndVisible];
The UIView contains more objects, such as UIButtons, that are visible. I am assuming because they are added as a subview. But I can't work out how to add the CGGradient as a subview? Does it need to be? Is there another reason CGGradient is not visible?
I also don't get the functionality on the UIButtons. I guess that is because of where I have added the UIButtons to the view. Do the buttons need to be added in the UIViewController or the appDelegate to have functionality. Sorry to ask what would seem like simple questions but I am trying to accomplish the programming without the Interface Builder and material on that is scarce. If anyone could point me in the right direction on both these problems I would really appreciate it.
Thanks!
The functionality on the buttons was lost because the frame was too large but the buttons were still visible because the background was clearColor

cocoa -- getting nested NSViews and CALayers to resize proportionally

My NSWindow's contentView is an NSView subclass. It has some other NSView subclasses as subviews. The subviews are layer-based, and those layers in turn contain sublayers. Some of the sublayers have further sub-sublayers.
I want the whole thing to resize proportionally when the window is resized. What is the right way to set it up so that will happen?
Thanks
EDIT: I am not using Interface Builder at all.
Here's what I've done to get the contents of an NSView to scale proportionally as I resize the parent window. First, in interface builder, I added my NSView to the window, then added a reference to it in my AppDelegate. Mine happens to be called scrollView. I removed all of the auto-sizing behaviour from the scrollView.
Then, in my AppDelegate I added this:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// keep the aspect ratio constant so that the content looks good
[window setContentAspectRatio:NSMakeSize(2, 1)];
window.delegate = self;
}
- (void)windowDidResize:(NSNotification *)notification {
// size the scrollView to fill the window, but keep its bounds constant
NSRect rect = [[window contentView] frame];
NSRect oldBounds = [scrollView bounds];
[scrollView setFrame:rect];
[scrollView setBounds:oldBounds];
}
This turns the AppDelegate into the window delegate too. Fine since I've not got much logic in it. By keeping the bounds constant while changing the frame, the contents of scrollView will be scaled down smoothly.

Resources