How can I make my text from "drawInRect" above the gradient layer? - ios

I created a new class named MySegment which inherits from UIControl.
First, I initialized a gradient line with CAGradientLayer.
Second,[self.layer addSublayer:myLayer]
Then, ["myString" drawInRect:rect withAttributes:attributes] is in the same location.
I want the text from drawInRect to be overlaid on myLayer, but no matter what I use addSublayer or insertlayer,my text is always under mylayer, the effect is shown on the photo.
How can I make my text above the gradient layer?

I'd indeed use CATextLayer as #DonMag has pointed out. In that case, you would have CATextLayer and CAGradientLayer.
First insert the CAGradientLayer using addSubLayer
[self.layer addSubLayer:gradientLayer];
Then the CATextLayer using insertSubLayer:above:
[self.layer insertSubLayer:textLayer above:gradientLayer];
PS: Answered question about putting attributedstring in CATextLayer:
Displaying an attributed string in a CATextLayer

Related

How to achieve this effect in iPhone SDK?

I would like to how can I apply this effect in iPhone SDK?
So, I have an image and a label on top of it.
I want to have the effect in which the bottom portion kind of blends in with the image.
So that there is no clear demarcation from where the image ends at the bottom portion of the view.
Please let me know.
Easy way to achieve this to CAGradientLayer
UIView *yourGradientView; // with that label "ENTREES", Add this view as a subview of the background view.
CAGradientLayer *gradientLayer=[CAGradientLayer layer];
[gradientLayer setFrame:[yourGradientView bounds]];
[gradientLayer setColors:#[(id)[UIColor clearColor].CGColor, (id)[[UIColor whiteColor] colorWithAlphaComponent:0.7f].CGColor]];
[gradientLayer setLocations:#[[NSNumber numberWithFloat:0.50f], [NSNumber numberWithFloat:1.0f]]];
[[yourGradientView layer] insertSublayer:gradientLayer atIndex:0];
Easiest solution: Add UIImageView with gradient PNG image as a subview between the image and label if you have the constant color.
If you need variable color of the gradient, you can either add a subview with the gradient drawn using CoreGraphics or CALayer.
If you need the image to blend with any background, you can mask the background image layer with CALayer gradient layer.
Unless you provide any more details to your question with regards to functionality and some code, the first look instance seems to have the following solution:
Step 1
Set a UIImage as a background image. In your case it is the one shown in the question.
Step 2 add a UILabel as a subview of UIImage and set the background of UILabel to be transparent. Position the label as per your needs which in your case seems to be the bootom left.
Hope his helps !!!

Is it possible to place a CAGradientLayer under the background layer?

I'm adding a gradient layer to a custom button, the this reference in the following code:
//a custom gradient
var layerGradient = new CAGradientLayer();
//the gradient colors are the base color to the modified version
layerGradient.Colors = new CGColor[]{color.CGColor, color2.CGColor};
//add the gradient as a sublayer in the button
this.Layer.InsertSublayer(layerGradient, 0);
This works fine and the gradient does what it should. But, if the button has a background image, the background doesn't display. The gradient appears to be on a layer above the background, obscuring it. Is there any way to fix this, or do I need to draw the background on my own layer and add it manually?
Haven't tried it but possibly insertSublayer:below: is what you are looking for.
- (void)insertSublayer:(CALayer *)aLayer below:(CALayer *)sublayer
I solved this by adding the background image as its own layer, and then adding the gradient layer below it:
mImageView = new UIImageView();
this.Layer.InsertSublayer(mImageView.Layer, 0);
mImageView.Image = mImage;
So this makes a UIImageView layer to hold the image. And then I call the code as in my question to insert the gradient layer underneath this ImageView layer and it works.

Is there a way to have stroke for UIFont

I'm using MKMap with overlay. The overlay display text. I need the text to have "stroke" effect. any clue?
[t drawAtPoint:CGPointMake(0,30) withFont:[UIFont fontWithName:#"Helvetica-Bold" /*"Arial"*/ size:(3 * MKRoadWidthAtZoomScale(zoomScale))]
];
If you're drawing in drawRect:, you can set the text drawing mode using:
CGContextSetTextDrawingMode(UIGraphicsGetCurrentContext(), kCGTextStroke);
If you wanted to fill and stroke, then you can use kCGTextFillStroke.
You can create an CFAttributedString from your string, set appropriate kCTStrokeWidthAttributeName and kCTStrokeColorAttributeName attribute values and draw it with CoreText framework.

How to draw UILabel Into Context

I'm trying to draw a UIlabel into a new Context, at a specific location. I know you can draw just the NSString into a context easily, but I want to retain the text size, color, and word wrap style of the UILabel. Thanks for your help!
UIGraphicsBeginImageContext(targetSize);
// here is where I want to draw UILabel to context
UIGraphicsEndImageContext();
You could draw any view using -renderInContext:, but if all you need is just retain the text size, color and word wrap style, you could simply use -drawInRect:withFont:lineBreakMode:alignment: to customize all options.
[label.textColor set];
[label.text drawInRect:label.bounds
withFont:label.font
lineBreakMode:label.lineBreakMode
alignment:label.textAlignment];
There is also a -drawTextInRect: method in UILabel, but Apple says "You should not call this method directly."

How to mask UIViews in iOS

I've seen similar questions, but haven't found workable answers.
I want to mask a UIView using a grey image (need to convert to alpha scale for masking). The UIView has background. It should be easy to mask an image, but I want to mask any UIView.
Any clues will be appreciated.
I've been working on this problem for a couple of hours and have a solution that I think will do what you want. First, create your masking image using whatever means you see fit. Note that we only need the alpha values here, all other colours will be ignored, so make certain that the method you use supports alpha values. In this example I'm loading from a .png file, but don't try it with .jpg files as they don't have alpha values.
Next, create a new layer, assign your mask to its contents and set this new layer to your UIView's own layer, like so: you should find that this masks the UIView and all its attached subviews:
UIImage *_maskingImage = [UIImage imageNamed:#"mask"];
CALayer *_maskingLayer = [CALayer layer];
_maskingLayer.frame = theView.bounds;
[_maskingLayer setContents:(id)[_maskingImage CGImage]];
[theView.layer setMask:_maskingLayer];
With this done, you can set the UIView's background colour to whatever you like and the mask will be used to create a coloured filter.
EDIT: As of iOS8 you can now mask a view simply by assigning another view to its maskView property. The general rules stay the same in that the maskView's alpha layer is used to determine the opacity of the view it is applied to.
For apps targeting iOS 8.0+ this worked well (in this case, using a gradient as the mask) It avoids any need to resize or position the mask.
// Add gradient mask to view
func addGradientMask(targetView: UIView)
{
let gradientMask = CAGradientLayer()
gradientMask.frame = targetView.bounds
gradientMask.colors = [UIColor.blackColor().CGColor, UIColor.clearColor().CGColor]
gradientMask.locations = [0.8, 1.0]
let maskView: UIView = UIView()
maskView.layer.addSublayer(gradientMask)
targetView.maskView = maskView
}
In my case, I want to remove the mask once the user starts scrolling. This is done with:
func scrollViewWillBeginDragging(scrollView: UIScrollView) {
exerDetailsTableView.maskView = nil
}
where the view is defined as an #IBOutlet:
#IBOutlet weak var exerDetailsTableView: UITableView!
Result:
I don't know the exact code off the top of my head but the basic idea is to have two UIViews. One UIView would have it's image property set to be the grey scale image and the other UIView would be set as usual the only difference is that you would position the initial UIView directly on top of the UIView containing the "normal" image.
I hope that is enough to push your idea a step further.

Resources