I have a custom tableview cell with a UIWebView contained in it. The UIWebView content is large, so I have the cell expanding on tap. When the cell is collapsed I am fading the bottom of the cell to show the content is truncated.
To determine whether I should fade the cell content I am comparing the height of the cell with the height of the webview content within layoutSubviews().
This works the first time the cell is displayed.
When I tap to expand the fade out is removed. Good so far.
Now when I collapse the cell, the height reported in layoutSubviews() for the webview comes back correctly once, but it is immediately followed by a second call to layoutSubviews() which reports the height of the webview as the same size as the collapsed cell. This stops causes the cell fade that was just added to be removed.
I have inspected the cell with the view debugger and it reports the correct height for the webview.
How can I reliably get the height of the webview?
Here is my code from the custom cell:
- (void)layoutSubviews
{
[super layoutSubviews];
if (gradientLayer != nil) {
[gradientLayer removeFromSuperlayer];
gradientLayer = nil;
}
// if cell height is less than web view height we must fade
if (self.frame.size.height < self.webView.bounds.size.height) {
gradientLayer = [CAGradientLayer layer];
NSObject* fadeColor = (NSObject*)[UIColor colorWithWhite:1.0 alpha:.9].CGColor;
NSObject* transparentColor = (NSObject*)[UIColor colorWithWhite:1.0 alpha:0.0].CGColor;
gradientLayer.colors = [NSArray arrayWithObjects:transparentColor, fadeColor, nil];
gradientLayer.locations = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.5],
[NSNumber numberWithFloat:1.0], nil];
gradientLayer.bounds = self.bounds;
gradientLayer.anchorPoint = CGPointZero;
[self.layer addSublayer:gradientLayer];
}
}
I had a rounded UIButton in a custom table view cell initialized via a XIB, and it was working fine. I just noticed that the border, a circular pink border, now doesn't appear. I tried adding some code to also set the property in the awakeFromNib function, but this also didn't do the trick.
- (void)awakeFromNib {
[super awakeFromNib];
[self setupProfileView];
self.contentView.backgroundColor = [UIColor colorWithWhite:0.97f alpha:1.0f];
self.selectionStyle = UITableViewCellSelectionStyleNone;
_initialLabel.layer.cornerRadius = _initialLabel.frame.size.width/2;
_initialLabel.layer.borderWidth = 2;
_initialLabel.layer.borderColor = [UIColor colorWithRed:223.0/255.0 green:158.0/255.0 blue:255.0/255.0 alpha:1].CGColor;
NSLog(#"on profile table view cell border width is %f and radius is %f and color is %#", _initialLabel.layer.cornerRadius, _initialLabel.layer.borderWidth, _initialLabel.layer.borderColor);
}
The above prints out what I would expect (the correct color + radius + width), but it doesn't show in the view. It's the only reference in code to _initialLabel, so it's not getting set somewhere else in code.
Has anyone run into this and know a fix? Any ideas how to troubleshoot this further?
I need to implement this left margin for the background of the cell.
Now I tried to do it this way - but the result is not correct - the content of the cell is moving with the margin. How can I solve an issue?
CGRect layerFrame = self.layer.frame;
layerFrame.size.width -= kRightLayerMargin;
layerFrame.origin.x += kLeftLayerMargin;
self.layer.frame = layerFrame;
self.layer.backgroundColor = [[SCUtils cellSelectionColor] CGColor];
self.layer.cornerRadius = 10.0f;
Implement your cell's layoutSubviews method as follows:
- (void)layoutSubviews {
//have the cell layout normally
[super layoutSubviews];
//get the bounding rectangle that defines the position and size of the textLabel
CGRect textLabelFrame = [[self textLabel] frame];
//anchor it to the top-left corner
textLabelFrame.origin = CGPointMake(kLeftLayerMargin, textLabelFrame.origin.y);
//set the textLabel frame (this will move+resize it)
[[self textLabel] setFrame:textLabelFrame];
//reposition the other controls accordingly
}
I have a UITableView with grouped style and UITableViewCell, which I need to make a little bit wider. So, I subclassing the UITableViewCell and implement there a method:
- (void) layoutSubviews
{
[super layoutSubviews];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad && !IS_OS_7_OR_LATER) {
CGRect frame = self.frame;
frame.origin.x -= 10;
frame.size.width += 20;
self.frame = frame;
}
}
Now there is a problem - my cell looks like this:
and with colour layers on:
In the top of the cell there is a part of the bounds of the previous cell before resizing.. This you can see much clearly on the second screen. Can you help me how to remove this border?
UIView *backgroundView = [[UIView alloc] initWithFrame:cell.bounds];
backgroundView.backgroundColor = [UIColor colorWithRed:240 green:240 blue:240 alpha:1];
cell.backgroundView = backgroundView;
have a try.
I'm using UICollectionView to lay out a bunch of cells that are sectioned by first letter of their title. Each cell should have a very thin border around it, and the section headers should have borders above and below. Here's my current prototype:
I achieve the current appearance with the following rules:
Stroke the right and bottom edge of each cell.
Stroke the bottom edge of each section heading.
This is very close to what I want, but there are two defects:
If the line before a section heading isn't full, then the border along the top of the heading stops short of the right edge of the screen.
It's not visible in this screenshot, but if a line is full, the right border of the last cell in the line is still drawn, which looks a little odd against the edge of the screen.
My best idea to fix this is to somehow tell each cell if it's in the last row of a section or the last cell in a row; then the cell would turn off the offending borders, section headings would draw a top border as well as a bottom, and everything would be hunky-dory. I don't know how to achieve that, though.
Any thoughts on how to manage that, or another way to get the look I'm going for? I'm currently using a UICollectionViewFlowLayout.
I ended up subclassing UICollectionViewFlowLayout and applying several heuristics after the flow layout had calculated the attributes for each cell:
If center.y is equal to center.y of the last item in the section, the cell is in the last row of the section.
If CGRectGetMaxY(frame) is equal to CGRectGetMaxY(self.collectionView.bounds), then the cell is agains the right edge of the collection view.
I then stored the results of these calculations in a subclass of UICollectionViewLayoutAttributes, and wrote a UICollectionViewCell subclass whose -applyLayoutAttributes: method would adjust the borders its background view draws based on the additional properties.
I've put the whole mess into a fairly enormous gist so you can see exactly what I did. Happy hacking.
My best idea to fix this is to somehow tell each cell if it's in the last row of a section or the last cell in a row; then the cell would turn off the offending borders, section headings would draw a top border as well as a bottom, and everything would be hunky-dory. I don't know how to achieve that, though.
What you describe is more or less what I did in a similar scenario. I added a border property to my cell:
typedef NS_OPTIONS(NSInteger, TLGridBorder) {
TLGridBorderNone = 0,
TLGridBorderTop = 1 << 0,
TLGridBorderRight = 1 << 1,
TLGridBorderBottom = 1 << 2,
TLGridBorderLeft = 1 << 3,
TLGridBorderAll = TLGridBorderTop | TLGridBorderRight | TLGridBorderBottom | TLGridBorderLeft,
};
#interface TLGridCellView : UIView
#property (nonatomic) TLGridBorder border;
#end
Then I set the border in my view controller's cell configuration:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
TLGridCellView *cell = ...;
if (indexPath.item == self collectionView:collectionView numberOfItemsInSection:indexPath.section - 1) {
cell.border = TLGridBorderLeft;
} else {
cell.border = TLGridBorderLeft | TLGridBorderRight;
}
return cell;
}
I solve this problem in a simple way. I didn't add boarder to cell, instead I add a label with boarder into the cell. For the first column, the frame of the label is the same with the cell. For the other label, I set the x coordinate -0.5 to make their boarder overlap. Hope it helps.
Here is the code:
- (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
// Then use it
UILabel *label = nil;
if (cell.contentView.subviews.count > 0) {
label = cell.contentView.subviews[0];
} else {
label = [[UILabel alloc] init];
}
label.text = #"北京";
[label setTextAlignment:NSTextAlignmentCenter];
[label setFont:[UIFont systemFontOfSize:14]];
[label setCenter:cell.contentView.center];
CGRect frame = label.frame;
if (indexPath.row%4 == 0) {
frame.origin.x = 0;
} else {
frame.origin.x = -0.5;
}
frame.origin.y = 0;
frame.size.width = self.collectionView.frame.size.width / 4;
frame.size.height = self.collectionView.frame.size.height / 9;
[label setFrame:frame];
if (cell.contentView.subviews.count == 0) {
[[cell contentView] addSubview:label];
}
label.layer.borderWidth = 0.5;
label.layer.borderColor = [[UIColor lightGrayColor] CGColor];
cell.backgroundColor = [UIColor whiteColor];
return cell;
}