Add a second subtitle row to UITableViewCellStyleSubtitle - objective-c

I have already made a custom class with the init:
if(self = [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier]) {
}
As I wanted to add a blue texted label to the right hand side of the cell and have it go right when selected otherwise it looked odd when highlighted:
self.sizeTextLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.contentView.frame.size.width-110, 0.0, 100.0, 44.0)];
self.sizeTextLabel.textAlignment = NSTextAlignmentRight;
self.sizeTextLabel.backgroundColor = [UIColor whiteColor];
self.sizeTextLabel.textColor = [UIColor colorWithRed:81/255.0 green:102/255.0 blue:145/255.0 alpha:1.0];
self.sizeTextLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleHeight;
[self.contentView addSubview:self.sizeTextLabel];
There is probably a better way of doing that ^
What I would like to do is add another label that is effectively another subtitle row, I then increase the height of the row when the cell is created with the heightForRowAtIndexpath method.
Problem: When I add a new label 'row' to the content view, it does not get higher (the default views shift to the middle of the view). How do I create and position it correctly below the subtitle view? If I were to change the first subtitle to multiline it would be nice if the second label knew what to do.
I wish cocoa had relative positioning. Or I haven't found it yet!

You can make the detail text label multi line and add your two strings to the one label. In this example, my data has three keys in its dictionaries, "main" for the main label text, and "detail1 and "detail2" for the two subtitle strings.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSDictionary *object = _objects[indexPath.row];
cell.textLabel.text = object[#"main"];
NSString *concat = [NSString stringWithFormat:#"%#\n%#",object[#"detail1"],object[#"detail2"]];
cell.detailTextLabel.numberOfLines = 2;
cell.detailTextLabel.text = concat;
return cell;
}

You can make a custom cell with interface builder and use it instead of UITableViewCell.
Check this: http://www.backslashtraining.com/blog/2012/3/10/ios-5-tip-of-the-week-custom-table-view-cells.html

Related

How to avoid selecting other cells that have the same indexPath

I've been struggling with this issue for weeks and still have not found one solution. No one really gave me an answer on SO and have not found anything that helps my issue either.
When making a change of a cell's content's color, position, whatever, other cells with the same indexPath also get modified.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object{
static NSString *simpleTableIdentifier = #"cell";
self.cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (self.cell == nil) {
self.cell = [[SearchCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
This is how I create cells. Help..!
EDIT
This is a slide-out view implemented in each cell. When you swipe to right on a cell, it shows up from the left but even though only the selected cell's content should be modified, several other cell's slide-out menu also come out.
This is how I implement slide-out menu in my custom cell class.
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.optionView = [[OptionView alloc]initWithFrame:CGRectMake(0, 0, self.contentView.frame.size.width , self.contentView.frame.size.width)];
self.optionView.delegate = self;
[self.contentView addSubview: self.optionView];
OptionView' delegate - called when swiped to the right
-(void)handleGesture:(UISwipeGestureRecognizer*)shouldOpenMenu{
POPSpringAnimation *anim = [POPSpringAnimation animation];
anim.property = [POPAnimatableProperty propertyWithName:kPOPViewFrame];
anim.toValue = [NSValue valueWithCGRect:CGRectMake(-self.frame.size.width/4, 0, self.optionView0.frame.size.width, self.optionView0.frame.size.height)];
anim.springBounciness = 11;
anim.springSpeed = 5;
[self.optionView0.layer pop_addAnimation:anim forKey:#"spring0"];
First, each tableview cell has different index path.
Second, you never want to save cells at class level properties. Create them locally and return from cellForIndexPath:. Your table view will take care of the cell thereon.
Third, and very important, cells are reused. So, you should reset the cell before using it. For instance, if you are setting cell colour to red in some condition and then you move the table down and this cell gets discarded and new cell is rendered by re-using the discarded cell. You would want to reset the cell colour to clear if you are not setting cell colour for that row.
Follow these rules and you should be able to fix your issue.

Multiple NSTableCellView in one NSTableviewColumn Cocoa OSX

I am trying to create a NSTableview with different cells in one column. I am setting two NSTableCellView's in one column like so:
And setting the data code like so:
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
// Get a new ViewCell
// Since this is a single-column table view, this would not be necessary.
// But it's a good practice to do it in order by remember it when a table is multicolumn.
if( [tableColumn.identifier isEqualToString:#"BugColumn"] )
{
NSMutableDictionary *dic =(NSMutableDictionary*)[self.ArraRecentDataLoad objectAtIndex:row];
if([[dic valueForKey:#"type"] isEqualToString:#"image/png"] || [[dic valueForKey:#"type"] isEqualToString:#"image/jpeg"])
{
ImageCell *cellView = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
cellView = [[ImageCell alloc] initWithFrame:NSMakeRect(0, 0, 316, 313)];
// This allows the cell to be reused.
cellView.identifier =tableColumn.identifier;
NSColor *orangeColor = [NSColor colorWithCGColor:[NSColor colorWithRed:240/255.0f green:240/255.0f blue:240/255.0f alpha:1.0f].CGColor];
// Convert to CGColorRef
NSInteger numberOfComponents = [orangeColor numberOfComponents];
CGFloat components[numberOfComponents];
CGColorSpaceRef colorSpace = [[orangeColor colorSpace] CGColorSpace];
[orangeColor getComponents:(CGFloat *)&components];
CGColorRef orangeCGColor = CGColorCreate(colorSpace, components);
[cellView.bgCellview setWantsLayer:YES];
cellView.bgCellview.layer.masksToBounds= YES;
cellView.bgCellview.layer.borderWidth=2;
// Set border
cellView.bgCellview.layer.borderColor = orangeCGColor;
// Clean up
CGColorRelease(orangeCGColor);
return cellView;
}
else
{
HomeCell *cellView = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
NSColor *orangeColor = [NSColor colorWithCGColor:[NSColor colorWithRed:240/255.0f green:240/255.0f blue:240/255.0f alpha:1.0f].CGColor];
// Convert to CGColorRef
NSInteger numberOfComponents = [orangeColor numberOfComponents];
CGFloat components[numberOfComponents];
CGColorSpaceRef colorSpace = [[orangeColor colorSpace] CGColorSpace];
[orangeColor getComponents:(CGFloat *)&components];
CGColorRef orangeCGColor = CGColorCreate(colorSpace, components);
[cellView.bgview setWantsLayer:YES];
cellView.bgview.layer.masksToBounds= YES;
cellView.bgview.layer.borderWidth=2;
// Set border
cellView.bgview.layer.borderColor = orangeCGColor;
// Clean up
CGColorRelease(orangeCGColor);
return cellView;
}
}
return nil;
}
But in my xib if I drag a second cell (imageCell) then my app crashes with unrecognized select. If I do it like the above screenshot, then I am not able to load a second cell and there is white space in NSTableview.
I do lots of RND but I am not able to find a proper way to use different cells in a single column and load as per conditional data.
Note:
If I remove alloc cell in first condition:
cellView = [[ImageCell alloc] initWithFrame:NSMakeRect(0, 0, 316, 313)];
cellView.identifier =tableColumn.identifier;
Then that shows the first row's pre-define labels instead of second ImageCell predefine like iOS.
The two cell views need to have different identifiers. You will have to manually assign at least one of them. You can't let Xcode automatically assign both. (I'm not even sure if Xcode will let you configure things that way.)
Then, you need to use the proper identifier when you call [tableView makeViewWithIdentifier:... owner:self]. At most one of those calls can use the table column's identifier. The other must use the manually-assigned one.
If you put both cell views in the NIB (with separate identifiers) and fetch them using [tableView makeViewWithIdentifier:... owner:self], then you don't need to alloc/init one programmatically (and you shouldn't). If you prefer to alloc/init one programmatically, you must assign a different identifier for it. Again, you can't have two separate cell view types with the same identifier.
Update: Let me try again in simpler form. Do this:
In the NIB, select the Image Cell view. On the Identity inspector, set the identifier to "ImageCell".
In your code, for the image branch, do ImageCell *cellView = [tableView makeViewWithIdentifier:#"ImageCell" owner:self]; instead of using the table column identifier.
Remove the following two statements which allocate a new instance of the ImageCell class and sets its identifier property.
So, the code should look like this:
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
// Get a new ViewCell
// Since this is a single-column table view, this would not be necessary.
// But it's a good practice to do it in order by remember it when a table is multicolumn.
if( [tableColumn.identifier isEqualToString:#"BugColumn"] )
{
NSMutableDictionary *dic =(NSMutableDictionary*)[self.ArraRecentDataLoad objectAtIndex:row];
if([[dic valueForKey:#"type"] isEqualToString:#"image/png"] || [[dic valueForKey:#"type"] isEqualToString:#"image/jpeg"])
{
ImageCell *cellView = [tableView makeViewWithIdentifier:#"ImageCell" owner:self];
NSColor *orangeColor = [NSColor colorWithCGColor:[NSColor colorWithRed:240/255.0f green:240/255.0f blue:240/255.0f alpha:1.0f].CGColor];
// ...
See first of all make it view base table view from nib. Then in viewfortablecolumn put conditions like of image, then check first of view(image cell or home cell make it simple NSView) available for image type then use it or alloc using makeviewusingidentifire or what ever you use and return that view. On second condition you have do same for that.
For every time call this method it will check first which type of view (image cell or home cell in this particular) it wants then check if it was available in memory then use it if not then alloc and use it.
Let me know if any problem on this.
Sry for bad English

Adding label/button to UICollectionView - Footer or not?

I have a collectionView that displays an array of images in a single, horizontal layout. I'm trying to add a UILabel under each cell. I assumed the best/easiest way to do this would be to add a footer view/supplementary view for each cell. Therefore, I'm overriding viewForSupplementaryElementOfKind. I have an array of images names that correlate to the array of images. So I'm just hoping the see the image name as the label for each each cell. However, all labels and names are overlapping on the first cell. Also, the footer view doesn't come into view until I scroll to the last image/cell, so I don't see the overlapping labels on the first cell until I scroll to the end. I know the issue is in my viewForSupplementaryElementOfKind implementation, but I'm not sure how to correct it. Can someone please advise? Thanks in advance!!
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
NSLog(#"viewForSupplementaryElementOfKind");
static NSString *FooterCellIdentifier = #"FooterView"; // string value identifier for cell reuse
FooterViewCell *footerView;
if (kind == UICollectionElementKindSectionFooter) {
NSLog(#"*******Element Kind is a footer!*******");
footerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter
withReuseIdentifier:FooterCellIdentifier forIndexPath:indexPath];
for (int i = 0; i < [self.imagesArray count]; i++) {
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.myCollectionView.frame.origin.x/2, self.myCollectionView.frame.origin.y/2, CellWidth, 20)];
//testLabel.text = [self.imageNames objectAtIndex:indexPath.row];
testLabel.text = self.imageNames[i];
[self.myCollectionView addSubview:testLabel];
}
return footerView;
} else {
NSLog(#"*******Element Kind is NOT a footer!*******");
return nil;
}
}
Header and footer views on UICollectionView are only relative to sections.
Since the labels are supposed to identify the images (the model), you should build your UICollectionViewCell with the label and image view inside, as subviews. The easiest way is doing it inside a storyboard, with prototype cells on the collection view.

Adding multiple icons in a cell of a UITableViewCell

I have a UITableView with cells in it, and there are buttons to the right of the Table View, so that when I click one of the buttons it takes the selected TableViewCell's label text, and saves it to the array specific to the button that was clicked. The buttons have different colored text, "Green, Blue, Red, Purple, and Orange". What I want to happen, is when I click one of the buttons it will put a colored circle to the right of the text in the cell. The color of the circle will depend on what button was pressed. I feel like you could do something with the accessory view of the cell, but what gets tricky, is when you click another button for that same cell it will put another colored circle in. I want to be able to show 5 circles if needed and if you click the same button again it will take away the circle you previously added. Here is a picture of my app with some photoshoped circles to give you an idea.
Does anyone have any ideas or approaches to this problem. I cant seem to figure out how you would set multiple circles in the accessory view, and how it would effect the text. Would it move the text over?
Help would be much appreciated.
Thanks
you try this code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// In your case it has to be the custom cell object here.
MyCustomCell *cell = (MyCustomCell*)[tableView dequeueReusableCellWithIdentifier:#"AnIdentifierString"];
if (cell == nil) {
cell = [[[MyCustomCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"AnIdentifierString"] autorelease];
}
//use your cell here----------
// cell.textLabel.text = #"This text will appear in the cell";
return cell;
}
You can override init with style of MyCustomCell as follows for multiple images
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
//change frame sizes to palce the image in the cell
UIImageView * thumbnail1 = [[UIImageView alloc] initWithFrame:CGRectMake(17, 12, 62, 62)];
thumbnail1.image = [UIImage imageNamed:#"Icon.png"];
[self addSubview:thumbnail1];
UIImageView * thumbnail2 = [[UIImageView alloc] initWithFrame:CGRectMake(17, 12, 62, 62)];
thumbnail1.image = [UIImage imageNamed:#"Icon.png"];
[self addSubview:thumbnail2];
UIImageView * thumbnail3 = [[UIImageView alloc] initWithFrame:CGRectMake(17, 12, 62, 62)];
thumbnail3.image = [UIImage imageNamed:#"Icon.png"];
[self addSubview:thumbnail3];
}
return self;
}

How to make a-two-column UITableViewController list?

I need to present my table view with a two column list. I read some related posts about making some grid by overriding drawRect (here). However, I'm seeking a simple way to design my cell with IB in nib, then load it and push two cells on each row. The example with drawRect is not appropriate because it involves manual setting of positions. I just need to push those two cells with some autosizing, that's it. Is it possible?
I'm looking for something like (in cellForRowAtIndexPath):
cell.contentView = emptyUIViewContainer;
[cell.contentView addSubview:FirstColumnUIView];
[cell.contentView addSubview:SecondColumnUIView];
I don't need to have two separate nibs for those two columns because every column is of the same format just with some other data. Any ideas?
UPDATE: Intuitively, I'm trying to do something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell1 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell1 == nil) {
cell1 = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the first cell.
cell1.textLabel.text = ...some text
// Configure the second cell
UITableViewCell *cell2 = [[UITableViewCell alloc] init];
cell2.textLabel.text = ...some text
//set row as container for two cells
UITableViewCell *twoColumnRowView = [[UIView alloc] init]; //initWithFrame:CGRectMake(0, 0, 200, 20)];
cell1.contentView.frame = CGRectMake(0, 0, 100, 20);
[twoColumnRowView addSubview:cell1];
cell2.contentView.frame = CGRectMake(100, 0, 100, 20);
[twoColumnRowView addSubview:cell2];
return twoColumnRowView; // cell;
}
It's just a raw prototype I'm playing with now. But the code crashes at runtime with "Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView setTableViewStyle:]: unrecognized selector sent to instance"
UPDATE 2. I have changed a code to look more practical. Strange but after several tries I got the app working without crash but with weird black background in all cells. Here is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *FirstCellIdentifier = #"FirstCellIdentifier";
static NSString *SecondCellIdentifier = #"SecondCellIdentifier";
// initialize first cell
UITableViewCell *cell1 = [tableView dequeueReusableCellWithIdentifier:FirstCellIdentifier];
if (cell1 == nil) {
cell1 = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:FirstCellIdentifier] autorelease];
}
//initialize second cell
UITableViewCell *cell2 = [tableView dequeueReusableCellWithIdentifier:SecondCellIdentifier];
if (cell2 == nil) {
cell2 = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SecondCellIdentifier] autorelease];
}
cell1.textLabel.text = ...data
cell2.textLabel.text = ...data
UITableViewCell *twoColumnRowView = [[UITableViewCell alloc] init];
[twoColumnRowView addSubview:cell1];
//cell2.contentView.frame = CGRectMake(100, 0, 100, 20);
[twoColumnRowView addSubview:cell2];
return twoColumnRowView; // cell;
}
I'm not reusing twoColumnRowView but both other does do.
You can't (or at least, shouldn't) put two table views next to each other. And, as you already know, a table view only ever has a single column.
However, you can put as much data as you want in each cell.
You can do most of this in Interface Builder. Create a XIB with a UITableViewCell. Drag and drop a couple of UILabels into the right place. You could update the labels by finding them with the viewWithTag: method, but it would be better to create a custom UITableViewCell class with properties pointing to each label.
Since tables are so central to UIKit, there are a lot of samples in Apple's documentation set and some good WWDC talks. You can download the videos from iTunes.
Hope this will help you...
http://www.iphonedevx.com/?p=153
else the best way is to put two table views side by side, if they need to scroll independently.
Hope this will help you...