Which view controller should I be using? - ios

I am trying to implement a mockup like this. However, I'm not sure which view controller I should be using for something like this? I tried UICollectionViewController but that puts cells of fixed width on each row. As you can see in my mockup, at some places I have a label taking all width and in other places I have three labels taking up the width.

You can use the simple UIViewController and drag the labels manually in the Storyboard. In order to make the rectangular label to round edged labels, you can create a IBOutletCollection of all those labels and iterate through the array, get each label's layer and set the corner radius to appropriate value.
e.g:
#property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *customLabels;
As customLabels is an NSArray so it doesn't have a layer property. You can do it like this:
for (UILabel *label in customLabels) {
label.layer.cornerRadius = 5.0;
}

I'd stick with a plain UIViewController based controller.
The collection view is more for dynamic content like a bunch of photos. To do this with a collection view would take a bunch of unnecessary work.
With this layout, just lay the objects out manually on the storyboard and then you can just use the regular constraints if you need to resize dynamically and that will do just fine.

You can just use a UIViewController and set the buttons up appropriately in Interface Builder or programmatically.
If you take the latter approach, you can do something like this in your view controller
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
// be sure to do this step or you won't see your button
button.frame = CGRectMake(...);
// Customize your button here
[self.view addSubview:button
See this documentation for information on CGRectMake if you aren't familiar
Edit: I'm not sure if this approach will handle orientation changes appropriately. I suspect it would if you calculate the frame instead of hardcoding values. I don't have the ability to test that right now unfortunately.
Edit again: I didn't realize this was tagged for RubyMotion. I'm not familiar with that api so my code example may not be relevant.

Related

Using interface builder to layout a scrolling view with images and text

I have a requirement in my app to display a bunch of information that includes both text and images. It will be quite long, so it will need to be scrollable to access all the content.
I know that I can achive this by programmatically adding different UILabels, UIImages etc to a UIScrollView. But this is a proof of concept, so I'm looking for something a little quicker than having to work out all the positioning and code required. The information is static anyway, and does not need to interact with code.
Is there a way to do this using the interface builder (storyboard or xib is fine)?
you definitely can do that if you simply want a quick interface
1.> you might need to know how long is your scroll view, for example in my case, i set it to 1568
2.> Then i drag all the controls that will fit for the first 568 pixel view onto the scroll view and position them.
3.> Then change the Y value for that scroll view to something like - 500, so you can see the rest of the scroll view, and put everything you need there.
4.> After you have all your controls, and remember to set the frame back to 0,0,320,568
5.> last step, in your code, set SCROLLVIEW.contentSize = CGSizeMake(320, 1568);
I would still suggestion don't hard code all those values, but if you are looking for a quick way to do your interface, hope that gives you some ideas.
Just start a new project with a single view, it will come with a xib or storyboard for its single ViewController.
Create a UIView by dragging it into the workspace and place as many Labels, Images and UI Elements as you want.
Open the xib / storyboard and drag a UIScrollView in as your root VC's root view. Drag the view containing your layout into the scrollview, making it the scrollviews only subview.
Done (almost)!
If you launch your app at this point, you'll notice you can't scroll. That is because the scrollview is "too stupid" to adjust the size of its contentSize property on its own.
You'll need some code here, but it is only a tiny snippet and you won't need to touch it again:
Create a new Category on UIScrollView.
In your category's implementation, do:
#implementation UIScrollView (MyHandyCategory)
-(void)awakeFromNib {
NSArray *subViews = [self subviews];
UIView *contentView = [subViews objectAtIndex:0];
[self setContentSize:contentView.frame.size];
}
#end
Done (for real this time)! This will check the size of the view your scrollview contains and ajust the contentSize after it has been initialized. You can change the size of your content view as you like, no need to play around with hardcoded values or even Interface Builder values!
If it’s just proof of concept I’d have a WebView and a local HTML page you load. Easy-peasy.
I would suggest UICollectionView. It's fairly straightforward. There's a good tutorial here:
http://www.raywenderlich.com/22324/beginning-uicollectionview-in-ios-6-part-12

Can't Wire to Subview in IB

Quick question. Using IB, I have a subview in a ViewController. In that subview I have a label, which I would like to wire to my custom subview class. However, IB will not let me. What am I missing?
I also tried to add the label programmatically; however, it appears that the frame was not ever set. I could hard code the size of the label, but I could not make it dependent on the frame size of my subview, because the frame and the bounds were always zero rects, even after the view showed up in my view controller at a non zero size. Any ideas here would also be much appreciated.
You are actually completely right. It wont let you connect from IB to the Header of a custom view in Xcode 4.6.2
Personally I would file a Radar but I would want to do a bit more research to prove it and as this is a pattern I wouldn't ever use then I won't.
Fortunately you can get around it
Make sure your custom view is configured correctly in IB
and assuming you are setup something like this
Then you can manually declare in your header
#interface MyCustomView : UIView
#property (weak) IBOutlet UILabel *label;
#end
And drag FROM the dot that appears beside the property TO the label.
Or drag FROM the right-click HUD of the custom view TO the label.
Neither case will work by dragging from the label to the view.
In your header file, you need to define the label as an IBOutlet, then you can drag from your file's owner to the label.
IBOutlet * lblSomeLabel;
Disable AutoLayOut and try again.

Changing size of UIButton while using Autolayout?

I'm pretty new to ios. I'm working on a project which is going to frequently use a certain UIView class throughout the application. This class is simply an image that does some transparency stuff with the background color. This works fine so far. This class sometimes exists as a lone UIView, and sometimes as a button subview.
When I add this UIView to a UIButton as a subview, the full contents of the UIView are displayed at full size, but the clickable area of the button remains the size defined in the xib unless Use Autolayout is turned off (even if I manually try to set the button's frame.)
I would like to put a UIButton on the xib as a placeholder, and then later define its size/clickable area based on the size of the overlay image which the UIView that was initialized with.
Should this be possible, or am I misinterpreting the usage of xib files/autolayout?
under ViewDidLoad I have...
- (void)viewDidLoad{
[theButton addSubview:_theView];
CGRect buttonFrame = theButton.frame;
buttonFrame.size = CGSizeMake(_theView.getSize.width,_theView.getSize.height);
[theButton setFrame:buttonFrame];
}
However, the frame stays the same size when I print the button info before and after I try calling setFrame.
(note that '_theView.getSize' was added by me)
Under Autolayout, views don't have frames at viewDidLoad. Try your code in viewWillAppear: or viewDidLayoutSubviews.
Under Autolayout, you don't set frames. You edit constraints instead. Setting a frame will work until the next layout pass, when your layout will revert to that described by your constraints.
To size a button to fit a subview, you can try something like this (in visual format language): |-[theView]-| but it would depend what constraints are in place from your xib.

UIScrollView - Moving view to front, but below scroll indicators

I am working with a custom view which inherits from UIScrollView. The problem I am having is adding a UILabel that should be displayed at the 'top', in front of the other views. It works, but unfortunately it also covers up the scroll indicators.
As you can see, the scroll indicator is being obscured. I don't want to disable scroll indicators.
I am adding the views directly to the UIScrollView:
UILabel *subsection = [[UILabel alloc] initWithFrame:CGRectMake(0, y * h,
[self totalContentWidth], [tableViewDelegate rowHeight])];
[subsection setText:subsectionName];
[subsection setTextAlignment:NSTextAlignmentCenter];
[subSectionRows setValue:subsection forKey:key];
[self addSubview:subsection];
and then bringing them to the front, which
- (void) bringSubsectionsToFront {
for (UIView* row in [self.subSectionRows allValues]) {
[self bringSubviewToFront:row];
}
}
This behavior is confusing to me. If I peek at UIView.layer.zPosition of all the UIScrollView's subviews, they are all the same.
If I adjust the bringSubsectionsToFront method to instead move the labels in front of the view that contains the grid lines, the behavior is the same.
Looking at some internal view classes whose behavior works, it looks as if they are being added to the scroll view with: [self insertSubview:cell atIndex:0];
What am I missing here?
Solution:
verec remarked that I could find the bars if I really wanted to. So I iterated over the subview list at a suitable point, and sure enough, there they were. The order of the objects was as follows:
CustomCell
...
UIImageView
UIImageView
CustomBorderView
UILabel
UILabel
Assuming this is the z ordering, no wonder my labels were always on top.
Solution becomes simple; add UILabel's after CustomCells. This solution only works because the custom table adds CustomCells at index 0, which I believe makes scroll indicators appear after the CustomCells. If this assumption holds, I can reorder the other views relative to the CustomCells, achieving the layering effect I want.
The simplest is to use and intermediate UIView, call it 'contentView' whose children are the views you want to bringToFront.
If that contentView is what is inside the scrollView, it will stay 'below' the scroll indicators whichever contentView child you bring to the front.
The alternative would be to scan into the scrollView looking for the scroll indicators (you will find them!) but that's a compatibility risk, as you never know if/when Apple may decide to remove/reshape/reposition them according to some new (flatter ...) design paradigm ...

How to make UILabel a child of another UILabel in Interface Builder?

I need to make a half of a sentence red and the other half blue, so I placed two different UILabels in Interface Builder and changed their colors accordingly using the GUI. On the Objective-C side, sometimes I need to hide and reveal the sentence.
self.redHalf.hidden = YES;
self.blueHalf.hidden = YES;
self.redHalf.hidden = NO;
self.blueHalf.hidden = NO;
This is not modular code. I'd rather just make one call to hide or reveal the whole sentence. So I tried to make one half the child of the other half by dragging one atop the other in Interface Builder, but nothing happened.
You cannot make subviews in a UILabel in IB. (You can do it in code though.)
Just drag out a generic UIView in IB and make both UILabels subviews of the generic UIView. Then set the generic UIView's hidden property to hide or show both labels.

Resources