I'm trying to set a stretched background picture on the back of a UITableViewCell.
It's a common question, answered many times, so I'm doing it the "standard way" :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
UIImage* bgImg;
bgImg = [[UIImage imageNamed:#"menu_bg_selected.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 1, 0)]; //top/left/bottom/right
cell = [tableView dequeueReusableCellWithIdentifier:#"mycell" forIndexPath:indexPath];
[cell setBackgroundView:[[UIImageView alloc] initWithImage:bgImg]];
return cell;
}
If I simply try this, I obtain a tiled background.
After reading several similar questions/answers, I did try :
Forcing scale of the background View : cell.backgroundView.contentMode = UIViewContentModeScaleToFill;
Force resizing of background view : cell.backgroundView.clipsToBounds = YES;
Set autoresize of the mask : cell.backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Trying for force the frame size of the background UIImageView
It appears that my background picture is partially stretched up to a predetermined size, then tiled (not enough reputation yet to upload images, sorry ...) :
vertical stretch is partial and doesn't use full height
horizontal stretch is partial and doesn't use full width
The background picture is a 6x3 pixels image (with a blue vertical line on the left, a dark gray back and a light gray horizontal line at the bottom).
What am I doing wrong ?
Thanks for your help !
[Edit]
In fact the problem doesn't seems to be a UIEdgeInsetsMake problem.
When using bgImg = [UIImage imageNamed:#"menu_bg_selected.png"]; the background image is still not filling the complete cell background.
This code will work for UIImage.
UIIMage *bgImage = [[UIImage imageNamed:#"menu_bg_selected.png"] stretchableImageWithLeftCapWidth:15 topCapHeight:15];
I believe the problem comes from
UIEdgeInsetsMake(0, 5, 1, 0)
Basically you say i want a stretchable image but i don't want the bottom line to stretch neither the left border. That does not make any sense. Your edge insets must leave some stretchable parts. For instance if your image is 6x3 you could have :
UIEdgeInsetsMake(1, 2, 1, 2)
However you might want to redesign your image before.
Allright, I got it !
The problem was that my background picture was only partially stretched and then tiled in order to fill the complete cell (whatever the UIEdgeInsetsMake parameter was).
I succeeded by using : resizableImageWithCapInsets and specifying the resizingMode argument.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
UIImage* bgImg;
bgImg = [[UIImage imageNamed:#"menu_bg_selected.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 1, 0) resizingMode:UIImageResizingModeStretch];
cell = [tableView dequeueReusableCellWithIdentifier:#"mycell" forIndexPath:indexPath];
[cell setBackgroundView:[[UIImageView alloc] initWithImage:bgImg]];
return cell;
}
Thanks to all for your suggestions !
Related
I'm trying to put some images into a UITableView, so I put an Image View into the UITableViewCell and set it aspect fit.
After starting the simulator, it appears to be right, but when I click at one cell or scroll out the originally hidden cells(may be the reused ones), the image breaks the limit of the image view's setting and destroys the layout.
the middle picture is normal, but the upper or lower one is out of shape.
cellForRowAtIndexPath function as follow:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ShangbaoOriginCell";
ShangbaoOriginCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.newsSampleLabel.text = [NSString stringWithFormat:NSLocalizedString(#"Cell %d",), indexPath.row];
cell.cellView.contentMode = UIViewContentModeScaleAspectFit;
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
cell.imageView.image = self.tableItems[indexPath.row];
return cell;
}
whether cell.imageView.contentMode is set or not, this problem exists.
I've added bg color, ImageView is black, Content View is blue, Cell is green.
So I saw incredible thing, the (table view) cells become not wide enough (you can see from the narrow gap between two pictures). Which is set properly in story board that the cell's width cover the whole screen.
I forgot to say that this table view is in a tabbed application, but I think this doesn't matter . And this time I have added constraints to the image view, but in vain.
This is really a n00b question, I am learning iOS while trying to build an app
I need to show an image, label on UITableViewCell. The following code does that for me
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.imageView.image = [self getImageNameForRow:indexPath.row];
cell.textLabel.text = self.features[(NSUInteger) indexPath.row];
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
return cell;
}
The problem is that image size comes bigger that I expect. so I tried to increase the height of row as
self.tableView.rowHeight = 80;
But then the image also scales up.
How can I keep my image size fixed while increasing (or changing) the size of the row?
The problem is that you are using a default table view cell style. That style comes with a built-in textLabel and an imageView, and the latter is a UIImageView with constraints so that it is resized to fill the height of the cell. But you have also said
cell.imageView.contentMode = UIViewContentModeScaleAspectFit
Which means that as the image view grows, the image grows with it - exactly what you are seeing.
The solution, as I explain here, is to size the image down to the actual size that you want it - and set the image view's contentMode to center. Something like this:
UIImage* im = [self getImageNameForRow:indexPath.row];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(36,36), YES, 0);
[im drawInRect:CGRectMake(0,0,36,36)];
UIImage* im2 = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
cell.imageView.image = im2;
cell.imageView.contentMode = UIViewContentModeCenter;
Change that 36,36 to the size you actually want.
This is good practice anyway. It is a terrible waste of memory to hold onto an image at a larger size than needed for actual display (the amount of wasted memory grows exponentially, because area is on the order of the square of a single dimension). So you should always size images down to their actual display size. There's lots and lots of code on Stack Overflow showing many other ways to do that.
I believe your main problem here is the image is too large. If the image were only 40x40, it would appear as half the tableViewCell's height (when it's 80). IIRC the UIImageView in that UITableViewCell stretches to the height of the cell, and images will always fill it if they're large enough.
Three things you could do:
1) Shrink the size of the image to the size you want.
2) Change the frame of the imageView manually like so:
cell.imageView.image = [self getImageNameForRow:indexPath.row];
CGPoint center = cell.imageView.center;
CGRect frame = cell.imageView.frame;
frame.size.width = 40;
frame.size.height = 40;
cell.imageView.frame = frame;
cell.imageView.center = center;
I'm not entirely certain if you need to cache the center and re-set it after the frame change or not (the UITableViewCell might do this automatically).
3) Make a custom UITableViewCell subclass that has a fixed size UIImageView. I've detailed how to do this on my blog here.
I recommend 1 or 3.
Screenshot below shows one tableview cell in editing mode after swiping to the left on the row. While in editing mode I can hold the cell and drag further to the left again which reveals this white space (bouncy effect when I let go). I'm setting each cell's background image as follows:
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"CellBG.jpg"]];
I have 2 questions.
Is it possible to prevent this extra dragging so this white area will never be seen? Would like the same behaviour as the iOS7 weather app for example.
Also, any idea why there is thin white line under the delete button?
Thanks
Is it possible to prevent this extra dragging so this white area
will never be seen?
Yes. Put the image on the UITableView's background. Not on the cell. Because if you put the image background on a cell and when you horizontally swap a cell to delete, that cell will move. That is to say the image background will also move. But if you put it on the UITableView, it will not move with the swap. Remember to set UITableView and UITableViewCell's background color to be clear color.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ReuseIdentifier"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"cellBackground.png"]];
imageView.frame = CGRectMake(0, kCellHeight*indexPath.row, 320, cell.frame.size.height);
[tableView addSubview:imageView];
[tableView sendSubviewToBack:imageView];
return cell;
}
2.Also, any idea why there is thin white line under the delete button?
I think that is Apple's little bug. As you can also find it in the weather app. So never mind that.
I am attempting to obtain this result to get a TitleTextLabel|DescTextLabel with the line to break the two. Just like this example the homepage is divided from the URL field.
Can someone please point me in the right direction? I have read online / & the documentation but cannot find the right answer I'm looking for. I appreciate your help!
Thanks
There are a couple of ways I can think of to add that dividing line. You could override drawRect, and draw the line there. Another way that could be done wholly in IB, would be to add a 1 pixel wide label (with a light gray background an no text) in between the left and right labels. The left label should have a fixed width and constraints to the left side of the cell and to the 1 pixel wide label. The right label should just have constraints to the 1 pixel wide label and the right side of the cell (no fixed width). The 1 pixel wide label should have 0 length constraints to the top and bottom of the cell and a fixed width.
You need to draw that line on the cell manually.
1) Create UIView subclass called CellDividerView Override the -drawRect: method in the UIView subclass CellDividerView.m. The drawing code fills the entire rect with a solid color, dark gray in this case.
- (void)drawRect:(CGRect)rect
{
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
CGContextSetFillColorWithColor(currentContext, [UIColor lightGrayColor].CGColor);
CGContextFillRect(currentContext, rect);
CGContextRestoreGState(currentContext);
}
In the table view delegate's -tableView:cellForRowAtIndexPath: you create and init a CellDividerView with the frame positioned where you want it on the cell. In the code below it is positioned 40pts to the right, 0pts from the top, and it is 1pt wide and spans the entire cell height vertically. Next, this view is added to the cell's contentView.
#define CELL_VIEW_TAG 1234
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.detailTextLabel.text = [NSString stringWithFormat:#"Section %u", indexPath.section];
cell.textLabel.text = [NSString stringWithFormat:#"Row %u", indexPath.row];
// Configure the cell...
CellView *cellView = (CellView *)[cell.contentView viewWithTag:CELL_VIEW_TAG];
if (!cellView)
{
cellView = [[CellView alloc] initWithFrame:CGRectMake(40.0, 0.0, 1.0, cell.contentView.frame.size.height)];
[cell.contentView addSubview:cellView];
cellView.tag = CELL_VIEW_TAG;
}
return cell;
}
The result is something like this:
Using a custom cell style and adjusting the 40.0pt offset will allow you to accurately position the line where you want it.
It doesn't have the line dividing it by default, but try UITableViewCellStyleValue2
We had create a UITableviewController to list some contents,
We want an effect that the background image view will smoothly expand follow as the row's height changing, but we just got the effect with image changed to the final height of row.
the video is what we got:
http://www.youtube.com/watch?v=v-5TtrpYhl8
in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath, we just add a subview too the cell as below
UIImage *cellBackgroundImage = [UIImage imageNamed:#"cellbg.png"];
UIImageView *cellBackgroundImageView = [[UIImageView alloc] init];
[cellBackgroundImageView setImage:[cellBackgroundImage stretchableImageWithLeftCapWidth:10 topCapHeight:10]];
[cell addsubview:cellBackgroundImageView]
than just set height in the -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath like return 50 or return 250
But there obviously some fault around here, how can I fix it? I had google all around, and some apps do this kind of effect (like "DOOO"), I will appreciate you're answers!
we had try other methods like add UIImageView height changing in a custom UITableViewCell's layoutSubview method, that's work the same as the video above
Thank You for CSmith's answer, we had tried this method for background, but we found our problem is not on background, we'll keep finding our solution, but thank you~~ :)
Refer to UITableView cell with background image
cell.backgroundView = [[UIImageView alloc] initWithImage:[ [UIImage imageNamed:#"cellbg.png"] stretchableImageWithLeftCapWidth:10.0 topCapHeight:10.0] ];