I would like to draw an outline around a column. here is how my app actually looks like: https://gyazo.com/80dffe6a153e82565a610222a43e0c11
So the white column represent the day on where we are actually. But I don't really want to do that.
Actually I'm doing this:
if(column == _intOfTheDay){ //intOfTheDay represent the day one where we are actually
cell.backgroundColor = [[UIColor whiteColor]colorWithAlphaComponent:0.95];
}
I've tried something like this to get closer of the result that I want:
if(column == _intOfTheDay){
cell.layer.borderWidth = 5.0f;
cell.layer.borderColor = [UIColor redColor].CGColor;
}
But the problem here (without all the bugs due to the UICollectionView) is that it draw a rectangle around each cell. And what I would like is to draw only one rectangle but around all the column.
How could I process?
Every help will be appreciated, thanks in advance.
If you don't want to subclass the UICollectionViewCell then use this :
float borderWidth = 5.0;
CALayer *leftBorder = [CALayer new];
leftBorder.frame = CGRectMake(0.0, 0.0, borderWidth, cell.frame.size.height);
leftBorder.backgroundColor = [UIColor redColor].CGColor;
[cell.layer addSublayer:leftBorder];
CALayer *rightBorder = [CALayer new];
rightBorder.frame = CGRectMake(cell.frame.size.width - borderWidth, 0.0, borderWidth, cell.frame.size.height);
rightBorder.backgroundColor = [UIColor redColor].CGColor;
[cell.layer addSublayer:rightBorder];
You can do something like this, set three border to first cell of column- left,right and top and for last cell of column left,right and bottom and for all middle cell left and right. you can use CALayer to set one side border like below example,
CALayer *TopBorder = [CALayer layer];
TopBorder.frame = CGRectMake(0.0f, 0.0f, self.myImageView.frame.size.width, 3.0f);
TopBorder.backgroundColor = [UIColor redColor].CGColor;
[cell.layer addSublayer:TopBorder];
Related
I have a UICollectionView (iPad) that has jarry scrolling.Each cell has a white rectangle UIView (with all rounded corners) that has another UIImageView in front of it with only top two corners rounded. See this link below for how this cell looks - i.stack.imgur.com/Ptlig.png
Here's the code for the UICollectionViewCell
UIView * bgView = [[UIView alloc] initWithFrame:CGRectMake(5, 5, (self.contentView.frame.size.width - 10), (self.contentView.frame.size.width - 10)*IMAGE_RATIO + 43.5)];
bgView.backgroundColor = [UIColor clearColor];
bgView.layer.cornerRadius = 10;
bgView.layer.borderWidth = 0.5f;
bgView.layer.borderColor = [UIColor colorWithRed: 179/255.0 green:181/255.0 blue:184/255.0 alpha:1.0].CGColor;
bgView.layer.backgroundColor = [UIColor whiteColor].CGColor;
bgView.layer.shouldRasterize = YES;
bgView.layer.rasterizationScale = [UIScreen mainScreen].scale;
[self.contentView addSubview:bgView];
self.parablePost = [[UIImageView alloc] initWithFrame:CGRectMake(5, 5, (self.contentView.frame.size.width - 10), (self.contentView.frame.size.width-10)*IMAGE_RATIO)];
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.parablePost.bounds byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerTopRight) cornerRadii:CGSizeMake(10.0, 10.0)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = self.parablePost.bounds;
maskLayer.path = maskPath.CGPath;
self.parablePost.layer.mask = maskLayer;
[self.contentView addSubview:self.parablePost];
When this line "self.parablePost.layer.mask = maskLayer" is commented, scrolling is smooth. So the CAShapeLayer is causing performance issues. I tried rasterize and hand drawing instead of using UIBezierPath but it does not improve the experience.
Is there a faster way to round two corners of UIImageView?
EDIT:
I finally added static images to simulate rounded corners on the top two corners of the UIImageView that gave me the same look without the scroll jitter. Surprised that CAShapeLayer is a performance drain.
masks are expensive... (they might even be rendered in software). try to think of another way to get the look you want. for example, pre-render things to an image...
I've been trying for some time now, using CAGradientLayer to produce this .
Initially I tried having a gradient background using the .colors property, however this is only a background fill. Trying this approach, I tried to add another CALayer inside that had a black background, however i could never get the radius correct, and it would create a line of various thickness at the rounded corners.
Is there a better way to create this rounded rect border with a gradient to it? Will CALayer not achieve this and should I move over to UIBezierPath or CGContextRef?
Code for failed attempt:
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(12*twelthWidth - squareCentre.x - squareSize.width, squareCentre.y, squareSize.width, squareSize.height)];
// Create the rounded layer, and mask it using the rounded mask layer
CAGradientLayer *roundedLayer = [CAGradientLayer layer];
[roundedLayer setFrame:view.bounds];
roundedLayer.cornerRadius = view.bounds.size.width/5;
roundedLayer.masksToBounds = YES;
roundedLayer.colors = [NSArray arrayWithObjects:(id)[[UIColor redColor] CGColor], (id)[[UIColor blueColor] CGColor], nil];
roundedLayer.borderWidth = 4;
roundedLayer.borderColor = [UIColor clearColor].CGColor;
// Add these two layers as sublayers to the view
int BorderWidth = 5;
CALayer *solidColour = [CALayer layer];
solidColour.cornerRadius = view.bounds.size.width/5;
solidColour.masksToBounds = YES;
solidColour.backgroundColor = [UIColor blackColor].CGColor;
[solidColour setFrame:CGRectMake(BorderWidth, BorderWidth, roundedLayer.bounds.size.width - 2*BorderWidth, roundedLayer.bounds.size.height - 2*BorderWidth)];
[view.layer insertSublayer:roundedLayer atIndex:0];
[view.layer insertSublayer:solidColour above:roundedLayer];
[self.view addSubview:view];
Which produces:
Whereby the corners aren't right. Could it be that I need to calculate a different radius for the second layer?
Edit
After setting the radius of the solid colour to solidColour.bounds.size.width/5, it still isn't right - It goes too thin at the corners.
The problem you are seeing is because the inner and outer corner radius are the same. That is what causes the line thickness to vary. This illustration from CSS-Tricks highlights the issue (even thought you aren't using CSS, the problem is still the same):
The solution is to calculate the inner radius as:
innerRadis = outerRadius - lineThickness
As shown in this illustration by Joshua Hibbert:
Instead of using the view bounds to set the cornerRadius of the solid layer, use the layer's frame value after you've set it to the correct inset value:
solidColour.masksToBounds = YES;
solidColour.backgroundColor = [UIColor blackColor].CGColor;
[solidColour setFrame:CGRectMake(BorderWidth, BorderWidth, roundedLayer.bounds.size.width - 2*BorderWidth, roundedLayer.bounds.size.height - 2*BorderWidth)];
solidColour.cornerRadius = solidColour.frame.size.width/5;
[view.layer insertSublayer:roundedLayer atIndex:0];
[view.layer insertSublayer:solidColour above:roundedLayer];
With this I get the following image
Just for your convenience if you use swift
let v = yourUIVIEW
let outerRadius:CGFloat = 60
let borderWidth:CGFloat = 8;
let roundedLayer = CAGradientLayer()
roundedLayer.frame = v.bounds
roundedLayer.cornerRadius = outerRadius
roundedLayer.masksToBounds = true
roundedLayer.endPoint = CGPoint(x: 1 , y: 0.5)
roundedLayer.colors = [ UIColor.redColor().CGColor, UIColor.blueColor()!.CGColor]
let innerRadius = outerRadius - borderWidth
//Solid layer
let solidLayer = CALayer()
solidLayer.masksToBounds = true
solidLayer.backgroundColor = UIColor.whiteColor().CGColor
solidLayer.cornerRadius = innerRadius
solidLayer.frame = CGRect(x: borderWidth, y: borderWidth, width: roundedLayer.bounds.width - 2*borderWidth, height:roundedLayer.bounds.height - 2*borderWidth )
v.layer.insertSublayer(roundedLayer, atIndex: 0)
v.layer.insertSublayer(solidLayer, above: roundedLayer)
I use this code in my customized UIView initialization:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
...
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRect:CGRectMake(frame.origin.x, frame.size.height, frame.size.width, 15)];
self.layer.masksToBounds = NO;
self.layer.shadowColor = [UIColor blackColor].CGColor;
self.layer.shadowOffset = CGSizeMake(0.0f, 4.0f);
self.layer.shadowOpacity = 0.5f;
self.layer.shadowPath = shadowPath.CGPath;
}
return self;
}
trying to make a drop shadow like this:
1)
But I got this effect:
2)
You can see this is an upside down version of what I want to achieve. How to make the shadow effect of the first image?
The issue is just with your shadowPath.
Using CGRectMake(frame.origin.x, frame.size.height, frame.size.width, 15) to create your UIBezierPath will set an incorrect origin.
First, origin.x should be 0.0f or the shadow will shift far away if your UIView's origin.x != 0.0f. Second, you need to line up the bottom of the shadowPath with the bottom of your UIView.
This is a screenshot of UIViews using your shadow code illustrating these issues. (In the lower UIView you cannot see the shadow because it is far off the right of the screen).
You will see what you intended if you change the rect to:
const CGFloat shadowRectHeight = 15.0f;
CGRect shadowRect = CGRectMake(0.0f, self.bounds.size.height - shadowRectHeight, self.bounds.size.width, shadowRectHeight)];
Do like this and set the UIView alpha
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = rect;
gradient.colors = [NSArray arrayWithObjects:(id)[UIColor blackColor].CGColor,
(id)[UIColor grayColor].CGColor,
(id)[UIColor blackColor].CGColor,nil];
[self.layer insertSublayer:gradient atIndex:0];
you can add or remove UIColor you want to display.
I am looking at how to make a label appear to have a rounded glossy look, similar to this:
I know I can use the CALayer in the app for different things like borders, and rounded corners, but I'm unsure about a glossy look. Right now I am using:
CALayer* l = [myCounterLabel layer];
CALayer* m = [myhiddenlabel layer];
[l setMasksToBounds:YES];
[l setCornerRadius:11];
[l setBorderWidth:2.0];
[l setBorderColor:[[UIColor blackColor] CGColor]];
This gives me a label that looks like this (I know font and everything else doesn't match...right now just looking for a glossy look:
There's a few ways you could do this but a CAGradientLayer is likely your best bet. Assume you have CAGradientLayer* property:
self.gradient = [CAGradientLayer layer];
self.gradient.frame = CGRectMake(100, 100, 100, 100);
self.gradient.cornerRadius = 11;
self.gradient.borderWidth = 2.0;
// Set the colors you want in the gradient
self.gradient.colors = #[(id)[UIColor grayColor].CGColor, (id)[UIColor grayColor].CGColor, (id)[UIColor blackColor].CGColor, (id)[UIColor blackColor].CGColor];
// if you want to control as to the distribution of the gradient you can set the control points for the gradient here (make sure you have as many as you have colors)
self.gradient.locations = #[#0.0f, #0.5f, #0.5f, #1.0f];
You could try to add another sub-layer to your original layer with background color to fill the second half part:
CALayer *sublayer = [CALayer layer];
sublayer.backgroundColor = [UIColor blueColor].CGColor; //your color
sublayer.frame = CGRectMake(0, 50, 50, 50); //parent layer (height 100, width 50)
[yourLayer addSublayer:sublayer];
I want to achieve the text appearance like in the pictures below:
Now I'm working on shadow around the letters and I can't figure out how to do that.
What I've tried so far:
- The solution with:
label.shadowColor = [UIColor blackColor];
label.shadowOffset = CGSizeMake(1, 2);
gives a nice sharp shadow, but it doesn't fit my needs by two reasons:
It gives a shadow only from one side, set up by shadowOffset, whereas I need a "wrapping" shadow;
This solution doesn't give the soft part of the shadow (gradient) as there is in the pictures;
-The solution with:
label.layer.shadowOffset = CGSizeMake(0, 0);
label.layer.shadowRadius = 5.0;
label.layer.shouldRasterize = YES;
label.layer.shadowOpacity = 1;
label.layer.shadowColor = [UIColor blackColor].CGColor;
label.layer.masksToBounds = NO;
Works great, but it gives too soft shadow even though the shadowOpacity is set to 1 and the shadowColor is set to black:
Obviously it's not enough and I already think about drawing in labels' context. But it is not clear to me how would I achieve the goal even through context drawing.
Any idea would be much appreciated.
Try this
Create a Custom UILabel SubClass and Override the following method
- (void)drawTextInRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetShadow(context, CGSizeMake(0.0, 0.0), 10);
CGContextSetShadowWithColor(context, CGSizeMake(0.0, 0.0), 10, [UIColor blackColor].CGColor);
[super drawTextInRect:rect];
CGContextRestoreGState(context);
}
and this bottomColorLayer to the Label
CALayer *bottomColorLayer = [CALayer layer];
bottomColorLayer.frame = CGRectMake(0, labelRect.size.height/2, labelRect.size.width, labelRect.size.height/2);
bottomColorLayer.backgroundColor = [[UIColor colorWithWhite:0 alpha:.5] CGColor];
[label.layer insertSublayer:bottomColorLayer above:(CALayer *)label.layer];
or If you want Gradient
CAGradientLayer *bottomGradient = [CAGradientLayer layer];
bottomGradient.frame = CGRectMake(0, labelRect.size.height/2, labelRect.size.width, labelRect.size.height/2);
bottomGradient.cornerRadius = 0.0f;
bottomGradient.colors = #[(id)[[UIColor colorWithWhite:1 alpha:.5] CGColor], (id)[[UIColor colorWithWhite:0 alpha:.5] CGColor]];
[label.layer insertSublayer:bottomGradient above:(CALayer *)label.layer];
Use an explicit shadow path that's the shape you want. It sounds like you want a shadow the same shape as your text, but larger, with each shadow-letter centered on its corresponding letter. Once you have that, use the shadow radius to soften the edges of the shadow to whatever degree you want.
The code you have relies on the shadow radius alone to make the shadow larger than the text, which removes your ability to control the softness.
Try with the code below :-
[_testLable setText:#"TION ERRO"];
[_testLable setTextColor:[UIColor whiteColor]];
[_testLable setFont:[UIFont boldSystemFontOfSize:22] ];
_testLable.layer.shadowOffset = CGSizeMake(0, 0);
_testLable.layer.shadowRadius = 10.0;
_testLable.layer.shouldRasterize = YES;
_testLable.layer.shadowOpacity = 1;
_testLable.layer.shadowColor = [UIColor blackColor].CGColor;
_testLable.layer.masksToBounds = NO;
CGPathRef shadowPath = CGPathCreateWithRect(_testLable.bounds, NULL);
_testLable.layer.shadowPath = shadowPath;
CGPathRelease(shadowPath);
Its output is like this:-