For my application's contact view, I have added individual users image based on his email id in an table view. Because of difference in image size of each user, image view is not unique for all user, some image view's width is more, So I set the frame size of UItableViewCell with fixed width, still the width size varies.
[cell.imageView setFrame:CGRectMake(0, 0, 55, 55)];
What should I do? Do I need to add new image view as subview for cell? Any idea?
UITableView's imageView property is read-only. You can resize your image before setting to your cell's imageView. To resize the image, you can get help from this StackOverflow answer.
Also, if you are loading your images from a web environment, you can use my fork of AFNetworking, I added image resizing options into the UIImageView extensions. https://github.com/polatolu/AFNetworking
You should set your imageview's property in order to display different images for different size.
For Example,
<imageview_name>.contentMode = UIViewContentModeScaleAspectFit;
Enjoy Programming!
I'm using the same JSON file to fill a UITableView, and here is what I'm using for a universal app in CustomCell:
- (void)layoutSubviews {
[super layoutSubviews];
if (UI_USER_INTERFACE_IDIOM()== UIUserInterfaceIdiomPad) {
self.imageView.frame = CGRectMake(0,0,300,100);
}else if (UI_USER_INTERFACE_IDIOM()== UIUserInterfaceIdiomPhone){
self.imageView.frame = CGRectMake(0,0,180,60);
}
float limgW = self.imageView.image.size.width;
if(limgW > 0) {
if (UI_USER_INTERFACE_IDIOM()== UIUserInterfaceIdiomPad) {
self.textLabel.frame = CGRectMake(320,self.textLabel.frame.origin.y,self.textLabel.frame.size.width,self.textLabel.frame.size.height);
}else if (UI_USER_INTERFACE_IDIOM()== UIUserInterfaceIdiomPhone){
self.textLabel.frame = CGRectMake(182,self.textLabel.frame.origin.y,self.textLabel.frame.size.width,self.textLabel.frame.size.height);
}
}
}
Subclass UITableViewCell and override this method;
- (void)layoutSubviews {
[super layoutSubviews];
self.imageView.frame = CGRectMake(0,0,55,55);
//Any additional setting that you want to do with image view
[self.imageView setAutoresizingMask:UIViewAutoresizingNone];
}
Related
I would like to know the best way/correct way to achieve from following layout? I want to place an UIImageView outside of UITableViewCell in a UITableView with static cells.
I have done the following by subclassing UITableViewCell for the cells in section 1 using the following code
- (void)setFrame:(CGRect)frame {
frame.size.width -= 125.0;
[super setFrame:frame];
}
In the UITableViewController's viewDidLoad I add the UIImageView and position it according to the width of the custom UITableViewCell.
This sort of works, but i'm not sure how to deal with rotation and also if what i've done so far would be the correct way?
there are differnt ways to do it. one is to set the width of table view less as you showd in pic 2nd is to use custom table view cell and on required cell add image so that your cell data as well as image will be shown. i think custom cell would be the better solution. tell me if you are asking the same thing what i answered, if no, then i review my answer thank.
I managed to produce what I wanted using the follow, this is proberly not the best way or cleanest way but as no one from StackOverFlow gave any better suggestions I thought I better answer this.
I subclassed the first 3 UITableViewCells and set a frame size to take into account the size of my image.
- (void)setFrame:(CGRect)frame {
float cellWidth = (frame.size.width - 345);
frame.size.width = cellWidth;
[super setFrame:frame];
}
Then in my UITableViewController's viewDidLoad I create and position the UIImageView using the first static cell in the tableview as an IBOutlet ("firstCell"). I then set the autoResizingMask which sorts out rotation and finally add the UIImageView to the view.
//Create and position the image view
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake((firstCell.frame.size.width), (firstCell.frame.origin.y + 70), 300, 137)];
// Add border and round corners of image view to make style look a little like tableviewcells
[imageView.layer setBorderColor:[UIColor colorWithWhite:0 alpha:0.5].CGColor];
[imageView.layer setBorderWidth:2.0];
[imageView.layer setCornerRadius:5.0];
[imageView setClipsToBounds:YES];
//Set the image in the image view
UIImage *image = [UIImage imageNamed:#"defaultPicture.png"];
imageView.image = image;
//Set resizing of image view for when view is rotated
imageView.contentMode = UIViewContentModeRedraw;
imageView.autoresizingMask = UIViewContentModeScaleAspectFit;
//Add tap gesture for imageview to initiate taking picture.
imageView.userInteractionEnabled = YES;
UITapGestureRecognizer *imageViewTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(takePicture:)];
[imageView addGestureRecognizer:imageViewTap];
//Add image view to view
[self.view addSubview:imageView];
This has not been fully tested and i'm sure isn't a great implementation, but its a starting point for the effect i'm after. Please reply if you know of a better way.
Note: The above code is written for my app on the iPad but screenshots are from testing I did on iPhone
On a UITableViewCell with UITableViewCellStyleSubtitle styling, I'm setting the imageView.image, textLabel.text, and detailTextLabel.text. There's white padding all around the cell. How do I get rid of the padding so all my images touch each other like the Youtube app below?
Probably the easiest way to do this would be to subclass UITableViewCell and override the -layoutSubviews method to do something like this:
- (void)layoutSubviews {
//have the cell layout normally
[super layoutSubviews];
//get the bounding rectangle that defines the position and size of the image
CGRect imgFrame = [[self imageView] frame];
//anchor it to the top-left corner
imgFrame.origin = CGPointZero;
//change the height to be the height of the cell
imgFrame.size.height = [self frame].size.height;
//change the width to be the same as the height
imgFrame.size.width = imgFrame.size.height;
//set the imageView's frame (this will move+resize it)
[[self imageView] setFrame:imgFrame];
//reposition the other labels accordingly
}
Just remove table separator:
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
In iOS8 you can set
tableView.layoutMargins = UIEdgeInsets.zero
in code, or from Interface Builder.
Try reducing the UITableView's row height in interface builder or code so that there is no padding.
I had to increase the padding i did so in the interface builder for the tableview.
However Daves answer might give you more control over modifying the cell view.
I am trying to create a table view which has a layout like what yobongo has:
and what I have now is really crappy, where the UIImage has different size, etc, etc...
How do I fix it to have something nice like that? I tried rearranging via IB but then mine looks like this:
I wanted to create a UIImage in the cell that has a fixed size (mine resizes here and there). How do I set that? I also want a rounded edge around the UIIMage... I have played around with the spring and struts via IB and I think I might have messed up something that I can't fix again..
I also want so that there exists a gap between rows and a border like in the picture below
I also wanted to implement a chat box like below where it expands if the text is more than it's limit. How can I do this?
Fixed image size
You have to set UIImageView frame for all image views. And then you have to play with UIImageView's contentMode property - where you can scale image to fit frame, fill frame, keep aspect ratio, etc. And you also have to set clipsToBounds to YES to clip "overlapping" image parts.
Round Corners
You can use CALayer for this, which is also available in UIImageView. It's matter of four lines ...
imageView.layer.cornerRadius = 3.0;
imageView.layer.masksToBounds = YES;
imageView.layer.borderColor = [UIColor blackColor].CGColor;
imageView.layer.borderWidth = 1.0;
Example:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier];
if ( self ) {
...
self.imageView.layer.cornerRadius = 3.0;
self.imageView.layer.masksToBounds = YES;
self.imageView.layer.borderColor = [UIColor blackColor].CGColor;
self.imageView.layer.borderWidth = 1.0;
...
}
return self;
}
Expandable Text Input
You have to prepare good background image for this. And then you can create stretchable image via UIImage class method: – stretchableImageWithLeftCapWidth:topCapHeight:
Each row will be subclassed UITableViewCell where you can handle all these things. Stretchable background, etc. Resizing via UITextView's delegate (textViewDidChange:), etc.
Google for some examples or search SO.
Gaps
UITableViewDelegate has method ...
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
... where you can specify row height. To create gap, add this to your custom cell ...
Header:
UIImageView *__backgroundImageView;
Initializer:
__backgroundImageView = [[UIImageView alloc] initWithImage:...stretchableImage...];
[self.contentView addSubview:__backgroundImageView];
[self.contentView sendSubviewToBack:__backgroundImageView];
Layouting:
- (void)layoutSubviews {
[super layoutSubviews];
// This draws background image over the whole cell and adds 5px gap top/bottom
CGRect rect = self.contentView.bounds;
rect.origin.y += 5; // Draw background image 5 pixels below cell top
rect.size.height -= 2 * 5; // Remove top/bottom gap from background image height
__backgroundImageView.frame = rect;
...
}
Memory Management:
- (void)dealloc {
[super dealloc];
[__backgroundImageView release]; __backgroundImage = nil;
...
}
If you want all images (of potentially different source sizes) to appear the same size in your UITableViewCell then you need to adjust the sizes of the images. The easiest way to do that is to use the ScaleToFill contentMode of your UIImageView, which will then do the work for you.
You can get rounded/bordered/colored corners on any view by doing this:
#import <QuartzCore/QuartzCore.h> // for layer.cornerRadius
...
self.comboTextView.layer.cornerRadius = 10.0;
self.comboTextView.layer.borderColor = [[UIColor grayColor] CGColor];
self.comboTextView.layer.borderWidth = 2;
Expanding TextView: I'd probably do this: implement the UITextViewDelegate function
- (void)textViewDidChange:(UITextView *)textView
then in that method get the textView.contentSize property, and set the textView.frame property to that size.
Create custom class that inherits from the UIView. Add ivar UIImageView* _img_v
Override setFrame:
-(void) setFrame:(CGRect) r {
[super setFrame: r];
if( _img_v.image && r.size.width*r.size.height ) {
CGSize isz = _img_v.image.size;
float sx = r.size.width/isz.width;
float sy = r.size.height/isz.height;
if( sx > sy ) {
sx = sy;
} else {
sy = sx;
}
CGRect img_frame = CGRectMake(0, 0, isz.width*sx, isz.height*sy);
img_frame.origin = CGPointMake((r.size.width - img_frame.size.width)/2.0, (r.size.height - img_frame.size.height)/2.0);
[_img_v setFrame: img_frame];
}
}
This won't crop the images, but you can also use scaleToFill for that.
I'd like to apply a margin to the UIImageView on the left of a plain old UITableViewCell (grouped style).
The only way I've found to do this (via here) is to resize the UIImage itself before attaching it to the UIImageView. If the image is smaller then the cell, it will be centred; leaving the desired margin as a side-effect.
Well, that works, but now my image is blurry because the 100 unit row height is not 100 pixels on an iPhone4, its 200. So I end up with a UIImage scaled to 90x90 pixels that produces a 90x90 unit (180x180 pixel) UIImageView image. Enter ugly blurriness.
So my question is: how do I achieve a margin around the imageView without over-downsampling my image?
(ideally without downsampling at all - I need to keep the original for later anyway).
I feel like I'm missing something obvious; I really don't want to implement a custom cell class just for this.
Thanks guys, I've come up with a 'solution' that doesn't require subclassing.
What I do is still downsample the image, but to the 2x size (180x180 from the example in the question).
Then, when I come to create the final UIImage from the processed CGImage I use:
UIImage: +(UIImage *)imageWithCGImage:(CGImageRef)imageRef scale:(CGFloat)scale orientation:(UIImageOrientation)orientation
and set scale: to 2. Now everything works. But I'm still creating duplicate images just to keep UIKit happy.
Implement this method in your UITableViewCell subclass
-(void) layoutSubviews
{
[super layoutSubviews];
self.imageView.frame = CGRectInset(self.imageView.frame, 5, 5);
}
Note: I haven't tested any of this, so it's possible that UITableViewCell will override some of these settings to lay its subviews out according to its own internal logic.
Have you tried just adjusting the image view's frame? Try this:
UITableViewCell * tableViewCell = [[[UITableViewCell alloc] init] autorelease];
tableViewCell.imageView.image = [UIImage imageNamed:#"table-view-image"];
CGRect imageViewFrame = tableViewCell.imageView.frame;
imageViewFrame.origin.x += 10.0f;
tableViewCell.imageView.frame = imageViewFrame;
That will just pad the image view 10 points more than its normal x coordinate. If you want to pad both sides, you can also set the contentMode property on the image view to UIViewContentModeCenter and adjust its width:
UITableViewCell * tableViewCell = [[[UITableViewCell alloc] init] autorelease];
tableViewCell.imageView.image = [UIImage imageNamed:#"table-view-image"];
tableViewCell.imageView.contentMode = UIViewContentModeCenter;
CGRect imageViewFrame = tableViewCell.imageView.frame;
imageViewFrame.size.width += 20.0f;
tableViewCell.imageView.frame = imageViewFrame;
That will make the image view 20 points wider, but because the content mode is set to center, the image will be drawn without stretching. If the dimensions of your image are right, this will effectively pad the image by 10 points on the left and right. However, you need to be aware that if you do this, the UIImage you provide must already be the exact dimensions to fit in the image view. contentMode's default setting is UIViewContentModeScaleToFill, so it will automatically scale images to fill the image view's frame. Setting it to UIViewContentModeCenter will no longer do this, but it will center the actual image.
In my case I used my own subclass inherited from UITableViewCell.
It's very clean and easier to use.
Also, I could use different sizes of image to be well resized for this cell.
The point is to use additional property that will replace regular imageView
1: In the subclass, I added a property mainImageView which can be used instead of imageView.
#property (nonatomic, retain) UIImageView *mainImageView;
2: Then in - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier.
I allocated and initialized mainImageView.
You can set any frame(rect) for mainImageView.
Add it as a subview to the contentView.
I used insetImageView to align it to the vertical middle of `contentView'.
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code.
mainImageView = [[UIImageView alloc] initWithFrame:frameCellMainImageView];
[self.contentView addSubview:mainImageView];
insetImageView = (sizeRowHeightTwoLinedDetail - frameCellMainImageView.size.height) / 2.0;
}
return self;
}
3: Override - (void)layoutSubviews to make sure other properties like textLabel, detailTextLabel set their frames to be well-situated with added property mainImageView
- (void)layoutSubviews {
[super layoutSubviews];
CGRect frameImageView = frameCellMainImageView;
frameImageView.origin.x = insetImageView;
frameImageView.origin.y = insetImageView;
[self.mainImageView setFrame:frameImageView];
// Use changed frame
frameImageView = self.mainImageView.frame;
CGFloat newLeftInset = frameImageView.size.width + insetImageView;
CGRect frameTextLabel = self.textLabel.frame;
CGRect frameDetailLabel = self.detailTextLabel.frame;
frameTextLabel.origin.x += newLeftInset;
frameDetailLabel.origin.x += newLeftInset;
CGFloat newTextWidth = 320.0;
newTextWidth -= newLeftInset;
newTextWidth -= insetImageView;
newTextWidth -= insetImageView;
frameTextLabel.size.width = newTextWidth;
frameDetailLabel.size.width = newTextWidth;
[self.textLabel setFrame:frameTextLabel];
[self.detailTextLabel setFrame:frameDetailLabel];
}
4: When using this cell in UITableDataSourceDelegate methods, use cell.mainImageView to receive messages, instead of regular cell.imageView
I'd like to have a gruped table where the first section has 2 row and 1 imageview like contacts app.
something like this: screeshot
How can I do that?
Thanks,
Max
The other solutions require you to create your own background images and use two tableviews which is not convenient. What I did was subclass UITableViewCell and indented the background views as such:
#define INDENT_WIDTH 84
...
- (void)layoutSubviews
{
[super layoutSubviews];
//Indent the background views.
CGRect frame = self.backgroundView.frame;
frame.origin.x = frame.origin.x + INDENT_WIDTH;
frame.size.width = frame.size.width - INDENT_WIDTH;
self.backgroundView.frame = frame;
self.selectedBackgroundView.frame = frame;
//Also indent the UIImageview that contains like a shadow image over the backgroundviews (in grouped tableview style only).
for (UIView *subview in self.subviews) {
if ([subview isKindOfClass:[UIImageView class]]) {
CGRect frame = subview.frame;
frame.origin.x = frame.origin.x + INDENT_WIDTH;
frame.size.width = frame.size.width - INDENT_WIDTH;
subview.frame = frame;
}
}
}
Since the content view has a transparent background color you can place a UIImageView (e.g on your storyboard cell prototype) on the left side and you should get the same effect as the "Add Contact" view in the Contacts App.
Please see this question:
Is it possible to adjust the width of a UITableViewCell?
It seems there's no convenient way to actually reduce the width of a cell (or cell group).
You can achieve the same in the screenshot by:
(1) A parent view controller with a view having a background color similar to that of a UITableViewStyleGrouped.
(2) Add the photo on a UIImageView which would be a subView to (1)
(3) Add the UITableView (Grouped Style) on the right side again as a subview to (1)
Set the frames of both subviews properly and accordingly for the layout in the screenshot and use delegation to "logically connect" both subviews.
Edit: The background color can be achieved using [UIColor colorWithPatternImage:(UIImage *)image]. Just crop the background from any sample app on the iphone simulator.