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.
Related
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.
I have the following code to make the UIImageView in each of my UITableView's cells have rounded corners:
- (void)awakeFromNib
{
// Rounded corners.
[[cellImage layer] setCornerRadius:([cellImage frame].size.height / 2)];
[[cellImage layer] setMasksToBounds:YES];
[[cellImage layer] setBorderColor:[[UIColor whiteColor] CGColor]];
[[cellImage layer] setBorderWidth:3]; // Trouble!
}
I want the images to have a bit of a gap between them, and figured I could make use of the border width to make that happen. Below is an image of what actually happened:
It's that faint black border that I want to know how to get rid of. I'd like to think there's a way of doing it using border width. If not, the best approach might be just to resize the image itself and just set the border width to be 0.
Rather than using corner radius, you can create bezier path for the mask, create a shape layer for that path, and then specify that shape layer for the image view's layer's mask:
CGFloat margin = 3.0;
CGRect rect = CGRectInset(imageView.bounds, margin, margin);
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(imageView.bounds.size.width/2, imageView.bounds.size.height/2) radius:radius startAngle:0 endAngle:M_PI*2 clockwise:NO];
CAShapeLayer *mask = [CAShapeLayer layer];
mask.path = path.CGPath;
imageView.layer.mask = mask;
What you are doing is, you are clipping the profile image and the border together, which is making the cell's profile image extending through the border.
You are missing this line:-
cellImage.clipsToBounds = YES;
I have a UIImageView which is basically a mole. I want this mole to pop out of a hole. So actually what I have in mind is that I will create a mole some points below the hole and have a mask over it so and then animate up the image view so it looks like its popping out of hole. So following the thought , I had made written down this code :
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
CGRect maskRect = _moleIcon.frame;
CGPathRef path = CGPathCreateWithRect(maskRect, NULL);
maskLayer.path = path;
CGPathRelease(path);
_moleIcon.layer.mask = maskLayer;
[UIView animateWithDuration:2.0 animations:^(void){
_moleIcon.transform=CGAffineTransformMakeTranslation(0, 50);
}];
but the problem, is that it seems that the mask itself is moving with the actual UIImageView. Any help would be highly appreciated.
try to use 2 UIViews, just maskView should be bring to front:
[superview bringSubviewToFront:maskView];
and set background color and alpha property for mask view,
maskView.backgroundColor = [UIColor blackColor];
maskView.alpha = 0.8;
and now you can move 2 view directly.
but better is to add 2 view to other view - container, and rotate this one view.
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 can add shadow to imageView layer using the following code.
self.imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"test.png"]];
self.imageView.center = self.view.center;
CALayer *containerLayer= [CALayer layer];
containerLayer.shadowColor = [UIColor blackColor].CGColor;
containerLayer.shadowRadius = 10.0f;
containerLayer.shadowOffset = CGSizeMake(10.0f, 5.0f);
containerLayer.shadowOpacity = .8f;
[containerLayer addSublayer:self.imageView.layer];
[self.view.layer addSublayer:containerLayer];
1 . The problem is that I don't know why I have to add imageView.layer to containerLayer to get the imageView shadow effect. However, if I add containerLayer to imageView.layer, there's no shadow in imageView, why?
The error code is:
self.imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"test.png"]];
self.imageView.center = self.view.center;
CALayer *containerLayer= [CALayer layer];
/*same as before*/
[self.imageView.layer addSublayer:containerLayer];
[self.view.layer addSublayer:self.imageView.layer];
Question2: the containerLayer's(used to provide shadow to imageView) frame = {{0, 0}, {0, 0}}, but the final position is in the center of screen. why?
A layer needs something opaque inside it to create a shadow around (unless you've specified a shadowPath explicitly). So your first version of the code works because the containerLayer has the imageView's layer as a sublayer. But, as you noticed from Question #2, the containerLayer's frame indicates that it is actually located in the upper left corner with a size of (0,0). The reason you can still see the image is that containerLayer is not masking to its bounds. Add this line to your first version, and the image disappears:
[containerLayer setMasksToBounds: YES]; // kitten (and shadow) is gone
Your version #2 of the code does not display a shadow because, in part, the containerLayer does not "contain" anything. If you use version #2 but give the containerLayer a new frame and an opaque background color, a shadow appears. (But this obviously isn't a solution, because the image is covered up...) Also note that there is no shadow when the layer's background is [UIColor clearColor].
[self.imageView.layer addSublayer:containerLayer];
containerLayer.frame = self.imageView.layer.bounds;
containerLayer.backgroundColor = [UIColor yellowColor].CGColor; // yellow box w/shadow
// containerLayer.backgroundColor = [UIColor clearColor].CGColor; // no shadow here
If you wanted to have a container with a shadow that houses the UIImageView, you could do something like this:
UIView * shadowView = [[UIView alloc] initWithFrame: self.imageView.frame];
shadowView.layer.shadowColor = [UIColor blackColor].CGColor;
shadowView.layer.shadowRadius = 10.0f;
shadowView.layer.shadowOffset = CGSizeMake(10.0f, 5.0f);
shadowView.layer.shadowOpacity = .8f;
[self.view addSubview: shadowView];
self.imageView.frame = (CGRect) { CGPointZero, self.imageView.frame.size };
[shadowView addSubview: self.imageView];
A CALayer could be used instead of a UIView in a similar way. Or you could apply shadow attributes to the imageView's layer directly, making sure that neither the view nor the layer is clipping/masking to bounds.
If you want to add a shadow over the imageview just change the alpha value (0.0 min - 1.0 max) of that imageview. This will give you the shadow effect and whenever you want to remove the shadow just restore the alpha value to 1.0.
For ex:
self.imageview.alpha = 0.5 // shadow state
self.imageview.alpha = 1.0 // original state