I'm using this answer to create a gradient background for a table view cell
How to make gradient background in UITableViewCell in iOS?
-(void)addGradientBackgroundWithColor:(UIColor *)color {
if (!self.gradientLayer) {
self.gradientLayer = [CAGradientLayer layer];
self.gradientLayer.frame = self.bounds;
self.gradientLayer.startPoint = CGPointMake(0.0f, 0.5f);
self.gradientLayer.endPoint = CGPointMake(1.0f, 0.5f);
}
self.gradientLayer.colors = #[(id)[[color hmf_makeLightHighlight] CGColor], (id)[[UIColor whiteColor] CGColor]];
[self.layer insertSublayer:self.gradientLayer atIndex:0];
}
The problem is that when I do a swipe to delete gesture, the gradient layer seems to cover the delete button.
Is there a way to fix this?
Adding this fixed my issue
- (void)layoutSubviews {
// resize your layers based on the view's new bounds
self.gradientLayer.frame = self.bounds;
}
I guess that you insert gradient layer into UITableViewCell. I think insert into contentView of UITableViewCell may solve your problem.
Related
I have an issue regarding the section border. I have a UITableView and it is of type Grouped. I am trying to draw the border around the each section of the tableview. I am getting the section frame using the below code. Could please tell me how to draw the border around the UITableView section.
CGRect rect = [groupsTableView rectForSection:indexPath.section];
NSLog(#"%f %f %f %f",rect.origin.x,rect.origin.y,rect.size.width,rect.size.height);
I will recommend that you make a new TableView Cell and inside this newTableViewCell, load all the cells in section 2 then give border to newTableViewCell.
but if you don't wanna do that then you can use this code :
#property(strong,nonatomic) CAShapeLayer* borderPath;
-(void)viewDidLayoutSubviews{
[_borderPath removeFromSuperlayer];
UIView *viewToGiveBorder = [[UIView alloc]initWithFrame:sectionView.frame];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:viewToGiveBorder.bounds byRoundingCorners:(UIRectCornerAllCorners) cornerRadii:CGSizeMake(5.0, 5.0)];
//apply path to shapelayer
_borderPath= [CAShapeLayer layer];
_borderPath.path = path.CGPath;
[_borderPath setFillColor:[UIColor clearColor].CGColor];
[_borderPath setStrokeColor:[UIColor colorWithRed: 0 green: 0 blue: 0].CGColor];
_borderPath.frame=sectionView.frame;
//add shape layer to view's layer
[[self.view layer] addSublayer:_borderPath];
}
I'm trying to build a category method on UIView to allow to stroke the UIView, similarly to the Photoshop function: Stroke-Outside. While CALayer properties borderWidth and borderColor work flawlessly to stroke on the inside, I cannot find a good way to stroke the view on the outside.
This is the solution I came up at first:
Using sublayers I add another CALayer with frame larger than the superlayer's bounds. The layer is then inserted in the UIView's sublayers.
- (void)strokeViewWithColor:(UIColor *)color borderWidth:(CGFloat)borderWidth
{
CALayer *borderLayer = [CALayer layer];
CGRect borderFrame = CGRectMake(-borderWidth, -borderWidth, (self.frame.size.width) + (borderWidth * 2), (self.frame.size.height) + (borderWidth * 2));
[borderLayer setBackgroundColor:[[UIColor clearColor] CGColor]];
[borderLayer setFrame:borderFrame];
//
// Copy current border layer radius
//
[borderLayer setCornerRadius:self.layer.cornerRadius];
[borderLayer setBorderWidth:borderWidth];
[borderLayer setBorderColor:[color CGColor]];
[self.layer addSublayer:borderLayer];
}
This works for all the UIView's that have layer's property masksToBounds or view's property clipsToBounds set to NO. But this disables the functionality to use cornerRadius property, which I want to have.
So my second attempt was to use UIView's, since obviously I must go out of the view I want to stroke (the same logic could be applied to layer and superlayer relationship I assume).
I came up with this solution:
- (void)strokeViewWithColor:(UIColor *)color borderWidth:(CGFloat)borderWidth
{
UIView* superview = self.superview;
//
// Fix frame
//
CGRect frame = self.frame;
frame.origin.x -= borderWidth;
frame.origin.y -= borderWidth;
frame.size.width += (2 * borderWidth);
frame.size.height += (2 * borderWidth);
UIView* strokeView = [[UIView alloc] initWithFrame:frame];
strokeView.layer.borderWidth = borderWidth;
strokeView.layer.cornerRadius = self.layer.cornerRadius + borderWidth;
strokeView.layer.borderColor = [color CGColor];
[superview insertSubview:strokeView aboveSubview:self];
}
This works, but the problem would be with auto layout. Because the strokeView has no auto layout constraints, it probably would not work correctly when constraints are added.
That is why I am looking for any other solutions.
What would be the best way to solve this problem? Should I write some code to handle the auto layout issue on second part of the code? Or should I approach the problem from different perspective? If so, how?
I'm mostly looking for suggestions on how to approach the problem.
Thanks for help!
I have a view where I do some drawing. I add a shape layer as a sublayer of the view's layer, then an image view as a subview of the view, and then curve the corners of the imageview's layer. It all works perfectly.
Now i need to use this view in a collectionviewcell, where i can set the image dynamically.
If i perform the work in draw rect it draws it self over and over on top of the other as the collection view scrolls.
I've tried a few other things, like creating a property on the cell for a uiimage, setting that as the imageview's image, and doing the drawing in a setter for it.
Does anyone have a suggestion about how to do this?
Update: Here's an example of the kind of thing im doing in the view
- (void)simplifiedDrawWithImage:(UIImage*)image
{
CAShapeLayer *circleLayer = [CAShapeLayer layer];
CGRect circleRect = self.bounds;
UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:circleRect];
circleLayer.path = circlePath.CGPath;
circleLayer.shadowOffset = CGSizeMake(0, shadowScale * length);
circleLayer.shadowOpacity = .5;
circleLayer.shadowRadius = shadowRadiusScale * length;
[self.layer addSublayer:circleLayer];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
// size appropriately
[self addSubview:imageView];
CALayer *imageLayer = imageView.layer;
[imageLayer setMasksToBounds:YES];
[imageLayer setCornerRadius:((imageView.frame.size.width - innerRing / 2) / 2)];
}
I use this:
UICollectionViewCell *cell = [collView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
[cell.contentView.subviews makeObjectsPerformSelector: #selector(removeFromSuperview)];
At least, it SOUNDS like the same problem.
In your UICollectionViewCell, override -prepareForReuse and remove the previous image.
Update:
In your code, you have this line: [self.layer addSublayer:circleLayer]; which is adding a layer of drawing TO YOUR CELL. So later when you create a UIImageView and assign it an image, you still have created a drawing in the cell itself.
When that cell is recycled, that layer is still there, and then you add it again. Don't draw that layer on self, create that in a view then add that to the cell.
I'm adding a CAGradientLayer to a view. When the view is auto-resized (such as after a rotation) the gradient layer is not resized. Can the gradient be set to auto-resize the same as the view? Note also that I am using auto-layout constraints in the view.
Here's what I'm doing:
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = CGRectMake(0.0, 0.0, frame.size.width, frame.size.height);
gradientLayer.colors = [NSArray arrayWithObjects:
(id)[[UIColor colorWithRed:255.0/255.0f green:255.0/255.0f blue:255.0/255.0f alpha:1.0f] CGColor],
(id)[[UIColor colorWithRed:233.0/255.0f green:233.0/255.0f blue:233.0/255.0f alpha:1.0f] CGColor], nil];
[self.layer insertSublayer:gradientLayer atIndex:0];
Here are two different ways to fix your problem.
Make gradientLayer an instance variable instead of a local variable. Then, override layoutSubviews in your view class to set the frame of the gradient layer:
- (void)layoutSubviews {
[super layoutSubviews];
_gradientLayer.frame = self.bounds;
}
Create a subclass of UIView named GradientView, and override its +layerClass method to return [CAGradientLayer class]. Use this view to draw your gradient instead of using a layer directly. Then set the gradient view's autoresizingMask (or add constraints to it if you are using auto layout). See this answer for an example.
Creating the GradientView class will also make the resizing behave correctly during rotation, so I recommend that solution.
I resize the layer's bounds manually by overriding the setFrame: method of the view:
-(void)setFrame:(CGRect)frame
{
[super setFrame:frame];
_gradientLayer.bounds = CGRectMake(0, 0, CGRectGetWidth(frame), CGRectGetHeight(frame));
}
I have a UIViewController with a UITableView. The sits inside the view controller's view with some padding on all sides. I am trying to draw a drop shadow from the table view as well as rounded corners, but I am unable to achieve both at the same time. I have tried with the following code and turned masksToBounds on and off, but setting it to NO create a really weird effect with the shadow scrolling and the calls are not clipping inside the table.
[self.tableView.layer setShadowColor:[UIColor blackColor].CGColor];
[self.tableView.layer setShadowOffset:CGSizeMake(0, 3)];
[self.tableView.layer setShadowOpacity:0.4];
[self.tableView.layer setShadowRadius:3.0f];
[self.tableView.layer setCornerRadius:5.0f];
[self.tableView.layer setShadowPath:[[UIBezierPath bezierPathWithRoundedRect:self.tableView.bounds cornerRadius:5.0f] CGPath]];
I am just drawing a UITableView with plain style too. The effect I am trying to achieve can be seen in the free app Transit App and here's a movie where you can see the shadow stays and the table even has a mask that scrolls up and down.
I have searched and searched and haven't been able to put together a solution based on other SO answers or online articles. Help appreciated.
Try the below links, some of them are old but you can get some pointer.
Custom Table Effects
Dropshadow 2
Cool Table Views
DropShadow
Okay!! I attempted once again and got an effect, it is again a work around only (instead of using images), the below is what i tried
Create a CALayer, with the same frame as your tableview, give the same curve and all, add the table view on top of this layer, thats it.
CALayer *sublayer = [CALayer layer];
sublayer.backgroundColor = [UIColor blueColor].CGColor; // If you dont give this, shadow will not come, dont know why
sublayer.shadowOffset = CGSizeMake(0, 3);
sublayer.shadowRadius = 5.0;
sublayer.shadowColor = [UIColor blackColor].CGColor;
sublayer.shadowOpacity = 1.0;
sublayer.cornerRadius = 5.0;
sublayer.frame = CGRectMake(myTable.frame.origin.x, myTable.frame.origin.y, myTable.frame.size.width, myTable.frame.size.height);
[self.view.layer addSublayer:sublayer];
[self.view.layer addSublayer:myTable.layer];
Ah!! due to some reason I am unable to upload the screenshot from my machine, firewall ;-). I will try from my home.
-anoop
It is recommended to use images for drop shadows with large tableviews, all that drawing has the ability to slow down performance, which can result in bad user experience, just a word of advice
I know this is a rather old question, but I recently had the same problem and the solutions here were good examples, but not full enough. So here it is the method I'm using to create shadow of a table view. It can be used also for any other view.
-(void)makeShadowToView:(UIView*) view withHeight:(CGFloat)shadowHeight
{
CGRect bounds = view.frame;
bounds.size.height = shadowHeight;
view.clipsToBounds = NO; // Without this row it doesn't display any shadow, at least for a table view
view.layer.shadowColor = [UIColor blackColor].CGColor;
view.layer.shadowOpacity = 0.9f;
view.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
view.layer.shadowRadius = 5.0f;
view.layer.shadowPath = [UIBezierPath bezierPathWithRect:bounds].CGPath;
}
Example usage: [self makeShadowToView:self.view withHeight:height];
where height is added in case you want to recalculate the shadow's height according to the table content's height.
(void)shadowForView{
CALayer *layer = self.viewActionMenu.layer;
layer.shadowOffset = CGSizeMake(-2, 0);
layer.shadowColor = [[UIColor blackColor] CGColor];
layer.shadowRadius = 2.0f;
layer.shadowOpacity = 0.80f;
// [self.view bringSubviewToFront:self.actionView];
}
And Call:
[self shadowForView];
Try this
UITableView * objTableview=[[UITableView alloc]initWithFrame:CGRectMake(x, y, w, h)];
UIView * objViewShadow=[[UIView alloc]initWithFrame:objTableview.bounds];
objTableview.layer.cornerRadius=5;
// add shadow
objViewShadow.layer.shadowOffset = CGSizeMake(0, 3);
objViewShadow.layer.shadowRadius = 5.0;
objViewShadow.layer.shadowColor = [UIColor blackColor].CGColor;
objViewShadow.layer.shadowOpacity = 0.8;
[objViewShadow addSubview:objTableview];
[self.view addSubview:objViewShadow];
You need to set this two properties
self.tableView.clipsToBounds = NO;
self.tableView.layer.masksToBounds = NO;