Is there a way to set the UITableViewCell.image to display on the right hand side of the cell instead of the left? Or will I need to add a separate UIImageView on the right side of the cell layout?
No. But you can easily add an image view as the accessory view to a table cell for the same effect.
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"foo.png"]];
cell.accessoryView = imageView;
[imageView release];
For simple cases you can do this:
cell.contentView.transform = CGAffineTransformMakeScale(-1,1);
cell.imageView.transform = CGAffineTransformMakeScale(-1,1);
cell.textLabel.transform = CGAffineTransformMakeScale(-1,1);
cell.textLabel.textAlignment = NSTextAlignmentRight; // optional
This will flip (mirror) the content view placing any imageView on the right. Note that you have to flip the imageView and any text labels also otherwise they themselves would be mirrored! This solution preserves the accessory view on the right.
Here is an example in Swift with the approach of using accessoryView:
private let reuseIdentifier: String = "your-cell-reuse-id"
// MARK: UITableViewDataSource
func tableView(tableView:UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell : UITableViewCell? = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier) as? UITableViewCell
if (cell == nil) {
cell = UITableViewCell(style:UITableViewCellStyle.Subtitle, reuseIdentifier:reuseIdentifier)
}
cell!.textLabel!.text = "Hello"
cell!.detailTextLabel!.text = "World"
cell!.accessoryView = UIImageView(image:UIImage(named:"YourImageName")!)
return cell!
}
If you don't want to make a custom cell and will work with standard one, you have as minimum two ways:
To use accessoryView.
cell.accessoryView = UIImageView(image: UIImage(named: "imageName"))
cell.accessoryView.frame = CGRectMake(0, 0, 22, 22)
If you want to have the right image + accessoryView, then you can add UIImageView outlet to ContentView (example name: rightImage) and change background color of textLabel as Clear.
cell.rightImage.image = UIImage(named: "imageName")
cell.textLabel.backgroundColor = UIColor.clearColor()
in swift3 and swift4, we can use this:
cell.accessoryView = UIImageView(image:UIImage(named:"imageNmae")!)
Subclass UITableViewCell and override layoutSubviews and then just adjust the frames of the self.textLabel, self.detailTextLabel and self.imageView views.
This is how it might look like in code:
MYTableViewCell.h:
#import <UIKit/UIKit.h>
#interface MYTableViewCell : UITableViewCell
#end
MYTableViewCell.m:
#import "MYTableViewCell.h"
#implementation MYTableViewCell
- (void)layoutSubviews
{
[super layoutSubviews];
if (self.imageView.image) {
self.imageView.frame = CGRectMake(CGRectGetWidth(self.contentView.bounds) - 32 - 8,
CGRectGetMidY(self.contentView.bounds) - 16.0f,
32,
32);
CGRect frame = self.textLabel.frame;
frame.origin.x = 8;
self.textLabel.frame = frame;
frame = self.detailTextLabel.frame;
frame.origin.x = 8;
self.detailTextLabel.frame = frame;
}
}
#end
To Add image # Right Hand side in the Cell, I would suggest you to create a Custom cell with imageview on right hand side , it will be very useful for you .
and add an empty view to link this nib with customcell class.
Now in your cell's nib file remove the view,add tableViewcell and in that cell drag & drop an imageView to right hand side.
Now go to the TableViewCell's class say DemoCell , create an outlet and set it with the imageview in the tablecell's nib
Now,in tableview's cellforrowatindexpath method reference your cell and use it with the nib name like this
static NSString *CellIdentifier = #"Cell";
DemoCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[SettingCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell = [[[NSBundle mainBundle]loadNibNamed:#"DemoCell" owner:self options:nil] lastObject];
}
and set the image as per your requirement
cell.imageVw.img ....
You can resize image in the accessoryview by calling setFrame method of imageview like this: [imageView setFrame:CGRectMake(0, 0, 35.0, 35.0)];
This Soln is for adding different image in each cell....Just a Try
// Customize the appearance of table view cells.
- (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];
}
if(indexPath.row == 0) {
cell.image = [UIImage imageNamed:#"image.png"];
}
else if (indexPath.row == 1) {
cell.image = [UIImage imageNamed:#"image1.png"];
}
It's unnecessary to create your own image, just edit cell.tintColor.
There is a way to set the position programmatically. Here is the Swift version of the solution:
image.frame = CGRect.init(
x: self.view.frame.width - image.frame.width*1.1,
y: image.frame.origin.y,
width: image.frame.width,
height: image.frame.height)
This will position your image on the right side of the cell.
This solution is adjusting automatically the position according to screen size.
The only down side is when you rotate the device you need to reload your data, but you can just override in your UITableView class the didRotate listener method:
override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
_tableView.reloadData()}
Related
I am adding label to uiimage and then adding that image on uitable view. but it is not showing. Can anyone help please?
This is code i am using:
- (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];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
//image which contains label
UIImageView *BgImage=[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"cell-bg.png"]];
BgImage.frame=cell.frame;
//label which will be on image
UILabel *NameLAbel=[[UILabel alloc]initWithFrame:CGRectMake(25, 5, 45, 45)];
NameLAbel.textColor=[UIColor blackColor];
if (indexPath.row==0) {
NameLAbel.text=#"Home";
}
else if (indexPath.row==1) {
NameLAbel.text=#"You";
}
else if (indexPath.row==2) {
NameLAbel.text=#"Contacts";
}
else if (indexPath.row==3) {
NameLAbel.text=#"Settings";
}
else {
NameLAbel.text=#"Sign Out";
}
NSLog(#"%#",NameLAbel.text);
[BgImage addSubview:NameLAbel];
//adding image on cell
[cell.contentView addSubview:BgImage];
[NameLAbel release];
[BgImage release];
return cell;
}
I'm not sure if you can actually add a UILabel to an UIImageView, although they are both UIView subclasses, I think the imageview will only display the image.
try adding the label to cell.contentView after you've added the image to the view. That should achieve the affect you are after.
Either that, or create of UIView which will hold both the UIImageView and the UILabel
Adding some UI widget as a subview of a UIImageView sounds really questionable. Even if it works now it may not work in the future, and I believe this breaks the UIKit convention. If you want to make one view look like it is "part of" another view, place the two as siblings, either directly in the cell.contentView as Amit noted, or if you want clipping so that the label looked like it was being clipped by the image, create a UIView container, enable the "clip subviews" setting of that view, and place the UIImageView and UILabel as siblings within that container UIView.
when adding an image to table cell, as default it goes to left:
cell.imageView.image = [UIImage imageNamed:[arrImages objectAtIndex:indexPath.row]];
how can I change it that every image in the UITableViewCell will go automaticlly to the right and the textLabel will be 10px to the left of the image.
Thanks alot!
Another way is to create a custom cell and override layoutSubviews method.
#interface CustomCell : UITableViewCell
#end
#implementation CustomCell
- (void)layoutSubviews
{
[super layoutSubviews];
// grab bound for contentView
CGRect contentViewBound = self.contentView.bounds;
// grab the frame for the imageView
CGRect imageViewFrame = self.imageView.frame;
// change x position
imageViewFrame.origin.x = contentViewBound.size.width - imageViewFrame.size.width;
// assign the new frame
self.imageView.frame = imageViewFrame;
}
#end
Rembember that in cellForRowAtIndexPath you need to create and reuse CustomCell and not UITableViewCell.
Hope it helps.
Edit
#import "CustomCell.h"
// other code here...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
return cell;
}
Find the solution here code.
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"foo.png"]];
cell.accessoryView = imageView;
For your reference.
UITableViewCell with image on the right?
try this:
cell.imageView.frame = CGRectMake(cell.frame.size.width - cell.imageView.frame.size.width, cell.imageView.frame.origin.y, cell.imageView.frame.size.width, cell.imageView.frame.size.height);
[cell.yourTexLabel sizeToFit];
cell.yourTexLabel.frame = CGRectMake(cell.imageView.origin.x - cell.yourTexLabel.frame.size.width - 10, cell.yourTexLabel.frame.origin.y, cell.yourTexLabel.frame.size.width, cell.yourTexLabel.frame.size.height);
Found a better answer from #TomSwift here https://stackoverflow.com/a/31616694/1884707
cell.contentView.transform = CGAffineTransformMakeScale(-1,1);
cell.imageView.transform = CGAffineTransformMakeScale(-1,1);
cell.textLabel.transform = CGAffineTransformMakeScale(-1,1);
cell.textLabel.textAlignment = NSTextAlignmentRight;
By applying a transform on the contentView you can place the imageView on the right.
in swift3 and swift4, we can use this:
cell.accessoryView = UIImageView(image:UIImage(named:"imageNmae")!)
One solution is to use a custom UITableViewCell. The steps are:
Create a new objective-C class that is a subclass of UITableViewCell, for example LabeledImageTableViewCell. Declare ivars and properties for a UILabel and a UIImageView.
In Interface Builder, set the content of the UITableView to Dynamic Prototypes. Drag a UIImageView and a UILabel to a table view cell and position them. Set the cell's class to LabeledImageTableViewCell. Connect the outlets of the cell to the UILabel & UIImageView objects of LabeledImageTableViewCell.
In the delegate for UITableView (usually a UITableViewController, sometimes a UIViewController) implement the datasource methods, for example:
//#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return (NSInteger)[rowData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"tvcLabeledImage";
LabeledImageTableViewCell *cell = (LabeledImageTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[LNCCorrelationInfoTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.myImage = [UIImage imageNamed:#"imageForThisRow.png"];
cell.myLabel = "imageForThisRow";
return cell;
}
Also, check out the Apple videos from WWDC 2011, UITableView Changes, Tips & Tricks and Introducing Interface Builder Storyboarding (Login required: https://developer.apple.com/videos/wwdc/2011/.)
I want to have my text in my UITableViewCell to be a little bit to the right. In other words I want to have an x-offset. Is this even possble? Do I have to create a custom cell just because of this?
You could use cell.indentationLevel and if needed cell.indentationWidth instead of custom UITableViewCell for this.
You can try this :
[cell setIndentationLevel:SOME_NUMBER];
[cell setIndentationWidth:SOME_OTHER_NUMBER];
A simple solution is you can change the frame of the textLabel.
CGRect textLabelFrame = cell.textLabel.frame;
textLabelFrame.origin.x += xOffset;
textLabelFrame.size.width -= xOffset;
cell.textLabel.frame = textLabelFrame;
I've also done this by creating a custom UILabel that supports edgeInsets similar to a UIButton. This is a better solution b/c you can layout the label to correct size but the above will work if you have simple needs.
[EDIT 1/2: fixed typo w/ CGRect]
[EDIT 3: fixed typo setting modified frame]
[EDIT 4: need a simple subclass]
Mea culpa. I was wrong that you can do this in tableView:cellForRowAtIndexPath. The UITableViewCell layout happens after the tableView delegate/datasource has a chance to customize the cell. I've tested the implementation below, it works.
Do as I say above but create a (simple) subclass of UITableViewCell that adds the xOffset in layoutSubviews. If you do this, you can also add an xOffset property that you can set in tableView:cellForRowAtIndexPath:.
#implementation XOffsetCell
// assumes property xOffset is defined and synthesized
- (void) layoutSubviews
{
[super layoutSubviews];
CGRect textLabelFrame = cell.textLabel.frame;
textLabelFrame.origin.x += self.xOffset;
textLabelFrame.size.width -= self.xOffset;
cell.textLabel.frame = textLabelFrame;
}
#end
The solution that suggested adding a custom UILabel to cell.contentView is also a good solution. I saw your comment that it obscures the built-in textLabel but that's the whole point. You would not use the built-in label anymore, use the custom label instead.
I'm not trolling for votes, but wanted to show what the code provided by #iPhone monster "should" look like. His solution is a valid option. If you add the label to the cell after the if (cell == nil) as he did you will be continually adding labels to dequeued cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(50.0f, 10.0f, 150.0f, 20.0f)];
lbl.tag = OffsetLabelTag; // define this as a constant
[cell.contentView addSubview:lbl];
[lbl release];
}
UILabel *lbl = (UILabel *)[cell.contentView viewWithTag:OffsetLabelTag];
[lbl setText:#"test text"];
return cell;
}
You can do that with Autolayouts:
UITableViewCell *cell = [UITableViewCell new];
cell.textLabel.translatesAutoresizingMaskIntoConstraints = NO;
[cell.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(indentation)-[textLabel]-(indentation)-|"
options:0
metrics:#{#"indentation": #35}
views:#{#"textLabel": cell.textLabel}]];
Or using Parus lib:
[cell.contentView addConstraints:(PVVFL(#"H:|-(indentation)-[textLabel]-(indentation)-|")
.withViews(#{#"textLabel": textLabel})
.metrics(#{#"indentation": #35}).asArray)];
Other way:
- (NSInteger)tableView:(UITableView *)tableView
indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
return intOffset; // but is like '\t', not points
}
There is another not very pretty and smart way : ) Position of Label in TableViewCell depends on size of image assigned to cell.imageView.image property. So if you want your text to move right you can add several blank pixel columns to image in cell.
Based off of https://stackoverflow.com/a/5659826/1058199, here is a Swift version.
This works within the cell to ONLY move the textLabel to the right. Swift 5.4
override func layoutSubviews() {
super.layoutSubviews()
var textLabelFrame = self.textLabel?.frame
textLabelFrame?.origin.x += 32
textLabelFrame?.size.width -= 32
self.textLabel?.frame = textLabelFrame ?? CGRect.zero
}
Will cell.textLabel.textAlignment = UITextAlignmentCenter; be enough for you. It could align the text to the center creating that space for you
I am adding my own UILabels to the contentView of a UITableViewCell because I need more control over the layout than the default UITableViewCellStyles provide. In essence I want the detailLabel have priority over the textLabel so the textLabel gets truncated.
I have the following code in my UITableViewController:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * const kCellIdentifier = #"CustomCell";
UITableViewCell * cell =
[tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
UILabel * titleLabel, * dateLabel;
if(cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:kCellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
titleLabel = [[[UILabel alloc] init] autorelease];
titleLabel.tag = kTitleLabelTag;
titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
dateLabel = [[[UILabel alloc] init] autorelease];
dateLabel.tag = kDateLabelTag;
dateLabel.textColor = [UIColor blueColor];
dateLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
[cell.contentView addSubview:titleLabel];
[cell.contentView addSubview:dateLabel];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)pCell
atIndexPath:(NSIndexPath *)pIndexPath
{
const float kHeight = 44.0, kLeftIndent = 8.0, kOverallWidth = 293.0,
kGap = 1.0;
UILabel * titleLabel, * dateLabel;
titleLabel = (UILabel *)[pCell.contentView viewWithTag:kTitleLabelTag];
dateLabel = (UILabel *)[pCell.contentView viewWithTag:kDateLabelTag];
NSString * dateText = #"9:39 AM";
// Calculate the size of dateLabel
CGSize dateSize = [dateText sizeWithFont:[dateLabel font]
constrainedToSize:CGSizeMake(kOverallWidth, kHeight)];
const float dateXPos = kOverallWidth - dateSize.width;
dateLabel.frame = CGRectMake(dateXPos, 0.0, dateSize.width, kHeight);
titleLabel.frame = CGRectMake(kLeftIndent, 0.0,
dateXPos - kLeftIndent - kGap, kHeight);
titleLabel.text = #"Some potentially very long text which will be wrapped.";
dateLabel.text = dateText;
pCell.contentView.backgroundColor = [UIColor purpleColor];
}
The code above produces incorrect results. When the table view is initially shown, it looks like figure 1) in this image of the renderings.
So there is a unwanted gap on the right of all the dateLabels. (the purple background is just for better visibility what is going on)
When dragging the tableview up like in 2) in the image, it then bounces back and looks like 3).
The first row has now exactly the layout I wanted and which calculated in configureCell:atIndexPath:. I guess this behavior happens because the cells get re-used and then configured again.
So it feels like I am missing some kind of initialization, I have tried calling setNeedsLayout and layoutSubviews of pCell and pCell.contentView but never achieved an initial correct rendering.
Only when I set the autoresizingMask of titleLabel and dateLabel to UIViewAutoresizingNone I get a correct initial rendering, then however the swipe to delete does not work because the delete button gets rendered over the dateLabel.
What do I have to change in my code so that all cells get rendered initially like the first cell in the third picture?
Thanks!
PS: I would like to have inlined the pictures but unfortunately I do not have enough reputation for that.
A good, and maybe simpler way to do this is to:
First Create a custom UITableViewCell subclass which you can setup using Interface Builder. If "MyTableViewCell" is your custom cell view you initialize it in CellForRowAtIndexPath like this:
MyTableViewCellClass *cell = (MyTableViewCellClass *)[tableView dequeueReusableCellWithIdentifier:#"MyTableViewCellClass"] autorelease];
if (!cell)
cell = [[[MyTableViewCellClass alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyTableViewCellClass"] autorelease];
// Call specific methods on your cell to pass information to it, not for display
[cell setProperties:...];
Then implement the layoutSubviews method in your custom UITableViewCell subclass. For instance:
-(void) layoutSubviews
{
// You must call this first to make sure your cell gets current parent information
[super layoutSubviews];
// Retrieve the content view bounds. This will include the edit symbols when present (delete button and ordering symbol
float inset = 5.0;
CGRect bounds = [[self contentView] bounds];
// Keep on going here with your own view layout.
}
Doing this you basically separate the cell model (CellForRowAtIndexPath) from the cell view (your custom implementation of cell drawing). If you later change the implementation (layout) of your cell you can do this easily simply by changing your cell layout without worrying about the CellForRowAtIndexPath method.
If you work with a storyboard , you should disable the "Use Auto Layout" in the File Inspector!
Then set the cell's property autoresizesSubviews
- (void)awakeFromNib
{
// Initialization code
self.autoresizesSubviews=YES;
}
The final step is configure the frame of the Label , overriding the method layoutSubviews of the UITableViewCell class
-(void)layoutSubviews{
[super layoutSubviews];
CGFloat top=VerticalPadding;
CGFloat left=HorizentalPadding;
CGFloat width=CGRectGetWidth(self.frame)-2*HorizentalPadding;
CGFloat height=CGRectGetHeight(self.frame)-2*VerticalPadding;
CGRect rect=CGRectMake(left, top, width, height);
self.Label.frame=rect;
}
I try to change the with of a cell in a tableview, I don't do a custom cell, I just subclass uitableviewcell.
This is the class
#implementation customCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier]) {
CGRect nouveauframe = CGRectMake(0.0, 0.0, 44,44);
self.frame = nouveauframe;
}
return self;
}
-(void)dealloc
{
[super dealloc];
}
#end
and this is when I create my cell in the cellForRowAtIndexPath:
static NSString *CellIdentifier = #"customCell";
customCell *cell = (customCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[customCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
[[cell textLabel]setText:[[[[Mission singletonMission] getObjectDataHistoireEncours] objectAtIndex:indexPath.row] valueForKey:[[langue singletonLangue] valeurBalise: #"_nom_label"]]];
cell.detailTextLabel.text = [[[[Mission singletonMission] getObjectDataHistoireEncours] objectAtIndex:indexPath.row] valueForKey:[[langue singletonLangue] valeurBalise: #"_valeur"]];
cell.userInteractionEnabled = FALSE;
retour = [cell retain];
but the width of my cell don't change, why?
Table views change the frame of cells when they are added to the table view. If you want to change the width of a cell, you should either change the width of the table, or change the width of the contentView in the cell.
If you want to change the height of the cell the implement the delegate method tableView:heightForRowAtIndexPath:.
If you want to change the width then you should only change it visually (set transparent background for all cell's subviews except the ones that shouldn't be) or, if all the cells should have the same width, you might change the entire table view's width, as #Jerry Jones has advised...