I want to make a UITableView, which has many columns, so the whole cell can't display the all data, and the first column shows titles, this row can't move flatly, but other rows can move flatly.
I tried adding UITableView to UIScrollView, but failed
Is there any ways to achieve this requirement?
You need to make a custom TableViewCell to achieve this properly.
EDIT:
A quick example:
#import <UIKit/UIKit.h>
#interface MultiColumnTableViewCell : UITableViewCell
{
UIButton *leftButton;
UIButton *middleButton;
UIButton *rightButton;
}
#property (nonatomic,retain) UIButton *leftButton;
#property (nonatomic,retain) UIButton *middleButton;
#property (nonatomic,retain) UIButton *rightButton;
#end
#import "MultiColumnTableViewCell.h"
#implementation MultiColumnTableViewCell
#synthesize leftButton;
#synthesize middleButton;
#synthesize rightButton;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
leftButton = [[UIButton alloc] init];
[leftButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
leftButton.titleLabel.textAlignment = UITextAlignmentCenter;
leftButton.titleLabel.font = [UIFont systemFontOfSize:15.0];
leftButton.titleLabel.numberOfLines = 2;
middleButton = [[UIButton alloc] init];
[middleButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
middleButton.titleLabel.textAlignment = UITextAlignmentCenter;
middleButton.titleLabel.font = [UIFont systemFontOfSize:15.0];
middleButton.titleLabel.numberOfLines = 2;
rightButton = [[UIButton alloc] init];
[rightButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
rightButton.titleLabel.textAlignment = UITextAlignmentCenter;
rightButton.titleLabel.font = [UIFont systemFontOfSize:15.0];
rightButton.titleLabel.numberOfLines = 2;
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
Quick usage in tableview:
- (MultiColumnTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
MultiColumnTableViewCell *cell = (MultiColumnTableViewCell*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[MultiColumnTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Set up the cell...
float tableviewWidth = self.myTableView.frame.size.width/3;
int irow = indexPath.row;
NSString *cellValue = myString;
cell.leftButton.frame = CGRectMake(0, 0, tableviewWidth, 64.0);
cell.leftButton.tag = someTag;
[cell.leftButton setTitle:cellValue forState:UIControlStateNormal];
[cell.leftButton addTarget:self action:#selector(someAction:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:cell.leftButton];
cellValue = someOtherString;
cell.middleButton.frame = CGRectMake(tableviewWidth, 0, tableviewWidth, 64.0);
cell.middleButton.tag = someOtherTag;
[cell.middleButton setTitle:cellValue forState:UIControlStateNormal];
[cell.middleButton addTarget:self action:#selector(someOtherAction:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:cell.middleButton];
cellValue = yetAnotherString
cell.rightButton.frame = CGRectMake(tableviewWidth*2, 0, tableviewWidth, 64.0);
cell.rightButton.tag = yetAnotherTag;
[cell.rightButton setTitle:cellValue forState:UIControlStateNormal];
[cell.rightButton addTarget:self action:#selector(yetAnotherAction:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:cell.rightButton];
return cell;
}
Related
I m trying to add cells to a tableView
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
cell.accessoryType = UITableViewCellAccessoryNone;
[cell setSelectionStyle:UITableViewCellEditingStyleNone];
// Set up the cell
cell.backgroundColor = [UIColor clearColor];
UIButton *buyBtn = [UIButton buttonWithType:UIButtonTypeCustom];
UIImageView *img;
UILabel *lbl;
UIImageView *backImage;
UILabel *textLabel;
UILabel *detailTextLabel;
NSInteger val = [indexPath row] * 3;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
//*buyBtn = [[UIButton alloc] initWithFrame:CGRectMake(x, y, w, h)];
[buyBtn setImage:[UIImage imageNamed:#""] forState:UIControlStateNormal];
//*img = [[UIImageView alloc] initWithFrame:CGRectMake(x, y, w, h)];
[img setImage:[UIImage imageNamed:#""]];
//*lbl = [[UILabel alloc] initWithFrame:CGRectMake(x,y,w,h)];
}
else
{
backImage = [[UIImageView alloc] initWithFrame:CGRectMake(2, 4, 316, 62)];
[buyBtn setFrame:CGRectMake(257, 100, 57, 24)];
img = [[UIImageView alloc] initWithFrame:CGRectMake(257, 75, 57, 24)];
lbl = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 57, 24)];
textLabel = [[UILabel alloc] initWithFrame:CGRectMake(4, 4, 230, 25)];
detailTextLabel = [[UILabel alloc] initWithFrame:CGRectMake(4, 25, 230, 30)];
backImage.image = [UIImage imageNamed:#"shop-bg.png"];
[buyBtn setImage:[UIImage imageNamed:#"buy_button"] forState:UIControlStateNormal];
[img setImage:[UIImage imageNamed:#"price_button.png"]];
lbl.center = img.center;
lbl.textAlignment = UITextAlignmentCenter;
lbl.text = [self.original_List objectAtIndex:val+2];
lbl.backgroundColor = [UIColor clearColor];
textLabel.font = [UIFont fontWithName:#"Arial Rounded MT Bold" size:14];
textLabel.backgroundColor = [UIColor clearColor];
textLabel.text = [self.original_List objectAtIndex:val];
detailTextLabel.text = [self.original_List objectAtIndex:val+1];
detailTextLabel.backgroundColor = [UIColor clearColor];
detailTextLabel.font = [UIFont fontWithName:#"Arial Rounded MT Bold" size:10];
textLabel.textColor = [UIColor blackColor];
detailTextLabel.textColor = [UIColor whiteColor];
detailTextLabel.numberOfLines = 2;
}
[buyBtn setTag:[indexPath row]];
[buyBtn addTarget:self action:#selector(buyBtnPressed:) forControlEvents:UIControlEventTouchDown];
[cell addSubview:backImage];
[cell addSubview:detailTextLabel];
[cell addSubview:textLabel];
[cell addSubview:buyBtn];
[cell addSubview:img];
[cell addSubview:lbl];
return cell;
}
From figure it can be seen that The first Cell DOES NOT Contain the added image, label and button, however if other cells are scrolled those who lost view turn transparent while those who are in view are okay.
Why is my three subview not getting added from first cell, my textLabel and detailTextLabel are added as they should.
First of all you don't dequeue the cell and always create a new one without reusing. Try adding something like this (not sure if you need autorelease, depends on weather you use ARC or not):
RecentsTableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[RecentsTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:cellIdentifier] autorelease];
}
Second, if you are not using ARC (auto ref counting) then you have bunch of lost refs here.
[[Class alloc] init] adds the ref and addSubview also adds the ref. I'm wondering what xcode "analyse" build says on this.
Third, imho all labels you added to the cell need also their "frame" property to set up, not just number of lines, etc.
here is example of how I did it. I created cell class derived what what you need (CopyableCell in my case).
This is *.h file.
#import <UIKit/UIKit.h>
#import "CopyableCell.h"
#interface RecentsTableViewCell : CopyableCell
#property (readonly, retain) UILabel *titleLabel;
#property (readonly, retain) UILabel *detailsLabel;
#property (readonly, retain) UILabel *subdetailsLabel;
#property (readonly, retain) UILabel *subtitleLabel;
#end
Here is *.m file.
#import "RecentsTableViewCell.h"
#interface RecentsTableViewCell ()
// Redeclare property as readwrite
#property (readwrite, retain) UILabel *titleLabel;
#property (readwrite, retain) UILabel *subtitleLabel;
#property (readwrite, retain) UILabel *detailsLabel;
#property (readwrite, retain) UILabel *subdetailsLabel;
#end
#implementation RecentsTableViewCell
#synthesize titleLabel;
#synthesize subtitleLabel;
#synthesize detailsLabel;
#synthesize subdetailsLabel;
- (void) layoutSubviews
{
int leftMargin = 30;
int rightMargin = 6;
[super layoutSubviews];
CGRect cellRect = self.contentView.frame;
int width = cellRect.size.width - (leftMargin + rightMargin);
CGSize constraintSize = CGSizeMake(300, MAXFLOAT);
CGSize titleSize = [titleLabel.text sizeWithFont:titleLabel.font
constrainedToSize:constraintSize
lineBreakMode:UILineBreakModeTailTruncation];
CGSize detailsSize = [detailsLabel.text sizeWithFont:detailsLabel.font
constrainedToSize:constraintSize
lineBreakMode:UILineBreakModeTailTruncation];
if (titleSize.width > titleLabel.frame.size.width ||
detailsSize.width > detailsLabel.frame.size.width) {
CGRect detailsFrame = detailsLabel.frame;
detailsFrame.size.width = detailsSize.width;
detailsFrame.origin.x = cellRect.size.width -
(detailsSize.width + subdetailsLabel.frame.size.width + rightMargin);
CGRect titleFrame = titleLabel.frame;
titleFrame.size.width = width - detailsSize.width - subdetailsLabel.frame.size.width - 5;
titleLabel.frame = titleFrame;
detailsLabel.frame = detailsFrame;
}
}
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
CGRect cellRect = self.contentView.frame;
cellRect.size.height = 61;
self.contentView.frame = cellRect;
int leftMargin = 30;
int rightMargin = 6;
int x = cellRect.origin.x + leftMargin;
int y = cellRect.origin.y;
int width = cellRect.size.width - (leftMargin + rightMargin);
int height = cellRect.size.height;
int titleWidth = width * 0.75;
int alldetailsWidth = width - titleWidth;
int detailsWidth = alldetailsWidth * 0.65;
int subdetailsWidth = alldetailsWidth - detailsWidth;
int titleHeight = height * 0.38;
int subtitleHeight = height - titleHeight;
self.titleLabel = [[[UILabel alloc]
initWithFrame:CGRectMake(x, y, titleWidth, titleHeight)] autorelease];
self.titleLabel.font = [UIFont boldSystemFontOfSize:18.0f];
self.titleLabel.highlightedTextColor = self.textLabel.highlightedTextColor;
self.titleLabel.textAlignment = UITextAlignmentLeft;
self.titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleBottomMargin;
[self.contentView addSubview:titleLabel];
self.detailsLabel = [[[UILabel alloc]
initWithFrame:CGRectMake(cellRect.size.width -
(detailsWidth + subdetailsWidth + rightMargin),
y + 4, detailsWidth, titleHeight - 4)] autorelease];
self.detailsLabel.font = [UIFont boldSystemFontOfSize:13.0f];
self.detailsLabel.textColor = [UIColor colorWithRed:0.12 green:0.439 blue:0.847 alpha:1];
self.detailsLabel.textAlignment = UITextAlignmentRight;
self.detailsLabel.highlightedTextColor = self.textLabel.highlightedTextColor;
self.detailsLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleHeight;
[self.contentView addSubview:detailsLabel];
self.subdetailsLabel = [[[UILabel alloc]
initWithFrame:CGRectMake(cellRect.size.width - (subdetailsWidth + rightMargin),
y + 6, subdetailsWidth, titleHeight - 6)] autorelease];
self.subdetailsLabel.font = [UIFont systemFontOfSize:11.0f];
self.subdetailsLabel.textColor = [UIColor colorWithRed:0.12 green:0.439 blue:0.847 alpha:1];
self.subdetailsLabel.textAlignment = UITextAlignmentCenter;
self.subdetailsLabel.highlightedTextColor = self.textLabel.highlightedTextColor;
self.subdetailsLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleHeight;
[self.contentView addSubview:subdetailsLabel];
self.subtitleLabel = [[[UILabel alloc]
initWithFrame:CGRectMake(x, y + titleHeight, width, subtitleHeight - 2)] autorelease];
self.subtitleLabel.highlightedTextColor = self.textLabel.highlightedTextColor;
self.subtitleLabel.font = [UIFont systemFontOfSize:13.0f];
self.subtitleLabel.textColor = [UIColor darkGrayColor];
self.subtitleLabel.numberOfLines = 2;
self.subtitleLabel.lineBreakMode = UILineBreakModeTailTruncation;
self.subtitleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleTopMargin;
[self.contentView addSubview:subtitleLabel];
self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
return self;
}
- (id) init
{
return [self initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"RecentsCell"];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
}
- (void) dealloc
{
self.titleLabel = nil;
self.subtitleLabel = nil;
self.detailsLabel = nil;
self.subdetailsLabel = nil;
[super dealloc];
}
#end
Note that I'm not using ARC so if you use this code, modify it accordingly. Here is how I use this class in my table view controller.
- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"TransactionCell";
NSMutableArray *data = searching ? searchResult : dataSource;
NSDictionary *object = [data objectAtIndex:[indexPath row]];
RecentsTableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[RecentsTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:cellIdentifier] autorelease];
}
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
cell.indexPath = indexPath;
cell.delegate = self;
cell.titleLabel.text = #"Transaction title";
if (pendingTransaction) {
cell.titleLabel.textColor = [UIColor grayColor];
cell.titleLabel.font = [UIFont systemFontOfSize:cell.titleLabel.font.pointSize];
} else {
if (!isGreen)
cell.titleLabel.textColor = [UIColor colorWithRed:0.733 green:0.098
blue:0.098 alpha:1];
else
cell.titleLabel.textColor = cell.textLabel.textColor;
cell.titleLabel.font = [UIFont boldSystemFontOfSize:cell.titleLabel.font.pointSize];
}
cell.subtitleLabel.text = #"Transaction subtitle";
cell.detailsLabel.text = #"Some details like location";
cell.subdetailsLabel.text = #"200 USD";
return cell;
}
This produces table very similar to what you see in iphone call app, that is, title, subtitle, subdetails in blue at rightmost position of the cell, etc.
You can see it in Torchoo app in the appstore. It is free to use and you can use test account to log in and see it as example.
Hope this helps a bit.
Are you continuously adding subView to cell not removing any subView?
Check condition while adding subView like code not exact I have written:
if ([[cell.contentView subviews] count]==0) {
[self.contentView addSubview:imageView];
}
If cell content View doesn't contain that View then add it.
Previous answer is correct although there is more that you could fix.
The part of code that adds subviews should only be called in case when the cell is not dequeued. Otherwise you'll be adding multiple instances of the same buttons, views etc.
[cell addSubview:backImage];
[cell addSubview:detailTextLabel];
[cell addSubview:textLabel];
[cell addSubview:buyBtn];
[cell addSubview:img];
[cell addSubview:lbl];
Also I guess it is better to add to cell.contentView instead of directly to cell. So it should look something like this:
RecentsTableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[RecentsTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:cellIdentifier] autorelease];
/*Create your subviews here*/
[cell.contentView addSubview:backImage];
[cell.contentView addSubview:detailTextLabel];
[cell.contentView addSubview:textLabel];
[cell.contentView addSubview:buyBtn];
[cell.contentView addSubview:img];
[cell.contentView addSubview:lbl];
}
// Below just set properties of existing subviews of the cell: color, textColor, text etc.
// You need to retrieve them and one way is to assign them to properties in
// RecentsTableViewCell or set the tag property of the subviews and retrieve
// them using e.g. [cell.contentView viewWithTag:kBuyButtonTag].
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
...
}
else {
...
}
In my application i am trying to adjust the position of the textlabel and detailtextlabel in a tableview cell.I am doing like this `
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
UIImageView* img = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"cell_with_arrow.png"]];
[cell setBackgroundView:img];
[img release];
}
cell.textLabel.frame = CGRectMake(0,0, 150, 40);
cell.detailTextLabel.frame = CGRectMake(155, 55, 150, 40);
cell.textLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:14.0];
cell.textLabel.textColor = [UIColor blackColor];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.textLabel.text =#"name";
cell.detailTextLabel.text=#" status";
cell.detailTextLabel.backgroundColor = [UIColor clearColor];
//cell.detailTextLabel.textAlignment = UITextAlignmenteft;
//cell.textLabel.textAlignment = UITextAlignmentLeft;
return cell;
}
`but seems to be having no effect.can anybody help me to point me where i am going wrong?
textLabel and detailTextLabel are readonly so you can not change them.
#property(nonatomic, readonly, retain) UILabel *textLabel
#property(nonatomic, readonly, retain) UILabel *detailTextLabel
See here
What I would suggest is that you could create your custom UITableViewCell instead, you will have more control over it's content and can add custom subviews in there as well.
Here are some tutorials for that:
From IB
From Code
you need to override layoutSubviews method
Create a customcell class and inherit with uitableviewcell
#try this code
CustomCell.h
#import <UIKit/UIKit.h>
#interface CustomCell : UITableViewCell
#end
CustomCell.m
#import "CustomCell.h"
#implementation CustomCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
-(void)layoutSubviews{
//Set here your frame
self.textLabel.frame = CGRectMake(0, , 320, 30);
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
In my UITableViewCell i have a UIButton and a label which is been dynamically added to the cell.
I have a background image for the cell too so when this button gets clicked i want either the background of the cell to get replace with another image or i want the text color of the label to change to something else like gray or blue.
Is that possible?
Here's the code for ny cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
NSArray *subviews = cell.contentView.subviews;
for (UIView *vw in subviews)
{
if ([vw isKindOfClass:[UILabel class]])
{
[vw removeFromSuperview];
}
}
NSArray * temp;
NSData * imageData;
if (dataToDisplay!=nil) {
temp = [dataToDisplay objectAtIndex:indexPath.row];
imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString: [temp objectAtIndex:4]]];
}
playButtonImage = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"music_player_play_button.png"]];
pauseButtonImage = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"music_player_pause_button.png"]];
UIButton* preview = [UIButton buttonWithType:UIButtonTypeCustom];
preview.tag = 100 + indexPath.row;
[preview addTarget:self
action:#selector(playPreview:)
forControlEvents:UIControlEventTouchUpInside];
preview.backgroundColor = [UIColor clearColor];
preview.frame = CGRectMake(11,6, 36, 35);
[preview setBackgroundImage:playButtonImage.image forState:UIControlStateNormal];
[cell addSubview:preview];
UILabel * songName = [[UILabel alloc]initWithFrame:CGRectMake(60,15, 150, 15)];
songName.tag = 100+indexPath.row;
songName.text = [temp objectAtIndex:5];
songName.font = [UIFont boldSystemFontOfSize:12];
songName.backgroundColor = [UIColor clearColor];
[cell addSubview:songName];
UIButton * buy = [UIButton buttonWithType:UIButtonTypeCustom];
[buy addTarget:self
action:#selector(buySong:)
forControlEvents:UIControlEventTouchUpInside];
[buy setImage:[UIImage imageNamed:#"button_buy.png"] forState:UIControlStateNormal];
buy.tag = 200 + indexPath.row;
[buy setTitle:#"Buy" forState:UIControlStateNormal];
buy.titleLabel.font = [UIFont boldSystemFontOfSize:8.0];
buy.frame = CGRectMake(255,9,41, 30);
[cell addSubview:buy];
songsResults.tableHeaderView = headerView;
UIImage * cellIcon;
if (indexPath.row==[dataToDisplay count]-1) {
cellIcon = [UIImage imageNamed:[cellViewImages objectAtIndex:1]];
}
else {
cellIcon = [UIImage imageNamed:[cellViewImages objectAtIndex:0]];
}
cell.backgroundView = [[UIImageView alloc]initWithImage:cellIcon];
cell.clipsToBounds = YES;
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
Using the tag as an identifier of the cell whose button was pressed. That way you can determine which cell you need to change:
-(void)buySong:(id)sender {
UIButton *buttonPressed = (UIButton*)sender;
NSUInteger rowSelected = buttonPressed.tag - 200;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowSelected inSection:0];
CustomTableViewCell *cellSelected = (CustomTableViewCell)[self.tableView cellForRowAtIndexPath:indexPath];
cellSelected.label.textColor = [UIColor redColor];
}
You should subclass UITableViewCell so you can add new attributes to it and access them later on, like I did with CustomTableViewCell.
Here is a tutorial on how to create a custom UITableViewCell.
Cheers
I'd make a subclass of UITableViewCell that has its own action method to receive the button click, and use a block to handle that click so that your controller code could look something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
SongCell *cell = [tableView dequeueReusableCellWithIdentifier:[SongCell identifier]];
if (cell == nil) {
cell = [[SongCell alloc] init];
}
cell.songData = [dataToDisplay objectAtIndex:indexPath.row];
cell.onPreviewClick =
^
(SongCell *cell)
{
cell.isPlaying = YES;
[self playSongAtIndexPath:indexPath]; // method to start the preview
};
return cell
}
To support this, your UITableViewCell subclass would look something like this:
// SongCell.h
#interface SongCell : UITableViewCell
#property (nonatomic, strong) NSArray *songData; // NSDictionary would be better
#property (nonatomic, copy) void(^onPreviewClick)(SongCell *cell);
#property (nonatomic, assign) BOOL isPlaying;
+ (NSString *)identifier;
#end
with this implementation:
// SongCell.m
#import "SongCell.h"
#interface SongData()
#property (nonatomic, strong) NSArray *_songData;
#property (nonatomic, assign) BOOL _isPlaying;
#property (nonatomic, strong) UIButton *playImage;
#property (nonatomic, strong) UIButton *pauseImage;
#property (nonatomic, strong) UIButton *previewButton;
#property (nonatomic, strong) UILabel *songNameLabel;
- (void)previewButtonPressed:(UIButton *)button;
#end
#implementation SongCell
#synthesize onPreviewClick, _songData, _isPlaying, playImage, pauseImage, previewButton, songNameLabel;
- (id)init {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[SongCell identifier]])) {
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.playImage = [UIImage imageNamed:#"music_player_play_button.png"];
self.pauseImage = [UIImage imageNamed:#"music_player_pause_button.png"];
self.previewButton = [UIButton buttonWithType:UIButtonTypeCustom];
previewButton.frame = CGRectMake(11,6, 36, 35);
[previewButton addTarget:self
action:#selector(previewButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
[self addSubview:previewButton];
self.songNameLabel = [[UILabel alloc]initWithFrame:CGRectMake(60,15, 150, 15)];
songNameLabel.font = [UIFont boldSystemFontOfSize:12];
[self addSubview:songNameLabel];
}
return self;
}
+ (NSString *)identifier {
return #"SongCell";
}
- (void)setSongData:(NSArray *)songData
{
self._songData = songData;
[self updateSubviews];
}
- (NSArray *)songData {
return _songData;
}
- (void)setIsPlaying:(BOOL)isPlaying {
self._isPlaying = isPlaying;
[self updateSubviews];
}
- (BOOL)isPlaying {
return _isPlaying;
}
- (void)previewButtonPressed:(UIButton *)button {
if (onPreviewClick) onPreviewClick(self);
}
- (void)updateSubviews {
if (_isPlaying) {
[previewButton setBackgroundImage:pauseImage forState:UIControlStateNormal];
}
else {
[previewButton setBackgroundImage:playImage forState:UIControlStateNormal];
}
songNameLabel.text = [_songData objectAtIndex:5];
}
#end
Caveat: I didn't test this. Hopefully it doesn't have too many errors.
I implemented the following method in my tableviewcontroller for showing favorites with empty star and filled star:
-(IBAction) tapped:(UIButton *)sender
{
if([sender isSelected])
{
//...
[sender setImage:[UIImage imageNamed:#"fav-empty.png"] forState:UIControlStateNormal];
[sender setSelected:NO];
}
else
{
//...
[sender setImage:[UIImage imageNamed:#"fav-filled.png"] forState:UIControlStateNormal];
[sender setSelected:YES];
NSLog(#"%#",sender);
}
}
and I tried to use in this part:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UILabel *recept_neve=[[UILabel alloc] initWithFrame:CGRectMake(10, 10, 100, 40)];
[recept_neve setTag:1];
UIButton *kedvenc_btn=[UIButton buttonWithType:UIButtonTypeCustom];
[kedvenc_btn setImage:[UIImage imageNamed:#"fav-empty.png"] forState:UIControlStateNormal];//default appereance on the startup
kedvenc_btn.frame=CGRectMake(200, 20, 50, 50);
[kedvenc_btn setTag:2];
[kedvenc_btn addTarget:self action:#selector(tapped:) forControlEvents:UIControlEventTouchUpInside];
[[cell contentView] addSubview:recept_neve];
[[cell contentView] addSubview:kedvenc_btn];
//[(UILabel*) [[cell contentView] viewWithTag:1] setText:[receptek objectAtIndex:indexPath.section*blokk+1]];
//[(UIButton *) [cell contentView] viewWithTag:2];
}
// Configure the cell...
cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
[(UILabel*) [[cell contentView] viewWithTag:1] setText:[receptek objectAtIndex:indexPath.section*blokk+1]];
return cell;
}
My problem is that every fifth button in the cells are working as would be the same.
If I tap on the button(empty star) in the first cell, the result will be the following: the first button becoming filled-star, so far so good(the expected behaviour), but in the same time the sixth star becoming filled too. Or if I tap on the second one, the seventh star getting filled and vica versa...
I logged the buttons where I tapping , and I realised, that the memory adresses are equals in the case of buttons above mentioned.
Sorry about my english, and thanks a lot for every help in advance!
the problem was that you reused the buttons all the time.
I show you a sample working code to structure a customized UITableViewCell correctly...
Let's do it step by step.
Create a new class called MyObjTableViewCellForSelection and provide these methods. Adapt it to your needs!
#class MyObj;
#interface MyObjTableViewCellForSelection : UITableViewCell
{
MyObj *myObj;
UIImageView *imageView;
UILabel *titleLabel;
}
#property (nonatomic,strong) MyObj *myObj;
#property (nonatomic,strong) UIImageView *imageView;
#property (nonatomic,strong) UILabel *titleLabel;
#end
Then the implementation:
#implementation MyObjTableViewCellForSelection
#synthesize myObj;
#synthesize imageView;
#synthesize titleLabel;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
imageView = [[UIImageView alloc] initWithFrame: CGRectZero];
imageView.contentMode = UIViewContentModeScaleAspectFit;
[self.contentView addSubview: imageView];
titleLabel = [[UILabel alloc] initWithFrame: CGRectZero];
[titleLabel setFont:[UIFont systemFontOfSize:14.0]];
[titleLabel setTextColor:[UIColor blackColor]];
[titleLabel setHighlightedTextColor:[UIColor darkGrayColor]];
[titleLabel setLineBreakMode: UILineBreakModeWordWrap];
titleLabel.numberOfLines = 2;
[self.contentView addSubview: titleLabel];
}
return self;
}
-(void) layoutSubviews {
[super layoutSubviews];
[imageView setFrame:CGRectMake(8.0, 10.0, 20.0, 20.0)];
[titleLabel setFrame:CGRectMake(40.0, 1.0, 250.0, 40.0)]; //two lines
}
- (void)setMyObj:(MyObj *)myObjX {
if (myObjX != myObj) {
[myObj release];
[myObjX retain];
//myObj = myObjX; //only with ARC on
}
titleLabel.text = whatever you need accessing myObj
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
// selection has to be adapted to your structure
[super setSelected:selected animated:animated];
switch (myObj.selectedFlag) {
case MYOBJ_STATUS_UNSELECTED:
imageView.image = [UIImage imageNamed:#"EmptyBullet.png"];
break;
case MYOBJ_STATUS_SELECTED:
imageView.image = [UIImage imageNamed:#"GreyBullet.png"];
break;
default:
break;
}
#end
now in your view class you can finally do:
- (MyObj *)myObjForIndexPath:(NSIndexPath *)indexPath {
MyObj* tmpObj = get the corresponding object
return tmpObj;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyObjTableViewCellForSelection *cell = (MyObjTableViewCellForSelection *)[tableView dequeueReusableCellWithIdentifier:#"cellID"];
if (cell == Nil) {
cell = [[ECUTableViewCellForSelection alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cellID"];
}
cell.myObj = [self myObjForIndexPath:indexPath]; //the assignment calls setMyObj of CLASS ECUTableViewCellForSelection that you just declared
return cell;
}
So finally that's the clean way of doing it...
Can anybody tell me how to create a tableview
with two cells by colums in the Iphone SDK??
order in like this :
_____________
| 1 | 2 |
|_____|______|
| 3 | 4 |
|_____|______|
Best regards
In ios UITableView you can only have one column/cell. If you want more propertyes, in a same cell you need to create a custom table view cell by subcalssing UITableViewCell. In interface builder you can customize the layout. TUTORIAL: http://adeem.me/blog/2009/05/30/iphone-sdk-tutorial-part-6-creating-custom-uitableviewcell-using-interface-builder-uitableview/
Concrete example for your problem:
the .h file:
#import <UIKit/UIKit.h>
#interface MyCell : UITableViewCell {
UIButton * column1;
UIButton * column2;
UILabel* column1_label1;
UILabel* column1_label2;
UILabel* column2_label1;
UILabel* column2_label2;
}
#property (nonatomic,retain) UIButton * column1;
#property (nonatomic,retain) UIButton * column2;
#property (nonatomic,retain) UILabel* column1_label1;
#property (nonatomic,retain) UILabel* column1_label2;
#property (nonatomic,retain) UILabel* column2_label1;
#property (nonatomic,retain) UILabel* column2_label2;
#end
the .m file:
#import "MyCell.h"
#implementation MyCell
#synthesize column1,column1_label1,column1_label2,column2,column2_label1,column2_label2;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
column1 = [UIButton buttonWithType: UIButtonTypeCustom];
column1.tag = 1;
column1.autoresizingMask = 292;
column1.backgroundColor = [UIColor redColor];
column1.frame = CGRectMake(0, 0, self.contentView.bounds.size.width/2, self.contentView.bounds.size.height);
column1_label1 = [[UILabel alloc] initWithFrame: CGRectMake(column1.bounds.size.width*1/5,
0,
column1.bounds.size.width*4/5,
column1.bounds.size.height/2)];
column1_label1.backgroundColor = [UIColor redColor];
[column1 addSubview:column1_label1];
column1_label2 = [[UILabel alloc] initWithFrame: CGRectMake(column1.bounds.size.width*1/5,
column1.bounds.size.height/2,
column1.bounds.size.width*4/5,
column1.bounds.size.height/2)];
column1_label2.backgroundColor = [UIColor greenColor];
[column1 addSubview:column1_label2];
[self.contentView addSubview: column1];
column2 = [UIButton buttonWithType: UIButtonTypeCustom];
column2.tag = 2;
column2.autoresizingMask = 292;
column2.backgroundColor = [UIColor greenColor];
column2.frame = CGRectMake(self.contentView.bounds.size.width/2, 0, self.contentView.bounds.size.width/2, self.contentView.bounds.size.height);
column2_label1 = [[UILabel alloc] initWithFrame: CGRectMake(column2.bounds.size.width*1/5,
0,
column2.bounds.size.width*4/5,
column2.bounds.size.height/2)];
column2_label1.backgroundColor = [UIColor redColor];
[column2 addSubview:column2_label1];
column2_label2 = [[UILabel alloc] initWithFrame: CGRectMake(column2.bounds.size.width*1/5,
column2.bounds.size.height/2,
column2.bounds.size.width*4/5,
column2.bounds.size.height/2)];
column2_label2.backgroundColor = [UIColor greenColor];
[column2 addSubview:column2_label2];
[self.contentView addSubview: column2];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)dealloc
{
[super dealloc];
}
#end
the usage in UITableViewController:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 40;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
MyCell * mycell2 = ((MyCell*)cell);
if (cell == nil) {
cell = [[[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
[mycell2.column1 addTarget:self action:#selector(column1Selected:) forControlEvents:UIControlEventTouchUpInside];
[mycell2.column2 addTarget:self action:#selector(column1Selected:) forControlEvents:UIControlEventTouchUpInside];
}
// Configure the cell...
mycell2.column1_label1.text = #"column1_label1";
mycell2.column1_label2.text = #"column1_label2";
mycell2.column1.tag = indexPath.row*2;
mycell2.column2_label1.text = #"column2_label1";
mycell2.column2_label2.text = #"column2_label2";
mycell2.column2.tag = indexPath.row*2 +1;
return cell;
}
- (void) column1Selected: (id) sender
{
UIAlertView *alert = [[ UIAlertView alloc]
initWithTitle: #" Alert"
message: [NSString stringWithFormat: #"button %d",((UIButton *) sender).tag]
delegate: nil
cancelButtonTitle: #" OK"
otherButtonTitles: nil];
[alert show] ;
[alert release];
}
In iOS6 you can use the UICollectionView.
If you need iOS5 support AQGridView is a grid control that will give you what you are after.