Issue in adding a shadow to view layer - iphone

In one of my view I am adding shadow to a view. Thing is that the shadow shows white spaces on left & right edges. I want to remove these spaces.
Here is my code:
UIView *myView = [[ISTView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 35)];
myView.backgroundColor = [UIColor greyColor];
[myView.layer setShadowOffset:CGSizeMake(0.0, 5.0)];
[myView.layer setShadowOpacity:0.8];
[myView.layer setShadowRadius:2.0];
[myView.layer setShadowColor:[UIColor blackColor].CGColor];
[self.view addSubview:myView];
[myView release];
Here is my view's o/p:

If you want homogenous shadow without side effects you can draw it in graphics editor, save to png and place UIImageView with stretchable image on your view. And don't forget to set clipToBounds to NO.
UIView *myView = [[ISTView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 35)];
myView.backgroundColor = [UIColor greyColor];
myView.clipToBounds = NO;
UIImageView *shadowView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 35, 320, 10)];
shadowView.image = [UIImage imageWithName:#"my-shadow.png"];
[myView addSubview:shadowView];
[shadowView release];
[self.view addSubview:myView];
[myView release];
It would be cheaper for system to draw cached existing image above view hierarcy than calculate layer's shadow.

Use shadowPath to make the shadow larger then the view
view.layer.shadowPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, view.frame.size.width+30, view.frame.size.height)].CGPath;

One solution I could think of and is working also is to adjust the view's frame by 2 pixels in X position and width:
UIView *myView = [[ISTView alloc] initWithFrame:CGRectMake(-2.0, 0.0, 324.0, 35)];
But this is not a cleaner approach of doing this. If anyone has better solution, please guide.

Try this, remove the code:
[myView.layer setShadowRadius:2.0];

Related

How to show delete button on top of the UIView

Please help me. I am phasing a problem, show a delete button on top of the view.
Without using bezier path showing like this
When i use bezier path is showing like this
how i can show the button.
This is the code i am using
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
[view1 setBackgroundColor:[UIColor orangeColor]];
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view1.bounds byRoundingCorners:UIRectCornerTopLeft| UIRectCornerTopRight cornerRadii:CGSizeMake(10.0, 10.0)];
// Create the shape layer and set its path
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = view1.bounds;
maskLayer.path = maskPath.CGPath;
// Set the newly created shape layer as the mask for the image view's layer
view1.layer.mask = maskLayer;
[self.view addSubview:view1];
UIButton *bt1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[bt1 setTitle:#"D" forState:UIControlStateNormal];
[bt1 setFrame:CGRectMake(87, -10, 25, 25)];
[view1 addSubview:bt1];
please help me. Thanks in advance.
You could always add the button in your superview depending of the view's position.
What #Larme said is true ,when you're making a view you're masking all the subviews that view has.
In case you don't want to do that just enter in your view's drawRect and draw there transparent corners to achieve the same effect.

Subview appears underneath superviews layer.border?

I have a UIView in which I define it's border in the following manner:
self.layer.borderColor = [UIColor blackColor].CGColor;
self.layer.borderWidth = 3;
I attach a subview to this UIView, and when I move the subview over the border, it goes underneath it. Is this the intended behavior? Is there anyway to make the subview go on top of it?
According to the Apple specification: It is composited above the receiver’s contents and sublayers.
So, the border will always be above of all your subviews, even if you bring your subview to the front and so on.
So I make a background view to fake the border.
E.g.:
UIView *backgroundView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
backgroundView.backgroundColor = [UIColor blackColor];
backgroundView.clipsToBounds = NO;
UIView *bView = [[UIView alloc] initWithFrame:CGRectInset(backgroundView.bounds, 3, 3)];
bView.backgroundColor = [UIColor redColor];
UIView *cView = [[UIView alloc] initWithFrame:CGRectMake(-50, -50, 100, 100)];
cView.backgroundColor = [UIColor yellowColor];
[bView addSubview:cView];
[backgroundView addSubview:bView];
[self.window addSubview:backgroundView];
and the effect:
Depending on your view structure, it might be easier to add the subview to the parent of your main view. It can then overlap the main view and will overlay the border as you requested.
Did you try setting the superview's 'clipsToBounds' property to YES? This is set to NO by default for performance reasons, but setting it to yes might give you the effect you are looking for.
Insert layer at specific position that suits you:
self.layer.insertSublayer(sublayer, at: 0)

ios changing depths of views opacity transition

I'm working on something that will require me to cycle through images and create some sort of fade in and fade out transition between them. I'm used to javascript, so naturally I would want change the depth of the imageview that is going to be faded in. Is there a way to choose which view shows on the top? Or is there a better way of doing what I want to achieve?
CGRect imageFrame = CGRectMake(0.0, 0.0, 1024.0, 280.0);
UIImageView *image_one = [[UIImageView alloc] initWithFrame:imageFrame];
image_one.image = [UIImage imageNamed:#"image_one.png"];
[self.view addSubview:image_one];
UIImageView *image_two = [[UIImageView alloc] initWithFrame:imageFrame];
image_two.image = [UIImage imageNamed:#"image_two.png"];
[self.view addSubview:image_two];
You can remove a view from the view hierarchy, then re-insert it using [UIView insertSubview:aboveSubview:] and [UIView insertSubview:belowSubview:].

highlight a part of the cell when selected

I am trying to add a non-standard color to the cell when its highlighted. FOr this i create a view with the background color that i want and set it as the selectedBackgroundView for the cell.
All is fine.
UIView *selectionView = [[UIView alloc] init];
[selectionView setBackgroundColor:[UIColor colorWithRed:(121/255.0) green:(201/255.0) blue:(209/255.0) alpha:1.0]];
[cell setSelectedBackgroundView:selectionView];
My question, can i change the frame of the selectedBackgroundView so that it highlights only a part of the cell (to be precise, i want the selectionBackroundView to have an X-offset of 20 pixels).
is there any easy way of doing this ?
Updated code :
UIView *selectionView = [[UIView alloc] init];
[selectionView setBackgroundColor:[UIColor clearColor]];
UIView *selectionSubView = [[UIView alloc] initWithFrame:(CGRectMake(20.0f, 0.0f, 300.0f, 72.0f))];
[selectionSubView setBackgroundColor:[UIColor colorWithRed:(121/255.0) green:(201/255.0) blue:(209/255.0) alpha:1.0]];
UIView *clearView = [[UIView alloc] initWithFrame:(CGRectMake(0.0f, 0.0f, 20.0f, 72.0f))];
[clearView setBackgroundColor: [UIColor clearColor]];
[selectionView addSubview: selectionSubView];
[selectionView addSubview: clearView];
[cell setSelectedBackgroundView: selectionView];
THis doesn seem to work either. I have added this code in the 'cellForRowAtIndexPath'
Thanks in advance
You could put a smaller UIView as subview of your selectionView and change tha background color of that view.
You can do like this.
You create the separate file for UIView as below.
TestView.m
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code.
[self setBackgroundColor:[UIColor clearColor]];
}
return self;
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
/* Draw a circle */
// Get the contextRef
CGContextRef contextRef = UIGraphicsGetCurrentContext();
// Set the border width
CGContextSetLineWidth(contextRef, 1.0);
// Set the circle fill color to GREEN
CGContextSetRGBFillColor(contextRef, 100.0, 255.0, 0.0, 1.0);
// Set the cicle border color to BLUE
CGContextSetRGBStrokeColor(contextRef, 0.0, 0.0, 255.0, 1.0);
// Fill the circle with the fill color
CGContextFillRect(contextRef, CGRectMake(20, 0, rect.size.width, rect.size.height));
// Draw the circle border
//CGContextStrokeRectWithWidth(contextRef, rect, 10);//(contextRef, rect);
}
And this Custom View you can use as a background View for cell selection like this.
TestView *bgView = [[TestView alloc] initWithFrame:cell.frame]; // Creating a view for the background...this seems to be required.
cell.selectedBackgroundView = bgView;
May be this help you.
Thanks,
Minesh Purohit.
Does the cell have fixed size and highlight area ?
If yes, create an image and use image view as the selectedBackgroundView
Try to set frame size for selectionView where x = 20. I am not sure about this but I guess it should work for your given scenario.

How to tint an image/show a colour?

2 things i want to do, which are related:
Show a block of any colour. So i could change that colour to something else at any time.
Tint a UIImage to be a different colour. An overlay of colour with alpha turned down could work here, but say it was an image which had a transparent background and didn't take up the full square of the image.
Any ideas?
Another option, would be to use category methods on UIImage like this...
// Tint the image, default to half transparency if given an opaque colour.
- (UIImage *)imageWithTint:(UIColor *)tintColor {
CGFloat white, alpha;
[tintColor getWhite:&white alpha:&alpha];
return [self imageWithTint:tintColor alpha:(alpha == 1.0 ? 0.5f : alpha)];
}
// Tint the image
- (UIImage *)imageWithTint:(UIColor *)tintColor alpha:(CGFloat)alpha {
// Begin drawing
CGRect aRect = CGRectMake(0.f, 0.f, self.size.width, self.size.height);
UIGraphicsBeginImageContext(aRect.size);
// Get the graphic context
CGContextRef c = UIGraphicsGetCurrentContext();
// Converting a UIImage to a CGImage flips the image,
// so apply a upside-down translation
CGContextTranslateCTM(c, 0, self.size.height);
CGContextScaleCTM(c, 1.0, -1.0);
// Draw the image
[self drawInRect:aRect];
// Set the fill color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextSetFillColorSpace(c, colorSpace);
// Set the mask to only tint non-transparent pixels
CGContextClipToMask(c, aRect, self.CGImage);
// Set the fill color
CGContextSetFillColorWithColor(c, [tintColor colorWithAlphaComponent:alpha].CGColor);
UIRectFillUsingBlendMode(aRect, kCGBlendModeColor);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Release memory
CGColorSpaceRelease(colorSpace);
return img;
}
The first one is easy. Make a new UIView and set its background color to whatever color you’d like.
The second is more difficult. As you mentioned, you can put a new view on top of it with transparency turned down, but to get it to clip in the same places, you’d want to use a mask. Something like this:
UIImage *myImage = [UIImage imageNamed:#"foo.png"];
UIImageView *originalImageView = [[UIImageView alloc] initWithImage:myImage];
[originalImageView setFrame:CGRectMake(0.0f, 0.0f, 100.0f, 100.0f)];
[parentView addSubview:originalImageView];
UIView *overlay = [[UIView alloc] initWithFrame:[originalImageView frame]];
UIImageView *maskImageView = [[UIImageView alloc] initWithImage:myImage];
[maskImageView setFrame:[overlay bounds]];
[[overlay layer] setMask:[maskImageView layer]];
[overlay setBackgroundColor:[UIColor redColor]];
[parentView addSubview:overlay];
Keep in mind you’ll have to #import <QuartzCore/QuartzCore.h> in the implementation file.
Here is another way to implement image tinting, especially if you are already using QuartzCore for something else.
Import QuartzCore:
#import <QuartzCore/QuartzCore.h>
Create transparent CALayer and add it as a sublayer for the image you want to tint:
CALayer *sublayer = [CALayer layer];
[sublayer setBackgroundColor:[UIColor whiteColor].CGColor];
[sublayer setOpacity:0.3];
[sublayer setFrame:toBeTintedImage.frame];
[toBeTintedImage.layer addSublayer:sublayer];
Add QuartzCore to your projects Framework list (if it isn't already there), otherwise you'll get compiler errors like this:
Undefined symbols for architecture i386: "_OBJC_CLASS_$_CALayer"
An easy way to achieve 1 is to create a UILabel or even a UIView and change the backgroundColor as you like.
There is a way to multiply colours instead of just overlaying them, and that should work for 2. See this tutorial.
Try this
- (void)viewDidLoad
{
[super viewDidLoad];
UIView* maskedView = [self filledViewForPNG:[UIImage imageNamed:#"mask_effect.png"]
mask:[UIImage imageNamed:#"mask_image.png"]
maskColor:[UIColor colorWithRed:.6 green:.2 blue:.7 alpha:1]];
[self.view addSubview:maskedView];
}
-(UIView*)filledViewForPNG:(UIImage*)image mask:(UIImage*)maskImage maskColor:(UIColor*)maskColor
{
UIImageView *pngImageView = [[UIImageView alloc] initWithImage:image];
UIImageView *maskImageView = [[UIImageView alloc] initWithImage:maskImage];
CGRect bounds;
if (image) {
bounds = pngImageView.bounds;
}
else
{
bounds = maskImageView.bounds;
}
UIView* parentView = [[UIView alloc]initWithFrame:bounds];
[parentView setAutoresizesSubviews:YES];
[parentView setClipsToBounds:YES];
UIView *overlay = [[UIView alloc] initWithFrame:bounds];
[[overlay layer] setMask:[maskImageView layer]];
[overlay setBackgroundColor:maskColor];
[parentView addSubview:overlay];
[parentView addSubview:pngImageView];
return parentView;
}