How to create a UITableCell that has multiple subtitles - ios

I came across this design image online and I am really puzzled on how could I make a UITableCell that has multiple subtitles and allows me to customised them in the way shown by the picture.
My understanding is that one can only use 1 subtitle per cell.
Is there a way to create a UITable cell that looks like that? How would you go on to make those 4 subtitles under the cell title???

You could do that easily by having a custom layout for the UITableViewCell. This video should help you in doing this:
http://www.youtube.com/watch?v=d_kO-J3DYvc
Basically you will need to design the UI of the cell in storyboard/NIB file and add multiple labels to your table cell there. Sub-class UITableViewCell and link it to the designed UITableViewCell in storyboard/NIB. Addd IBOulets in that class for the labels and link your labels from the UI to these IBOutlets.

From the image provided, it looks like the prototype UITableViewCell contains one UIImageView and 5 UILabels. Assuming you are using IB or storyboard to create the table view cell, set the 'Table View Style' to Custom, than drag a UIImageView and 5 UILabels onto the prototype cell. For each of the UILabels, adjust their position, font and font size as desired. You may also need to adjust the height of the cell.

Hey I have created a Sample Project regarding Custom Cell check this github link that I have created. I have used storyboard.
here is the screenshot of the sample app

Just subclass UITableViewCell, and add in multiple UILabel's. Then override the layoutSubviews method to position those labels. Then in the cellForRow, make sure you instantiate your subclassed UITableViewCell. I don't have time to check this, but the subclass would look something like:
#interface CustomCell : UITableViewCell {
UILabel *myCustomLabel1;
}
#end
#implementation CustomCell
- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) {
// Initialization code
myCustomLabel1 = [[UILabel alloc] initWithFrame:CGRectZero];
[self.contentView addSubview:myCustomLabel1];
}
return self;
}
-(void)layoutSubviews
{
[super layoutSubviews];
float margin = 5;
[myCustomLabel1 setFrame:CGRectMake(self.bounds.origin.x+margin, self.bounds.origin.y, self.bounds.size.width - (2*margin), self.bounds.size.height)];
}
#end

Related

Image on cells not all the way to the left

I am learning about UITableview on iOS and following a course online. I get the table showing fine, but the images on my cells are not all the way to the left (whereas the instructor's ones are). Here is a screenshot of the cells in question:
I don't want that gap, I want the images to be positioned right at the beggining of the cell, all the way to the left. I have done some research and it seems Apple has changed the default look of the cells between ios6 and ios7 so that now the images in cells show a little gap at the left. To get rid of it, I have tried UIEdgeInsets:
[tableView setSeparatorInset:UIEdgeInsetsZero];
and that's not working. I also have tried this approach:
cell.imageView.frame = CGRectMake( 0, 0, 50, 55 );
Nothing happens. So how would I go about it? Thanks
edit-------------------------------------------------------------------------------------------------------------------------------
Still not have found the answer to this. The solutions posted here don't work. I found this piece of code:
self.tableView.contentInset = UIEdgeInsetsMake(0, -50, 0, 0);
Which besides completely puzzling me (as the parameter affected should be the y?) I thought solved the issue by making the image on the cell appear all the way to the left, until I realised it only moved the whole view to the left (as I should have expected I guess) leaving an equal gap on the other side of the screen. All I want is for my images in the cells to appear all the way to the left of the cell as it used to be the case on previous ios. Thanks
It happens because default table content offset from left is 15, you should change it with 0.
See this once, you get idea Remove empty space before cells in UITableView
If you create custom cells. UITableViewCell have owner imageView. Change title of image in your cell.
If you use default cell, use custom cell with constraint Leading space = 0.
It is better not use default imageView of the cell. Drag and drop UIImageView from objective library, create a custom table view cell (Child class of UITableViewCell) then create and outlet of the image view just dragged.
The spacing in the UITableViewCell is because of the default TRUE returned by shouldIndentWhileEditingRowAtIndexPath method of UITableViewDelegate.
I was able to reproduce your problem by the below scenario:
UITableView is in editable mode:
self.tableView.editing = true
And you have implemented:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView
editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleNone;
}
To correct your code:
If you do not want to set Editing Style then you can turn off the editing mode by
self.tableView.editing = false
and remove editingStyleForRowAtIndexPath.
Else if you need editing mode then set the appropiate Editing style(UITableViewCellEditingStyleDeleteor UITableViewCellEditingStyleInsert) or simply turn the indentation off.
- (BOOL)tableView:(UITableView *)tableView
shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return FALSE;
}
You must create a custom cell, by adding a new class as a subclass of UITableViewCell. then you can design cell with autolayout and constraints which will resolve the issue.
there is a another concrete way to achieve this by creating subclass uitableviewcell (custom class).
steps to follow
create a class subclass of UITableViewCell.
in .h file create properties and outlets of UI components.
go to storyboard and add table view cell inside the tableview.
now add UI components like: imageview or button etc and set the x, y values according to.
make class of custom cell your className using identity inspector see image.
connect all outlets of UI components.
use below code uitableview
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *MyIdentifier = #"uniqueIdentifire";
yourCustomClassForCell *cell = (yourCustomClassForCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil){
cell = [[yourCustomClassForCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier];
}
cell.imageView.image = [imageAry objectAtIndex:indexPath.row];
}
Dont forget to give identifire by selecting your cell using storyboard Attribute inspector uniqueIdentifire to identifire property see image.
Also you can give some vertical space between cells by just to add this below code (Method only) inside customeCellClass.
- (void)setFrame:(CGRect)frame { // method to insert gap between table view cell
frame.origin.y += 6;
frame.size.height -= 2 * 6;
[super setFrame:frame];
}
You can not really change the frame of the inbuilt subviews of uitableviewcell like imageview, accessoryview. But if you create a custom tableviewcell class(even if you do not add any other subelement to it), you can change the frame of the inbuilt imageview by overriding the layoutSubviews method inside the UITableViewCell. I have tried it and it works.
#import "TableViewCell.h"
#implementation TableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(void) layoutSubviews{
[super layoutSubviews];
CGRect frame = self.imageView.frame;
frame.origin.x = 0;
self.imageView.frame = frame;
}
#end

Adjusting the size of the UIImageView in a Right Detail style UITableViewCell

I have a simple application which contains a few UITableViewControllers in a UITabBarController. The last UITableViewController is called the More tab and it's a static UITableView. I have designed everything in Storyboard.
Within the More UITableView, I have 4 sections. Within section One, Two and Three, I have 2 basic UITableViewCells. That works well. Within section four, I have 11 basic UITableViewCells. I'm populating the cell titles within Storyboard. I have decided to slightly modify the UI so that section 4 contains a small image and the label.
To do this, I have used Right Detail as the style of the UITableViewCell because it allows you in the inspector, to specify an image.
The problem at the moment is that the image looks just too big.
I have the image in the view, but the size inspector is greyed out.
Without using a custom UITableViewCell (because everything works in this way; just the image is too big), how can I specify the size of the UIImageView? And where do I specify that?
You can create a UITableViewCell subclass and set it to your static cell within storyboard, e.g.
#interface MyCell : UITableViewCell
#end
#implementation MyCell
-(void)layoutSubviews
{
[super layoutSubviews];
//TODO: adjust self.imageView
//self.imageView.contentMode = ...
//self.imageView.frame = ...
}
#end
Or, you can click on that imageView and change it's Mode to Center from the inspector and set an image with right sizes that you want to display.

UISwitch not displaying in custom UITableView Cell

I need a custom cell with a label and a switch.
Now, the main problem is that I can't get the switch to display. I have tried several methods, including adding the switch programatically to the cell's accessoryView.
I used the IB, added the switch to the cell, connected the IBOutlet. I also tried to add the switch programatically, in cell's awakeFromNib:
- (void)awakeFromNib {
[super awakeFromNib];
if (!self.fieldSwitch) {
self.fieldSwitch = [[UISwitch alloc] init];
[self.fieldSwitch addTarget:self action:#selector(switchUpdatedValue:) forControlEvents:UIControlEventValueChanged];
self.fieldSwitch.onTintColor = [ColorManager sharedInstance].genericSwitchColor;
self.accessoryView = self.fieldSwitch;
}
}
This has had absolutely no effect; I also tried adding it as a subview to the cell's contentView then calling bringSubviewToFront:. Again, no success.
I checked, and self, accessoryView, fieldSwitch none of them were nil.
Does anyone have any idea what could be so wrong? on a side note, does anyone understand why adding a control from the IB is broken by default?
If you are using size classes you have to set a constraint for the UISwitch. For example if you are using an Any Any size class and you place the UISwitch in the cell it may actually be displaying far off to the right. (I would of posted this as a comment however not enough rep)

UICollectionView custom layout with two cells

I've been reading online tutorials on UICollectionView with different layouts. Also looked at a lot of SO Questions on the subject. But it seems what I am looking might be something more simple but I am stuck on how to go forward.
The Goal
I have a UIViewController that is embedded in a UINavigation controller. I am displaying data in a UITableView which includes:1 UIImageView and three UILabels in each cell. The data is fetched from a server and all works nicely.
I then wanted to have a UIButton that, when tapped, would kick off a cool animation that shows the cells transition into a nice grid view.
It suddenly dawned on me that I needed to use a UICollectionView to change between these two cells and ditch the UITableView completely. Tapping the button again, would switch back to the last state (Grid or UITableView style)
The grid cell needs to loose one label - but keep the image.
The problem
I have spent the last two days reading up on UICollectionView and UICollectionViewFlowLayout. I think I could use a Apple's pre-made UICollectionViewFlowLayout and just tweak it a little.
I don't know if I need two custom cells or one cell that changes shape between the two views and how the animations must work.
I'm not looking for the exact code to do this - I just need to know which direction I need to go in and if I need to use two custom cells - and how do I change between the two with animation and not reloading all the data again.
Appreciate any input.
Thanks all.
I finally found a solution that was acceptable to my need. If anyone ever has similar needs - this is how you use two different custom UICollectionViewCell's and how to change between the two different cells / layouts.
First thing is create the customCells in IB - creating the xib
files.
Then set the up as you need
Since my requirement needed the standard flow layout provided by the class UICollectionViewFlowLayout - I just needed to create two custom layouts and tweak them to my needs.
Create two (or more if needed) classes that subclass UICollectionViewFlowLayout
In the implementation - setup the layout as needed. Since I am subclassing the pre-made UICollectionViewFlowLayOut and all I need to do is tweak it - the implementation is pretty simple.
So - for the table view layout I did this:
tableViewFlowLayOut.m
-(id)init
{
self = [super init];
if (self){
self.itemSize = CGSizeMake(320, 80);
self.minimumLineSpacing = 0.1f;
}
return self;
}
This sets each cells width and height to the values I needed. self.minimumLineSpacing sets the spacing between the cells. (Spacing between the cell above / below )
Then for the grid layout:
gridFlowLayOut.m
-(id)init
{
self = [super init];
if (self){
self.itemSize = CGSizeMake(159, 200);
self.minimumInteritemSpacing = 0.1f;
self.minimumLineSpacing = 0.1f;
}
return self;
}
Same as before - however, this time I needed spacing between my cells right edge -
self.minimumInteritemSpacing = 0.1f'
takes care of that.
Right - now to put it all together - in the viewController that has the UICollectionView
viewController.m
// Import the new layouts needed.
#import "GridFlowLayOut.h"
#import "TableViewFlowLayOut.m"
//Create the properties
#property (strong, nonatomic) TableViewFlowLayOut *tableViewLayout;
#property (strong, nonatomic) GridFlowLayOut *grideLayout;
-(void)viewDidLow
{
//Register the two custom collection view cells you created earlier. Make sure you set the correct reuse identifier here.
[self.tradeFeedCollectionView registerNib:[UINib nibWithNibName:#"TableViewCell" bundle:nil] forCellWithReuseIdentifier:#"TableItemCell"];
[self.tradeFeedCollectionView registerNib:[UINib nibWithNibName:#"GridViewCell" bundle:nil] forCellWithReuseIdentifier:#"GridItemCell"];
}
-(void)viewWillAppear
{
//Create the layout objects
self.grideLayout = [[GridFlowLayOut alloc]init];
self.tableViewLayout = [[TableViewFlowLayOut alloc]init];
//Set the first layout to what it should be
[self.tradeFeedCollectionView setCollectionViewLayout:self.tableViewLayout];
}
Right - now to change between the layouts with some animation. This is actually very easy to do and only needs a few lines of code -
I called this code in a button method in viewController.m
-(void)changeViewLayoutButtonPressed
{
//BOOl value to switch between layouts
self.changeLayout = !self.changeLayout;
if (self.changeLayout){
[self.tradeFeedCollectionView setCollectionViewLayout:self.grideLayout animated:YES];
}
else {
[self.tradeFeedCollectionView setCollectionViewLayout:self.tableViewLayout animated:YES];
}
}
And lastly in cellForItemAtIndexPath
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{ static NSString *tableCellIdentifier = #"TableItemCell";
static NSString *gridCellIdentifier = #"GridItemCell";
//BOOL used to detect which layout is active
if (self.gridLayoutActive == NO){
CustomCollectionCellClass *tableItemCell = [collectionView dequeueReusableCellWithReuseIdentifier:tableCellIdentifier forIndexPath:indexPath];
//Setup the cell
}
return tableItemCell;
}else
{
CustomCollectionCellClass *gridItemCell= [collectionView dequeueReusableCellWithReuseIdentifier:gridCellIdentifier forIndexPath:indexPath];
//Setup the cell
}
return gridItemCell;
}
return nil;
}
Of course you will need to conform to the other UICollectionView delegates and setup the remaining stuff.
This actually took me a while to figure out. I really hope it helps others out there.
If anyone wants a demo project - I'll happily create one and upload to GitHub.
For anyone new to UICollectionViews I highly recommend reading Apple's programming guide on the subject - it was this document which lead me to this solution.
Reference:
https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/Introduction/Introduction.html

How do I define a ViewDidLoad method for a UILabel that's contained in a nib file?

I have a nib with a table cell, and within that table cell I have a UILabel. I want to make that label sizeToFit which means I have to do:
- (void)viewDidLoad {
[self sizeToFit];
}
However my label doesn't have any code, just an outlet to a variable in my controller, so there's nowhere I can put that code to effect the label.
I attempted making a sub class of UILabel (fitUILabel : UILabel) and then I clicked on the label in the nib and set its class to fitUILabel, however it does not seem to run.
In my controller right before the return statement in cellForRowAtIndexPath I tried putting
[cell.myLabelOutletVariable sizeToFit]
And this seems to work, however it only works on the recycled rows and not the labels contained in the initial cells of my table. This also seems to cause my text to flow right out of the cells and overlap onto others, however it does align it to the top which is what I wanted.
I assume you mean that your nib contains a UITableViewCell as a top-level object, and the table view cell has a UILabel subview.
The viewDidLoad method is defined on UIViewController, and UITableViewCell doesn't inherit from UIViewController.
UITableViewCell is a subclass of UIView. The proper place for a view to adjust the frames of its subviews is in its layoutSubviews method. You need to make a subclass of UITableViewCell, and set that as the custom class of the cell in your nib. Then, in your subclass, define this method:
- (void)layoutSubviews {
[self.label sizeToFit];
}
In your table view data source's tableView:cellForRowAtIndexPath: method, you may want to send setNeedsLayout to the cell after setting the text of the label. This will ensure that the cell receives layoutSubviews again, if it's being reused.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCell *cell = ...;
cell.customLabel.text = [self labelTextForIndexPath:indexPath];
[cell setNeedsLayout];
return cell;
}
Alternatively, you could make a UILabel subclass, like this:
#implementation MyLabel
- (void)layoutSubviews {
[self sizeToFit];
}
- (void)setText:(NSString *)text {
[super setText:text];
[self setNeedsLayout];
}
#end
and then set MyLabel as the custom class of the label in your nib. But having a view set its own frame in layoutSubviews seems a little fishy to me, so I usually avoid it.
You should put your code for size the Label in Table view's Delegate Method CellForRowAtIndexPath and not in viewDidLoad.
If your Label is in Table View Cell.
You may rewrite the -(void) awakeFromNib method for initializing the Label.

Resources