I have a Custom UIView inside my prototype cell in a nd iOS 8.2 app before it was a regular UIImage and i was getting it back fine with [currentCell viewWithTag:200]; inside my UITableView cellForRowIndexPath method. But after i have made a custom uiview and replaced the uiimage it always returns nil..
edit
After trying to add a new label to a working menu controller that is way more simple just loops over a array of strings. and setting the tag and in the loop (that is already printing the correct value out for the menu) it can't find the newly added label. is it possible to somehow not get the tags compiled ?
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *currentCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Lists *listItem = [lists objectAtIndex:indexPath.row];
if(currentCell == nil){
currentCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//THIS ALLWAYS RETUNS nil
ShadedBadgeImage *cellImage = (ShadedBadgeImage *)[currentCell viewWithTag:200];
//UIView *cellImage = (UIView *)[currentCell viewWithTag:200];
//cellImage.completedProcentage = 2.0 * listItem.id.doubleValue;
UILabel *cellTitle = (UILabel *) [currentCell viewWithTag:101];
UILabel *cellDescription = (UILabel *)[currentCell viewWithTag:102];
cellTitle.text = listItem.id.stringValue;
cellDescription.text = listItem.shortText;
return currentCell;
And my custom uiview. that is using the layoutSubviews to render the masked image and progress bar.
IB_DESIGNABLE
#implementation ShadedBadgeImage {
double lineWidth;
CAShapeLayer *backgroundLayer;
CAShapeLayer *coloredLayer;
CALayer *imageLayer;
}
- (void)baseInit {
lineWidth = 5.0;
[self updateStroke];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self baseInit];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
[self baseInit];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
//Adds the background ring layer
if(backgroundLayer == nil)
{
backgroundLayer = [[CAShapeLayer alloc] init];
CGRect rect = CGRectInset(self.bounds, lineWidth/2.0, lineWidth/2.0);
UIBezierPath *roundPath = [UIBezierPath bezierPathWithOvalInRect:rect];
backgroundLayer.path = roundPath.CGPath;
backgroundLayer.fillColor = nil;
backgroundLayer.lineWidth = lineWidth;
backgroundLayer.strokeColor = [UIColor colorWithWhite:0.5 alpha:0.05].CGColor;
[self.layer addSublayer:backgroundLayer];
}
backgroundLayer.frame = self.layer.frame;
//Adds the color ring layer
if(coloredLayer == nil)
{
coloredLayer = [[CAShapeLayer alloc] init];
CGRect rect = CGRectInset(self.bounds, lineWidth/2.0, lineWidth/2.0);
UIBezierPath *roundPath = [UIBezierPath bezierPathWithOvalInRect:rect];
coloredLayer.path = roundPath.CGPath;
coloredLayer.fillColor = nil;
coloredLayer.lineWidth = lineWidth;
coloredLayer.strokeColor = [UIColor blueColor].CGColor;
coloredLayer.anchorPoint = CGPointMake(0.5, 0.5);
coloredLayer.transform = CATransform3DRotate(coloredLayer.transform, -M_PI/2, 0, 0, 1);
[self.layer addSublayer:coloredLayer];
}
coloredLayer.frame = self.layer.frame;
//Adds the color ring layer
if(imageLayer == nil)
{
CAShapeLayer *imageMask = [[CAShapeLayer alloc] init];
CGRect insertBounds = CGRectInset(self.bounds, lineWidth + 3.0, lineWidth + 3.0);
UIBezierPath *innerPath = [UIBezierPath bezierPathWithOvalInRect:insertBounds];
imageMask.path = innerPath.CGPath;
imageMask.fillColor = [UIColor grayColor].CGColor;
imageMask.frame = self.bounds;
[self.layer addSublayer:imageMask];
imageLayer = [[CALayer alloc] init];
imageLayer.mask = imageMask;
imageLayer.frame = self.layer.frame;
imageLayer.backgroundColor =[UIColor grayColor].CGColor;
imageLayer.contentsGravity = kCAGravityResizeAspectFill;
[self.layer addSublayer:imageLayer];
}
[self updateStroke];
}
- (void) updateStroke{
if (coloredLayer != nil)
{
coloredLayer.strokeEnd = self.completedProcentage;
}
if(self.image != nil)
{
imageLayer.contents = (__bridge id)([self.image CGImage]);
}
}
#end
As the comments says, dont use tags go for custom UITableCellViews for more control
Related
I'm using a container for elements which I'd like for it to be blurred. In order to add rounded corners I modified the layer while for the shadow I created a second view named containerShadow and placed it below it.
It works, but not flawlessly. The shadow darkens the effect of the blur. Is there a way to perfect it?
.h
#property (strong) UIVisualEffectView *containerView;
#property (strong) UIView *containerShadowView;
.m
- (instancetype)init {
if (self = [super init]) {
self.containerShadowView = [[UIView alloc] init];
self.containerShadowView.layer.masksToBounds = NO;
self.containerShadowView.layer.shadowRadius = 80.0;
self.containerShadowView.layer.shadowColor = [[UIColor blackColor] CGColor];
self.containerShadowView.layer.shadowOffset = CGSizeZero;
self.containerShadowView.layer.shadowOpacity = 0.25;
[self addSubview:self.containerShadowView];
self.containerView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]];
self.containerView.clipsToBounds = YES;
self.containerView.layer.cornerRadius = 20.0;
[self addSubview:self.containerView];
}
return self;
}
- (void)setFrame:(CGRect)frame {
[super setFrame:frame];
// Random container frame for testing...
self.containerView.frame =
CGRectMake(20.0,
200.0,
380,
480);
self.containerShadowView.frame = self.containerView.frame;
self.containerShadowView.layer.shadowPath =
[[UIBezierPath bezierPathWithRoundedRect:self.containerShadowView.bounds cornerRadius:self.containerView.layer.cornerRadius] CGPath];
}
You can do this by masking your containerShadowView with a "cutout" that matches the containerView effect view.
So, this is how it looks - I centered the 380x480 view, and used 0.9 for the .shadowOpacity to emphasize the differences.
Your original on the left, masked version on the right:
Kinda difficult to tell what's really going on, since that could be an opaque layer, we'll add a label behind it:
and, to clarify what we're doing, let's look at it with the containerView effect view hidden:
Here's the source code I used for that - each tap anywhere will cycle through the 8 different layouts:
#import <UIKit/UIKit.h>
#interface OrigShadowView : UIView
#property (strong) UIVisualEffectView *containerView;
#property (strong) UIView *containerShadowView;
#end
#implementation OrigShadowView
- (instancetype)init {
if (self = [super init]) {
self.containerShadowView = [[UIView alloc] init];
self.containerShadowView.layer.masksToBounds = NO;
self.containerShadowView.layer.shadowRadius = 80.0;
self.containerShadowView.layer.shadowColor = [[UIColor blackColor] CGColor];
self.containerShadowView.layer.shadowOffset = CGSizeZero;
self.containerShadowView.layer.shadowOpacity = 0.9;
[self addSubview:self.containerShadowView];
self.containerView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]];
self.containerView.clipsToBounds = YES;
self.containerView.layer.cornerRadius = 20.0;
[self addSubview:self.containerView];
}
return self;
}
- (void)setFrame:(CGRect)frame {
[super setFrame:frame];
// let's center a 380 x 480 rectangle in self
CGFloat w = 380.0;
CGFloat h = 480.0;
CGRect vRect = CGRectMake((frame.size.width - w) * 0.5, (frame.size.height - h) * 0.5, w, h);
self.containerView.frame = vRect;
self.containerShadowView.frame = self.containerView.frame;
// change origin to 0,0 because the following will be relative to the subviews
vRect.origin = CGPointZero;
self.containerShadowView.layer.shadowPath =
[[UIBezierPath bezierPathWithRoundedRect:vRect cornerRadius:self.containerView.layer.cornerRadius] CGPath];
}
#end
#interface MaskShadowView : UIView
#property (strong) UIVisualEffectView *containerView;
#property (strong) UIView *containerShadowView;
#end
#implementation MaskShadowView
- (instancetype)init {
if (self = [super init]) {
self.containerShadowView = [[UIView alloc] init];
self.containerShadowView.layer.masksToBounds = NO;
self.containerShadowView.layer.shadowRadius = 80.0;
self.containerShadowView.layer.shadowColor = [[UIColor blackColor] CGColor];
self.containerShadowView.layer.shadowOffset = CGSizeZero;
self.containerShadowView.layer.shadowOpacity = 0.9;
[self addSubview:self.containerShadowView];
self.containerView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]];
self.containerView.clipsToBounds = YES;
self.containerView.layer.cornerRadius = 20.0;
[self addSubview:self.containerView];
}
return self;
}
- (void)setFrame:(CGRect)frame {
[super setFrame:frame];
// let's center a 380 x 480 rectangle in self
CGFloat w = 380.0;
CGFloat h = 480.0;
CGRect vRect = CGRectMake((frame.size.width - w) * 0.5, (frame.size.height - h) * 0.5, w, h);
self.containerView.frame = vRect;
self.containerShadowView.frame = self.containerView.frame;
// change origin to 0,0 because the following will be relative to the subviews
vRect.origin = CGPointZero;
self.containerShadowView.layer.shadowPath =
[[UIBezierPath bezierPathWithRoundedRect:vRect cornerRadius:self.containerView.layer.cornerRadius] CGPath];
UIBezierPath *bigBez;
UIBezierPath *clipBez;
// we need a rectangle that will encompass the shadow radius
// double the shadowRadius is probably sufficient, but since it won't be seen
// and won't affect anything else, we'll make it 4x
CGRect expandedRect = CGRectInset(vRect, -self.containerShadowView.layer.shadowRadius * 4.0, -self.containerShadowView.layer.shadowRadius * 4.0);
bigBez = [UIBezierPath bezierPathWithRect:expandedRect];
// we want to "clip out" a rounded rect in the center
// which will be the same size as the visual effect view
clipBez = [UIBezierPath bezierPathWithRoundedRect:vRect cornerRadius:self.containerView.layer.cornerRadius];
[bigBez appendPath:clipBez];
bigBez.usesEvenOddFillRule = YES;
CAShapeLayer *maskLayer = [CAShapeLayer new];
maskLayer.fillRule = kCAFillRuleEvenOdd;
maskLayer.fillColor = UIColor.whiteColor.CGColor;
maskLayer.path = bigBez.CGPath;
self.containerShadowView.layer.mask = maskLayer;
}
#end
#interface BlurTestViewController : UIViewController
{
OrigShadowView *origView;
MaskShadowView *newView;
UILabel *bkgLabel;
// so we can step through on taps to see the results
NSInteger step;
UILabel *infoLabel;
}
#end
#implementation BlurTestViewController
- (void)viewDidLoad {
[super viewDidLoad];
bkgLabel = [UILabel new];
bkgLabel.textColor = UIColor.blueColor;
bkgLabel.font = [UIFont systemFontOfSize:48.0 weight:UIFontWeightBlack];
bkgLabel.textAlignment = NSTextAlignmentCenter;
bkgLabel.numberOfLines = 0;
bkgLabel.text = #"A label can contain an arbitrary amount of text, but UILabel may shrink, wrap, or truncate the text, depending on the size of the bounding rectangle and properties you set. You can control the font, text color, alignment, highlighting, and shadowing of the text in the label.";
bkgLabel.text = #"I'm using a container for elements which I'd like for it to be blurred. In order to add rounded corners I modified the layer while for the shadow I created a second view named containerShadow and placed it below it.";
origView = [OrigShadowView new];
newView = [MaskShadowView new];
[self.view addSubview:bkgLabel];
[self.view addSubview:origView];
[self.view addSubview:newView];
infoLabel = [UILabel new];
infoLabel.font = [UIFont systemFontOfSize:20.0 weight:UIFontWeightBold];
infoLabel.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:infoLabel];
step = 0;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// let's inset the "shadow blur" views 40-points
CGRect r = CGRectInset(self.view.frame, 40.0, 40.0);
origView.frame = r;
newView.frame = r;
// let's put the background label midway down the screen
r.origin.y += r.size.height * 0.5;
r.size.height *= 0.5;
bkgLabel.frame = r;
// put the info label near the top
infoLabel.frame = CGRectMake(40.0, 80.0, r.size.width, 40.0);
[self nextStep];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self nextStep];
}
- (void)nextStep {
bkgLabel.hidden = YES;
origView.hidden = YES;
newView.hidden = YES;
origView.containerView.hidden = NO;
newView.containerView.hidden = NO;
step++;
switch (step) {
case 1:
origView.hidden = NO;
infoLabel.text = #"1: Original View";
break;
case 2:
newView.hidden = NO;
infoLabel.text = #"2: Masked View";
break;
case 3:
bkgLabel.hidden = NO;
origView.hidden = NO;
infoLabel.text = #"3: Original View";
break;
case 4:
bkgLabel.hidden = NO;
newView.hidden = NO;
infoLabel.text = #"4: Masked View";
break;
case 5:
origView.hidden = NO;
origView.containerView.hidden = YES;
infoLabel.text = #"5: Original View - effect view hidden";
break;
case 6:
newView.hidden = NO;
newView.containerView.hidden = YES;
infoLabel.text = #"6: Masked View - effect view hidden";
break;
case 7:
bkgLabel.hidden = NO;
origView.hidden = NO;
origView.containerView.hidden = YES;
infoLabel.text = #"7: Original View - effect view hidden";
break;
default:
bkgLabel.hidden = NO;
newView.hidden = NO;
newView.containerView.hidden = YES;
infoLabel.text = #"8: Masked View - effect view hidden";
step = 0;
break;
}
}
#end
I am working on collage app and in collage view I need to set border width and corner radius of frame, the view will be a sublayer of another view and the back view will have background colour as brown.I am able to change the border width and corner radius using slider but after doing that I am getting small tiny border white line (like a shadow) around the view.I tried using shadow opacity but it didn't work. below is my code.
- (IBAction)sliderActionToChangeCornerWidthOfView:(id)sender {
UISlider *slider = (UISlider*)sender;
int i=0;
for (CollageView *viewCollage in self.collageView.subviews) {
if ([viewCollage isKindOfClass:[CollageView class]]) {
self.appDelg.borderWidth = slider.value/2;
if ([[array objectAtIndex:i] valueForKey:#"path"]!=nil) {
if (arrayOfLayers.count > 0) {
[arrayOfLayers makeObjectsPerformSelector:#selector(removeFromSuperlayer)];
}
NSMutableArray *arrayToRadius = [[NSMutableArray alloc] init];
arrayToRadius = [arrayToRadius getArrayOfCollages:_collageView.bounds.size numberOfCollages:numberOfCollages];
NSArray *arrayToChangeCornerRadius=[[[arrayToRadius objectAtIndex:btnClickIndex] valueForKey:#"values"] objectAtIndex:0];
UIBezierPath *starPath=[[arrayToChangeCornerRadius objectAtIndex:i] valueForKey:#"path"];
CAShapeLayer *cornerMaskLayer = [CAShapeLayer layer];
[cornerMaskLayer setPath:starPath.CGPath];
viewCollage.layer.mask = cornerMaskLayer;
CAShapeLayer *strokeLayer = [CAShapeLayer layer];
strokeLayer.path = starPath.CGPath;
strokeLayer.lineWidth = self.appDelg.borderWidth;
strokeLayer.lineJoin = kCALineJoinRound;
// the stroke splits the width evenly inside and outside,
strokeLayer.fillColor = [UIColor clearColor].CGColor;
if (patternImage!=nil) {
strokeLayer.strokeColor = [UIColor colorWithPatternImage:[self patterDraw]].CGColor;
}
else
{
strokeLayer.strokeColor = borderColour.CGColor;
}
CGRect rect=CGPathGetBoundingBox(starPath.CGPath);
[viewCollage layoutIfNeeded];
strokeLayer.shadowOpacity = 0.0;
[arrayOfLayers addObject:strokeLayer];
[viewCollage.layer addSublayer:strokeLayer];
NSLog(#"value : %#", NSStringFromCGRect(viewCollage.frame) );
}
else
{
if (patternImage!=nil) {
viewCollage.layer.borderColor = [UIColor colorWithPatternImage:[self patterDraw]].CGColor;
}
else
{
viewCollage.layer.borderColor = borderColour.CGColor;
}
viewCollage.layer.borderWidth = slider.value/2;
}
i++;
}
}
}
- (IBAction)sliderActionToChangeCornerRadius:(id)sender {
UISlider *slider = (UISlider*)sender;
int i = 0;
for (CollageView *viewCollage in self.collageView.subviews) {
if ([viewCollage isKindOfClass:[CollageView class]]) {
self.appDelg.cornerRadiusValue = slider.value;
if ([[array objectAtIndex:i] valueForKey:#"path"]!=nil) {
if (arrayOfLayers.count > 0) {
[arrayOfLayers makeObjectsPerformSelector:#selector(removeFromSuperlayer)];
}
NSMutableArray *arrayToRadius = [[NSMutableArray alloc] init];
arrayToRadius = [arrayToRadius getArrayOfCollages:_collageView.bounds.size numberOfCollages:numberOfCollages];
NSArray *arrayToChangeCornerRadius=[[[arrayToRadius objectAtIndex:btnClickIndex] valueForKey:#"values"] objectAtIndex:0];
UIBezierPath *starPath=[[arrayToChangeCornerRadius objectAtIndex:i] valueForKey:#"path"];
CAShapeLayer *cornerMaskLayer = [CAShapeLayer layer];
[cornerMaskLayer setPath:starPath.CGPath];
viewCollage.layer.mask = cornerMaskLayer;
CAShapeLayer *strokeLayer = [CAShapeLayer layer];
strokeLayer.path = starPath.CGPath;
strokeLayer.lineWidth = self.appDelg.borderWidth;
strokeLayer.lineJoin = kCALineJoinRound;
// the stroke splits the width evenly inside and outside,
strokeLayer.fillColor = [UIColor clearColor].CGColor;
if (patternImage!=nil) {
strokeLayer.strokeColor = [UIColor colorWithPatternImage:[self patterDraw]].CGColor;
}
else
{
strokeLayer.strokeColor = borderColour.CGColor;
}
CGRect rect=CGPathGetBoundingBox(starPath.CGPath);
[viewCollage layoutIfNeeded];
[arrayOfLayers addObject:strokeLayer];
[viewCollage.layer addSublayer:strokeLayer];
NSLog(#"value : %#", NSStringFromCGRect(viewCollage.frame) );
}
else
{
viewCollage.layer.cornerRadius = slider.value;
}
i++;
}
}
}
Below is the screenshot of the issue which I am facing
Can anyone please help me on this issue.
You can get angle of view by following code:-
CGFloat radians = atan2f(view.transform.b, view.transform.a);
CGFloat degrees = radians * (180 / M_PI);
Can you try once by adding following line:-
UIImageView.clipsToBounds to YES
It will help to get radians and degrees of rotation of particular view.
Hope it works!
End Goal
I'm doing a tooltip feature for one of my views. The tooltip view will be presented in a modal fashion over the view it's giving tips on. Most of the view will be a dark translucent background, except for one or two key points that need to be completely translucent. These points would be circles or rectangles themselves.
Basically I need to create a UIImage so it can go nicely into a UIImageView.
So far...
Currently I know how to draw an image with one color of any size:
- (UIImage *)imageWithColor:(UIColor *)color scaledToSize:(CGSize)size {
UIImage *image;
CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillRect(context, rect);
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
In other words...
In other words, I could use the above code to make a translucent rectangle. Then all I'd need to do is find a way to "punch holes" in the rectangle of certain sizes at certain points.
Question
How can I create these "keyhole"-like images? Is there another approach?
I don't think you need to do this with an image. You can do it with a CALayer with a mask that's the same size as the view, with added sublayers that are opaque (which will act as holes). The code below adds a darkened layer with square and a circle "holes".
-(IBAction)addMask:(id)sender {
CALayer *maskLayer = [CALayer layer];
maskLayer.frame = self.view.bounds;
CALayer *square = [CALayer layer];
square.frame = CGRectMake(100, 200, 50, 50);
square.backgroundColor = [UIColor blackColor].CGColor;
CAShapeLayer *circle = [CAShapeLayer layer];
UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(150, 280, 50, 50)];
circle.path = circlePath.CGPath;
[maskLayer addSublayer:square];
[maskLayer addSublayer:circle];
maskLayer.backgroundColor = [UIColor colorWithWhite:1 alpha:.4].CGColor;
self.view.layer.mask = maskLayer;
}
Here is my full tooltip solution. Credit goes to #rdelmar for showing me that a UIIMage was not needed.
It's probably redundant in some places and the frame work looks atrocious, but it gets the job done. I'd love to hear some improvements:
Home.h file
#property (strong, nonatomic) CALayer *maskLayer;
#property (strong, nonatomic) CATextLayer *profileTitleLayerBack;
#property (strong, nonatomic) CATextLayer *profileDetailLayerBack;
#property (strong, nonatomic) CATextLayer *checkinTitleLayerBack;
#property (strong, nonatomic) CATextLayer *checkinDetailLayerBack;
#property (strong, nonatomic) CATextLayer *dismissLayerBack;
#property (strong, nonatomic) UIButton *tooltipButton;
Home.m file
- (void)viewDidLoad {
[super viewDidLoad];
if ([self firstTimeViewingHome]) {
[self showTooltipLayers];
}
}
//FYI if you want to allow the user to see the tooltip again - just remove the 'DoesNotNeedHomeTooltip' key
- (BOOL)firstTimeViewingHome {
BOOL firstTime = YES;
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"DoesNotNeedHomeTooltip"])
{
firstTime = NO;
}
else {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"DoesNotNeedHomeTooltip"];
[[NSUserDefaults standardUserDefaults] synchronize];
firstTime = YES;
}
return firstTime;
}
- (void)showTooltipLayers {
//I use JASidePanels so if I want to mask the full screen I need to use its view that I store in my session controller
UIView *sidePanelView = self.sessionController.sidePanelController.view;
//A mask is used to cover the view
self.maskLayer = [CALayer layer];
self.maskLayer.frame = sidePanelView.bounds;
self.maskLayer.backgroundColor = [UIColor colorWithWhite:1 alpha:.25].CGColor;
sidePanelView.layer.mask = self.maskLayer;
//Shapes are then used to highlight points in view behind the mask
CAShapeLayer *circle1 = [CAShapeLayer layer];
UIBezierPath *circlePath1 = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-4, 10, 60, 60)];
circle1.path = circlePath1.CGPath;
[self.maskLayer addSublayer:circle1];
CAShapeLayer *circle2 = [CAShapeLayer layer];
CGRect checkinCircleFrame = CGRectMake(sidePanelView.frame.size.width/2 - 35, sidePanelView.frame.size.height - 65, 70, 70);
UIBezierPath *circlePath2 = [UIBezierPath bezierPathWithOvalInRect:checkinCircleFrame];
circle2.path = circlePath2.CGPath;
[self.maskLayer addSublayer:circle2];
//Text Layers
//
//Each layer is added twice.
//
//The first layer goes in the back (in the main view).
//
//The second layer goes in front (in the mask),
//creating a clear window to the text layer in the back.
//
//This solution was used because the front layer text color
//could not be changed to white (only clear).
//Using only white in the back results being affected by the mask
//Title for Profile tip
self.profileTitleLayerBack = [[CATextLayer alloc] init];
self.profileTitleLayerBack.contentsScale = UIScreen.mainScreen.scale;
self.profileTitleLayerBack.frame = CGRectMake(30, 70, 250, 40);
self.profileTitleLayerBack.font = (__bridge CFTypeRef)(#"Oswald-Light");
self.profileTitleLayerBack.fontSize = 35;
self.profileTitleLayerBack.alignmentMode = kCAAlignmentLeft;
self.profileTitleLayerBack.string = #"OBFUSCATED";
self.profileTitleLayerBack.foregroundColor = UIColor.whiteColor.CGColor;
[sidePanelView.layer addSublayer:self.profileTitleLayerBack];
CATextLayer *profileTitleLayerFront = [[CATextLayer alloc] init];
profileTitleLayerFront.contentsScale = UIScreen.mainScreen.scale;
profileTitleLayerFront.frame = self.profileTitleLayerBack.frame;
profileTitleLayerFront.font = self.profileTitleLayerBack.font;
profileTitleLayerFront.fontSize = self.profileTitleLayerBack.fontSize;
profileTitleLayerFront.alignmentMode = self.profileTitleLayerBack.alignmentMode;
profileTitleLayerFront.string = self.profileTitleLayerBack.string;
[self.maskLayer addSublayer:profileTitleLayerFront];
//Detail for Profile Tip
self.profileDetailLayerBack = [[CATextLayer alloc] init];
self.profileDetailLayerBack.contentsScale = UIScreen.mainScreen.scale;
self.profileDetailLayerBack.frame = CGRectMake(self.profileTitleLayerBack.frame.origin.x + 5,
self.profileTitleLayerBack.frame.origin.y +
self.profileTitleLayerBack.frame.size.height + 8,
300,
150);
self.profileDetailLayerBack.font = (__bridge CFTypeRef)(#"Oswald-Light");
self.profileDetailLayerBack.fontSize = 20;
self.profileDetailLayerBack.alignmentMode = kCAAlignmentLeft;
self.profileDetailLayerBack.string = #"This is your space.\nEverything about your obfuscated,\nobfuscated, and obfuscated.";
self.profileDetailLayerBack.foregroundColor = UIColor.whiteColor.CGColor;
[sidePanelView.layer addSublayer:self.profileDetailLayerBack];
CATextLayer *profileDetailLayerFront = [[CATextLayer alloc] init];
profileDetailLayerFront.contentsScale = UIScreen.mainScreen.scale;
profileDetailLayerFront.frame = self.profileDetailLayerBack.frame;
profileDetailLayerFront.font = self.profileDetailLayerBack.font;
profileDetailLayerFront.fontSize = self.profileDetailLayerBack.fontSize;
profileDetailLayerFront.alignmentMode = self.profileDetailLayerBack.alignmentMode;
profileDetailLayerFront.string = self.profileDetailLayerBack.string;
[self.maskLayer addSublayer:profileDetailLayerFront];
//Title for Checkin tip
self.checkinTitleLayerBack = [[CATextLayer alloc] init];
self.checkinTitleLayerBack.contentsScale = UIScreen.mainScreen.scale;
self.checkinTitleLayerBack.frame = CGRectMake(sidePanelView.frame.size.width/2 - 125,
checkinCircleFrame.origin.y - 40 - 115,
250,
40);
self.checkinTitleLayerBack.font = (__bridge CFTypeRef)(#"Oswald-Light");
self.checkinTitleLayerBack.fontSize = 35;
self.checkinTitleLayerBack.alignmentMode = kCAAlignmentCenter;
self.checkinTitleLayerBack.string = #"OBFUSCATED";
self.checkinTitleLayerBack.foregroundColor = UIColor.whiteColor.CGColor;
[sidePanelView.layer addSublayer:self.checkinTitleLayerBack];
CATextLayer *checkinTitleLayerFront = [[CATextLayer alloc] init];
checkinTitleLayerFront.contentsScale = UIScreen.mainScreen.scale;
checkinTitleLayerFront.frame = self.checkinTitleLayerBack.frame;
checkinTitleLayerFront.font = self.checkinTitleLayerBack.font;
checkinTitleLayerFront.fontSize = self.checkinTitleLayerBack.fontSize;
checkinTitleLayerFront.alignmentMode = self.checkinTitleLayerBack.alignmentMode;
checkinTitleLayerFront.string = self.checkinTitleLayerBack.string;
[self.maskLayer addSublayer:checkinTitleLayerFront];
//Detail for Checkin Tip
self.checkinDetailLayerBack = [[CATextLayer alloc] init];
self.checkinDetailLayerBack.contentsScale = UIScreen.mainScreen.scale;
self.checkinDetailLayerBack.frame = CGRectMake(sidePanelView.frame.size.width/2 - 150,
checkinCircleFrame.origin.y - 115 + 8,
300,
150);
self.checkinDetailLayerBack.font = (__bridge CFTypeRef)(#"Oswald-Light");
self.checkinDetailLayerBack.fontSize = 20;
self.checkinDetailLayerBack.alignmentMode = kCAAlignmentCenter;
self.checkinDetailLayerBack.string = #"Tap to view your obfuscated\nobfuscated and check in to your\nobfuscated and obfuscated.";
self.checkinDetailLayerBack.foregroundColor = UIColor.whiteColor.CGColor;
[sidePanelView.layer addSublayer:self.checkinDetailLayerBack];
CATextLayer *checkinDetailLayerFront = [[CATextLayer alloc] init];
checkinDetailLayerFront.contentsScale = UIScreen.mainScreen.scale;
checkinDetailLayerFront.frame = self.checkinDetailLayerBack.frame;
checkinDetailLayerFront.font = self.checkinDetailLayerBack.font;
checkinDetailLayerFront.fontSize = self.checkinDetailLayerBack.fontSize;
checkinDetailLayerFront.alignmentMode = self.checkinDetailLayerBack.alignmentMode;
checkinDetailLayerFront.string = self.checkinDetailLayerBack.string;
[self.maskLayer addSublayer:checkinDetailLayerFront];
//Add a notice disclosing how to dismiss the tooltip
self.dismissLayerBack = [[CATextLayer alloc] init];
self.dismissLayerBack.contentsScale = UIScreen.mainScreen.scale;
self.dismissLayerBack.frame = CGRectMake(sidePanelView.frame.size.width/2 - 75,
sidePanelView.frame.size.height/2 - 10,
150,
20);
self.dismissLayerBack.font = (__bridge CFTypeRef)(#"Oswald-Light");
self.dismissLayerBack.fontSize = 16;
self.dismissLayerBack.alignmentMode = kCAAlignmentCenter;
self.dismissLayerBack.string = #"(Tap anywhere to dismiss)";
self.dismissLayerBack.foregroundColor = self.view.backgroundColor.CGColor;
[sidePanelView.layer addSublayer:self.dismissLayerBack];
CATextLayer *dismissLayerFront = [[CATextLayer alloc] init];
dismissLayerFront.contentsScale = UIScreen.mainScreen.scale;
dismissLayerFront.frame = self.dismissLayerBack.frame;
dismissLayerFront.font = self.dismissLayerBack.font;
dismissLayerFront.fontSize = self.dismissLayerBack.fontSize;
dismissLayerFront.alignmentMode = self.dismissLayerBack.alignmentMode;
dismissLayerFront.string = self.dismissLayerBack.string;
[self.maskLayer addSublayer:dismissLayerFront];
//Add a clear button over top the view
self.tooltipButton = [[UIButton alloc] initWithFrame:CGRectMake(sidePanelView.frame.origin.x,
sidePanelView.frame.origin.y,
sidePanelView.frame.size.width,
sidePanelView.frame.size.height)];
self.tooltipButton.backgroundColor = UIColor.clearColor;
[self.tooltipButton addTarget:self action:#selector(tooltipButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[sidePanelView addSubview:self.tooltipButton];
[sidePanelView bringSubviewToFront:self.tooltipButton];
}
//dismisses the tooltip view / cleans up
- (void)tooltipButtonPressed {
self.sessionController.sidePanelController.view.layer.mask = nil;
self.maskLayer = nil;
[self.profileTitleLayerBack removeFromSuperlayer];
self.profileTitleLayerBack = nil;
[self.profileDetailLayerBack removeFromSuperlayer];
self.profileDetailLayerBack = nil;
[self.checkinTitleLayerBack removeFromSuperlayer];
self.checkinTitleLayerBack = nil;
[self.checkinDetailLayerBack removeFromSuperlayer];
self.checkinDetailLayerBack = nil;
[self.dismissLayerBack removeFromSuperlayer];
self.dismissLayerBack = nil;
[self.tooltipButton removeFromSuperview];
self.tooltipButton = nil;
}
I've created this custom UIView named RoundView:
#import <QuartzCore/QuartzCore.h>
#implementation RoundedView
+(UIColor *)grayUIColor {
return [UIColor colorWithRed:161.0/255.0 green:157.0/255.0 blue:164.0/255.0 alpha:1.0];
}
+(UIColor *)darkBlueUIColor {
return [UIColor colorWithRed:86.0/255.0 green:88.0/255.0 blue:87.0/255.0 alpha:1];
}
+(UIColor *)greenUIColor {
return [UIColor colorWithRed:51.0/255.0 green:141.0/255.0 blue:130.0/255.0 alpha:1];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self)
{
//add pico icon as default image
_defaultImage = [UIImage imageNamed:#"actionBar_pico_icon"];
_isCreated = NO;
}
return self;
}
-(UIView*)createRoundViewWithBorder:(UIColor*)borderColor andPaddingColor:(UIColor*)paddingColor{
_borderColor = borderColor;
_paddingBackgroundColor = paddingColor;
[self setViewAppearance];
[self addImageToView];
_isCreated = YES;
return self;
}
/**
Set the current view appearance
*/
-(void) setViewAppearance {
self.layer.borderWidth = 1.5;
self.layer.borderColor = [_borderColor CGColor];
self.backgroundColor = _paddingBackgroundColor;
}
-(void) addImageToView {
CGRect frame = CGRectMake(0, 0, self.frame.size.width - 5, self.frame.size.height - 5);
_imageView = [[UIImageView alloc] initWithFrame:frame];
//calculate center x
float x = (self.frame.size.width - _imageView.frame.size.width) / 2;
//calculate center y
float y = (self.frame.size.height - _imageView.frame.size.height) / 2;
//create new frame
frame = CGRectMake(x, y, _imageView.frame.size.width, _imageView.frame.size.height);
_imageView.image = _defaultImage;
_imageView.frame = frame;
_imageView.contentMode = UIViewContentModeScaleAspectFit;
[self addSubview:_imageView];
[self makeViewRounded:_imageView];
[self makeViewRounded:self];
}
-(UIView*) makeViewRounded:(UIView*)view {
//set the look of the image
view.layer.cornerRadius= self.frame.size.height /2;
view.layer.opaque = NO;
view.layer.masksToBounds = YES;
return view;
}
-(void)updateImage:(UIImage *)image {
_image = image;
_imageView.image = image;
}
-(void)reset {
[self updateImage:_defaultImage];
}
#end
an example for the output will be :
If you look closely you will notice that the border is a circle, but the image view has edges.
How can i make the Image smooth as well ?
self.imgViewbg.layer.cornerRadius = self.imgViewbg.frame.size.width / 2;
self.imgViewbg.clipsToBounds = YES;
u Can Try This Code. And Implement in your Project..
It Will Definetly Work.. for u
I think the problem seems to be here:
view.layer.cornerRadius= self.frame.size.height /2;
Try giving it a constant small number and see the change. May be the height/2 is not making a perfect circle. You can give a smaller value than height/2 and see the change. It a wild guess by watching your image.
In my app I'm using the PSCollectionView to create a view similar to pinterest. Now I'm trying to pass from my class to the cell class a value in which I insert the height of the imageView I set in the cell. When I run the app, the app create a cell exactly using this height, but the imageView has no dimension.
I post here my code:
PSCollectionView controller
- (CGFloat)collectionView:(PSCollectionView *)collectionView heightForRowAtIndex:(NSInteger)index {
NSString *width = [self.arrayWithData[index] objectForKey:#"width"];
NSString *height = [self.arrayWithData[index] objectForKey:#"height"];
NSLog(#"%# e %#", width, height);
cellHeight = [self getHeightWith:width andHeight:height];
return cellHeight;
}
- (CGFloat)getHeightWith:(NSString *)originalWidth andHeight:(NSString *)originalHeight {
float width = [originalWidth floatValue];
float height = [originalHeight floatValue];
float multiplier = height / width;
// So che la mia cella ha una dimensione massima in larghezza di 100, da questo calcolo l'altezza
return 100 * multiplier;
}
- (PSCollectionViewCell *)collectionView:(PSCollectionView *)collectionView cellForRowAtIndex:(NSInteger)index {
ProductViewCell *cell = (ProductViewCell *)[self.psView dequeueReusableViewForClass:nil];
if (!cell) {
//cell = [[ProductViewCell alloc]initWithFrame:CGRectMake(10, 70, 100, 100)];
//cell = [[ProductViewCell alloc] initWithFrame:CGRectMake(0,0,collectionView.frame.size.width/2,100)];
cell = [[ProductViewCell alloc] initWithFrame:CGRectMake(0,0,collectionView.frame.size.width/2,cellHeight + 20)];
}
cell.imageHeight = cellHeight;
cell.labelName.text = [[self.arrayWithData objectAtIndex:index]objectForKey:#"name"];
NSURL * url = [NSURL URLWithString:[[self.arrayWithData objectAtIndex:index]objectForKey:#"url"]];
[self loadImageFromWeb:url andImageView:cell.productImage];
return cell;
}
- (void) loadImageFromWeb:(NSURL *)urlImg andImageView:(UIImageView *)imageView {
//NSURLRequest* request = [NSURLRequest requestWithURL:url];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:urlImg];
NSString *authCredentials =#"reply:reply";
NSString *authValue = [NSString stringWithFormat:#"Basic %#",[authCredentials base64EncodedStringWithWrapWidth:0]];
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
if (!error){
UIImage *image = [[UIImage alloc] initWithData:data];
[imageView setImage:image];
[HUD hide:YES];
} else {
NSLog(#"ERRORE: %#", error);
}
}];
}
and this code:
ProductViewCell.h
#import "PSCollectionViewCell.h"
#interface ProductViewCell : PSCollectionViewCell {
float wMargin;
}
#property(nonatomic,strong)UIImageView *productImage;
#property(nonatomic,strong)UILabel *labelName;
// I use this variable to pass the height of the cell from the class who implement PSCollectionView
#property CGFloat imageHeight;
+ (CGFloat)heightForViewWithObject:(id)object inColumnWidth:(CGFloat)cloumnWidth;
#end
ProductViewCell.m
#import "ProductViewCell.h"
#define MARGIN 8.0
#implementation ProductViewCell
- (id)initWithFrame:(CGRect)frame
{
wMargin = 5.0;
self = [super initWithFrame:frame];
if (self) {
// self.productImage = [[UIImageView alloc]initWithFrame:CGRectMake(wMargin, 5, frame.size.width - (wMargin * 2), 125)];
self.productImage = [[UIImageView alloc]initWithFrame:CGRectMake(wMargin, 5, frame.size.width - (wMargin * 2), self.imageHeight)];
self.labelName = [[UILabel alloc]initWithFrame:CGRectMake(wMargin, 130, frame.size.width - (wMargin * 2), 20)];
self.labelName.font = [self.labelName.font fontWithSize:12];
self.labelName.textAlignment = NSTextAlignmentCenter;
[self addSubview:self.productImage];
[self addSubview:self.labelName];
self.backgroundColor = [UIColor colorWithRed:236.0f/255.0f green:236.0f/255.0f blue:236.0f/255.0f alpha:1.0];
self.layer.masksToBounds = YES;
self.layer.borderWidth = 1.0f;
self.layer.cornerRadius = 10.0f;
self.layer.borderColor= [[UIColor colorWithRed:207.0f/255.0f green:207.0f/255.0f blue:207.0f/255.0f alpha:1] CGColor];
[self.productImage setContentMode:UIViewContentModeScaleAspectFit];
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
When I try to log the value of self.imageHeight it shows in the console a 0, but you can see that I set this data to cellHeight in the PSCollectionView controller.
How I can send the data I calculate to my cell? There's a way to do that?
According to the provided code, the class property imageHeight in the ProductViewCell implementation is only used when a new cell is initialized. At that time the imageHeight has never been set or updated, so it will always be 0.
This means whenever you update the value for imageHeight, the cell property will be updated, but the cell won't do anything with it.
To achieve that you can simply override the setImageHeight: method in ProductViewCell to be able to trigger some action.
- (void)setImageHeight:(CGFloat)imageHeight {
if (_imageHeight != imageHeight) {
_imageHeight = imageHeight;
// Do something useful with the new value e.g. calculations
}
}
This method will be called every time you update the cell property
cell.imageHeight = ...
Finally I did it without using setter! The solution is simply to use the frame.size.height. My cell code is the following:
- (id)initWithFrame:(CGRect)frame
{
wMargin = 5.0;
self = [super initWithFrame:frame];
if (self) {
self.productImage = [[UIImageView alloc]initWithFrame:CGRectMake(wMargin, 5, frame.size.width - (wMargin * 2), frame.size.height)];
self.labelName = [[UILabel alloc]initWithFrame:CGRectMake(wMargin, frame.size.height, frame.size.width - (wMargin * 2), 20)];
self.labelName.font = [self.labelName.font fontWithSize:12];
self.labelName.textAlignment = NSTextAlignmentCenter;
[self addSubview:self.productImage];
[self addSubview:self.labelName];
self.backgroundColor = [UIColor colorWithRed:236.0f/255.0f green:236.0f/255.0f blue:236.0f/255.0f alpha:1.0];
self.layer.masksToBounds = YES;
self.layer.borderWidth = 1.0f;
self.layer.cornerRadius = 10.0f;
self.layer.borderColor= [[UIColor colorWithRed:207.0f/255.0f green:207.0f/255.0f blue:207.0f/255.0f alpha:1] CGColor];
[self.productImage setContentMode:UIViewContentModeScaleAspectFit];
}
return self;
}
I simply used the frame.size.height to define the height of my imageView and following you can see the result: