How to add drop shadow only for the right side? - ios

I am adding the drop shadow like this.
vwVertical=[[UIView alloc] init];
[vwVertical setBackgroundColor:[UIColor whiteColor]];
vwVertical.translatesAutoresizingMaskIntoConstraints = NO;
vwVertical.layer.shadowColor=[UIColor colorWithRed:32/255 green:59/255 blue:90/255 alpha:1.0].CGColor;
vwVertical.layer.shadowOffset=CGSizeMake(5, 0);
vwVertical.layer.shadowOpacity=0.12;
vwVertical.layer.shadowRadius=6.5;
[vwBlock addSubview:vwVertical];
But this is adding shadow 3 sides. How can I add just to right side.
Please help me.
Thanks

All you need to do is to inset the view's bounds on top - left - bottom, and use the shadow path.
vwVertical=[[UIView alloc] init];
// Create edge insets
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0, 10, 0, 0);
// Create rect with inset and view's bounds
CGRect shadowPathOnlyIncludingRight = UIEdgeInsetsInsetRect(vwVertical.bounds, contentInsets);
// Apply it on the layer's shadowPath property
vwVertical.layer.shadowPath = [UIBezierPath bezierPathWithRect:shadowPathOnlyIncludingRight].CGPath;
[vwVertical setBackgroundColor:[UIColor whiteColor]];
vwVertical.translatesAutoresizingMaskIntoConstraints = NO;
vwVertical.layer.shadowColor=[UIColor colorWithRed:32/255 green:59/255 blue:90/255 alpha:1.0].CGColor;
vwVertical.layer.shadowOffset=CGSizeMake(5, 0);
vwVertical.layer.shadowOpacity=0.12;
vwVertical.layer.shadowRadius=6.5;

Related

IOS/Objective-C: Subview of Subview not displaying

I am trying to create a chart where a bar in the form of a UIView displays on top of a background UIView. I'd like both to display on top of the UIView for the whole screen. I have done this before successfully, but while I can get the first view to display, I somehow can't get my code to display the bar. Could it have something to do with setting the color? Or can anyone suggest why the second subview is not displaying.
My code:
//Make background box:
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGFloat graphWidth = screenWidth-40;
CGFloat graphHeight = 160;
CGRect graphBounds =CGRectMake(20, 200, graphWidth, graphHeight);
float tableStartY = graphBounds.origin.y;
UIView *graphBox = [[UIView alloc] initWithFrame:graphBounds];
graphBox.backgroundColor = [UIColor colorWithRed:200.0/255.0 green:200.0/255.0 blue:200.0/255.0 alpha:0.2]; graphBox.layer.borderWidth = 1;
graphBox.layer.borderColor = [UIColor blueColor].CGColor;
//Make Bar
CGFloat barWidth = 20;
CGFloat barHeight = 100;
CGRect aBar = CGRectMake(20, tableStartY+1, barWidth, barHeight);
UIView *barView = [[UIView alloc] initWithFrame:aBar];
barView.backgroundColor = [UIColor blueColor];
barView.layer.borderWidth = 1;
barView.layer.borderColor = [UIColor redColor].CGColor;
// [graphBox addSubview:barView];
[self.view addSubview: graphBox];
If I run the above code, it displays the graphBox. If I add the bar directly to the view as a subView instead of the graphBox, the bar displays. However, if I uncomment out the line shown and add the barView first to the graphBox and then add the graphBox to the view, the barView does not display.
Thanks in advance for any suggestions.
If I understand correctly what you need to do, you should replace
CGRect aBar = CGRectMake(20, tableStartY+1, barWidth, barHeight);
with
CGRect aBar = CGRectMake(20, 1, barWidth, barHeight);
[edit: and obviously uncomment the addSubview line]
Perhaps this is an accident in your posted code, but you have specifically commented out where the barView would be added to the screen.
// [graphBox addSubview:barView];
In addition, as another answer lists, your offset is incorrect if you are adding barView to graphBox. If you add it to self.view instead, your offset is correct.
So, you've got two choices, depending on the containment you desire in your view hierarchy:
CGRect aBar = CGRectMake(20, 1, barWidth, barHeight);
// ...
[graphBox addSubview:barView];
or
CGRect aBar = CGRectMake(20, tableStartY+1, barWidth, barHeight);
// ...
[self.view addSubview: graphBox];
[self.view addSubview:barView];
Note that in the second option, the order is important to get the barView to display over top of the graphBox as they will be siblings.

UILabel Background Color Leaks to Border

I'm creating a UILabel to which I set the background color and corner radius with the following code:
self.scoreLabel.backgroundColor = [UIColor DISRed];// custom red`
self.scoreLabel.layer.masksToBounds = YES;
self.scoreLabel.layer.cornerRadius = self.scoreLabel.frame.size.width/2;
self.scoreLabel.layer.borderWidth = 8.0;
self.scoreLabel.layer.borderColor = [[UIColor DISNavy] CGColor];
However the background's color seems to be leaking to the edge of the border (see image). Any ideas why? Any idea on how to fix it?
I was also facing the same problem. It was a silly mistake. I always forget to tick clipToBounds in case of cornerRadius.
So, just ticking the Clip to Bounds for UILabel in Storyboard fixed my problem.
And yes, we need to keep the below code too:
label.layer.masksToBounds = true
I ran into the same problem with the UIButton's background color leaking around the edge of its border.
Instead of setting the UIButton background color on the UIButton, set it on the UIButton's layer.
Replace:
self.scoreLabel.backgroundColor = [UIColor DISRed];// custom red`
With this:
self.scoreLabel.layer.backgroundColor = [[UIColor DISRed] CGColor];// custom red`
I created my own UILabel and background colour does not seem to be leaking.
Write this in .h file of your project.
UILabel *label;
Write this in .m file of your project.
label=[[UILabel alloc]initWithFrame:CGRectMake(100, 300, 100, 100)];//Set frame of label in your viewcontroller.
[label setBackgroundColor:[UIColor redColor]];//Set background color of label.
[label setText:#"Label"];//Set text in label.
[label setTextColor:[UIColor blackColor]];//Set text color in label.
[label setTextAlignment:NSTextAlignmentCenter];//Set text alignment in label.
[label.layer setCornerRadius:50.0];//Set corner radius of label to change the shape.
[label.layer setBorderWidth:8.0f];//Set border width of label.
[label setClipsToBounds:YES];//Set its to YES for Corner radius to work.
[label.layer setBorderColor:[UIColor greenColor].CGColor];//Set Border color.
[self.view addSubview:label];//Add it to the view of your choice.
It is probably anti aliasing issue. you can better fix it by adding a bezier path around the corners.
CAShapeLayer *subLayer = [[CAShapeLayer alloc] init];
[subLayer setFillColor:[UIColor clearColor].CGColor];
[subLayer setStrokeColor:[UIColor whiteColor].CGColor];
[subLayer setLineWidth:1.0];
[subLayer setPath:[UIBezierPath bezierPathWithRoundedRect:imageView.bounds cornerRadius:imageView.layer.cornerRadius].CGPath];
[imageView.layer addSublayer:subLayer];
For those who are still facing the issue of border color leaking out:
Go through the below code, please note you will need to set frames & border width as per your requirement, I'm setting the position as view's center
let badgeSize: CGFloat = 10
let redBadge = UIView(frame: CGRect(x: view.center.x, y:view.center.y, width: badgeSize, height: badgeSize))
redBadge.layer.borderColor = UIColor.white.cgColor
redBadge.layer.borderWidth = 2
redBadge.backgroundColor = .red
redBadge.layer.cornerRadius = badgeSize * 0.5
redBadge.clipsToBounds = true
redBadge.layer.masksToBounds = true
redBadge.maskLayerOnView(radius: badgeSize * 0.5)
view.addSubview(redBadge)
Secondly, we need to write an extension on UIView
extension UIView{
func maskLayerOnView(radius: CGFloat){
let maskLayer = CAShapeLayer()
maskLayer.path = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: [.allCorners],
cornerRadii: CGSize(width: radius,
height: radius)).cgPath
self.layer.mask = maskLayer
}
}
This code snippet removes the border color separating out, one can replicate this behaviour on any kind of views.
For detailed explanation please see this article.
Well, a lot of answers...
I found the problem persists, as long as the UIViews background color is used and not the background color of the UIViews 'layer'. In addition, of course, masking needs to be enabled.
For a UICollectionViewCell subclass the code is:
- (void)prepare
{
self.contentView.layer.backgroundColor = UIColor.redColor.CGColor;
self.contentView.layer.cornerRadius = 25.0;
self.contentView.layer.borderColor = UIColor.blackColor.CGColor;
self.contentView.layer.borderWidth = 1.0;
//Enable to optimize image views: self.contentView.layer.shouldRasterize = YES;
//Enable to optimize image views: self.contentView.layer.rasterizationScale = UIScreen.mainScreen.scale;
self.contentView.layer.masksToBounds = YES;
self.contentView.clipsToBounds = YES;
}
To make the setting of the background color more comfortable and less error prone, some could add this:
/*
setBackgroundColor:
*/
- (void)setBackgroundColor:(UIColor *)p_BackgroundColor
{
super.backgroundColor = nil;
self.contentView.layer.backgroundColor = p_BackgroundColor.CGColor;
self.contentView.layer.masksToBounds = YES;
self.contentView.clipsToBounds = YES;
}

iOS: programmatically draw a rectangle on top of a button

I need to draw a rectangle on top of a UIButton. Assume that there's a UIButton called hideMe, and this button has 100x50 size. I want to place a 100x10 rectangle on top of this button every time a user receives a message. If the user receives five messages, then the button will be completely covered by the rectangles. How do I do this?
CALayer *topBorder = [CALayer layer];
topBorder.borderColor = [UIColor redColor].CGColor;
topBorder.backgroundColor = [UIColor blackColor].CGColor;
topBorder.borderWidth = 2;
topBorder.frame = CGRectMake(0, 15, <tempButton>.frame.size.width, <tempButton>.frame.size.height-30);
[<tempButton>.layer addSublayer:topBorder];
The above code helps you to draw the rectangle.You can increase the layer frames to cover full.
try this
#import <QuartzCore/QuartzCore.h>
here we are drawing our own border rect and sub viewing it to our button
-(UIView*)borderRectWithYvalue:(CGFloat)yValue
{
UIView * rect = [[UIView alloc] initWithFrame:CGRectMake(0,yValue, 100, 10)];
rect.backgroundColor = [UIColor lightGrayColor];
rect.layer.borderColor = (__bridge CGColorRef)([UIColor redColor]);
rect.layer.borderWidth = 2.0f;
return rect;
}
and call this method when and where you want to add border to your button with your custom y value
for ex
[yourButton addSubview:[self borderRectWithYvalue:10.0]];

Masking Content of a UIView

Is it possible to mask certain area of a view, so that content of that part became invisible/hidden.
I am using a web view and wanted to remove the top round corner of view, like below attached image -
Problem -
I want to remove/hide all the content which is below red area.
What I have tried -
I have tried to add a image view on top of web view and added a masking layer on top of it, but that doesn't seems to be working for me -
UIImageView *maskImage = [[UIImageView alloc] init];
maskImage.frame = CGRectMake(256, -10, 64, 64);
maskImage.image = [UIImage imageNamed:#"maskingImage"];
[self.webView addSubview: maskImage];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
CGRect maskRect = whitefoldMaskImage.frame;//CGRectMake(0, 0, 50, 100);
CGPathRef path = CGPathCreateWithRect(maskRect, NULL);
maskLayer.path = path;
CGPathRelease(path);
maskImage.layer.mask = maskLayer;
EDIT 1 --
As per suggestion of Mundi, I have tried opaque view on top of web view.
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(256, -10, 64, 64)];
view.opaque = YES;
[self.webView addSubview:view];
But that haven't worked too.
I have also gone through following threads on SO, but haven't found any solution -
CALayer: add a border only at one side
Simply mask a UIView with a rectangle
I want to remove/hide all the content which is below red area.
Simply add a opaque view above the area you want to hide. No need for a mask. E.g.
UIView *cover = [[UIView alloc] initWithFrame:topRightCornerFrame];
cover.backgroundColor = [UIColor whiteColor];
[webView addSubView:cover];

Show progress line over existing elements

Not sure if the title is very clear but I don't know the exact name for the thing I'm looking for. I have a gird that consists of UIButtons (basically a sequencer). I want a line similar to the vertical line in this image (between the 8th and 9th button of each row:
So basically when my grid is being played I want to indicate the progress. Any idea how I could do this? What kind of elements to use etc.
You can add a UIView that is very narrow, 1 or 1.5 pixels. Set the background color to white or a gradient. Add this view to the same subview as the buttons.
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(100.0, 0.0, 1.5, 320.0)];
lineView.backgroundColor = [UIColor whiteColor];
[parentView addSubview:lineView];
To show progress you'll need to know how much is left until completion. Take that value and divide by 320 to get the lineView height.
CGRect frame = CGRectMake(100.0, 0.0, 1.5, 0);
lineView.frame = frame; // 0% complete
frame = CGRectMake(100.0, 0.0, 1.5, 160.0);
lineView.frame = frame; // 50% complete
frame = CGRectMake(100.0, 0.0, 1.5, 320.0);
lineView.frame = frame; // 100% complete
That is the idea. Hope this help.
Update to vertical bar moving across the screen
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 1.5, 320.0)];
lineView.backgroundColor = [UIColor whiteColor];
[parentView addSubview:lineView];
As progress is made
- (void)progressWithValue(CGFloat)progress {
CGRect frame = lineView.frame;
frame.origin.x = progress; // Change x position
lineView.frame = frame;
}
You can use UISlider to show the progress of your events or activity(not so clear of your code) and customize it according to your needs.You can look at the UICatalog sample code by Apple to get to know-how of customizing a UISlider along with other elements or UISlider Tutorial

Resources