Making UIView foreground transparent - ios

I am modifying an IOS app to allow an additional background layer. All the existing overlays are UIImageViews, which handle transparency just fine.
The existing background is the main UIView. I want to change the black background to transparent, to put another view behind. It doesn't work. The simplest code which doesn't work as I would hope is as follows:
# import "TestUIView.h"
#implementation TestUIView
- (void)drawRect:(CGRect)rect {
self.opaque = NO;
[self setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0]];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(context, 0,0,0,0);
CGContextFillRect(context, rect);
// and here goes my code where I draw to the transparent background
}
#end
When this is executed, it produces a black rectangle. I have set its background to transparent and filled its foreground with transparent. What do I have to do to get a UIView where I can draw against a transparent background?
(And I know I can change the alpha of the view as a whole, that's not the issue. I want opaque drawing on a truly transparent background).
UPDATE: Its not in the setbackgroundcolor, I appreciate it isn't necessary and so shouldn't be there, but the same thing happens if it is commented out. I can't draw against a transparent background; the code above shows I can't even make a transparent rectangle to draw onto.
Thanks

By default the value of opaque is NO. Also if you set the alpha to 0, then the view will be completely invisible to the user.If you want to have transparency, then you need to have an alpha value greater than 0 and less than 1.
Also the backgroundColor property is used to set the view’s color rather than drawing that color yourself.
If you need to change the background color in drawRect, you will have to draw it yourself:
self.backgroundColor=yourColorWithSomeAlphaValue;//
[self.backgroundColor setFill];
CGContextFillRect(UIGraphicsGetCurrentContext(), rect);
More explanation is provided in here:

Related

How to draw a rounded transparent rectangle over GLKView

I'm working on a business card scanner application and I'm using AVCaptureSession and AVCaptureDevice for detecting edges of the card. I'd like to create a view on top of the preview layer which is rendered using GLKView and that view should have rounded rectangles and the outside of the rectangle should be blurred and the inside should be transparent.
Like this image:
How can I achieve this in Objective-C?
Thanks
Jugs
You can set background color of view to the UIColor with alpha
coverView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];

Is it possible to add a transparent layer or view above a colored view?

I'm using AVFoundation framework to scan a barcode, but that may be unrelevant for my problem.
What I want:
I would like that the square bordered in green be transparent (not with the darkened black).
Here is what I have done:
I have 2 views: backgroundView( which occupies the whole screen) and highlightView which is the square bordered with green, on top of backgroundView (I have used a XIB for dimensions and positions) :
self.highlightView.layer.borderColor = [UIColor greenColor].CGColor;
self.highlightView.layer.borderWidth = 3;
// this following line does not allow the square to be transparent
self.highlightView.layer.opacity = 0;
// relative to AVFoundation
_previewLayer.frame = _backgroundView.bounds;
[_backgroundView.layer addSublayer:_previewLayer];
_previewLayer.backgroundColor = [UIColor blackColor].CGColor;
_previewLayer.opacity = 0.3;
UPDATE : xib (here representing the square with a clear color background), the backgroundView has the property black color background).
As I mentioned, you were looking in the wrong direction. There are multiple posts with a problem similar to yours, which have pretty decent answers. (You will have to study and understand to make the most of them):
Cut Out Shape with Animation
Simply mask a UIView with a rectangle
To sum it up, you need to apply the semi-transparent color to the layer of backgroundView and then play around with the layer's mask property to get the work done.
You can find many tutorials to learn using the layer and mask together.
Hope this helps.

iOS 7/8 Objective C - apply blendmode to views

I would like to apply a saturation blendMode using a UIView on other views, like this :
: Example
I have a UILabel and UIImageView in the view of my ViewController, plus a BlendView which overwrites drawRect method.
- (void) drawRect:(CGRect)area
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
[[UIColor whiteColor] setFill];
CGContextSetBlendMode(context, kCGBlendModeSaturation);
CGContextFillRect(context, self.bounds);
CGContextRestoreGState(context);
}
However, I only have a black square if kCGBlendModeSaturation is given and a white square if kCGBlendModeMultiply give - the blendmode isn't applied.
I have set the BlendView as not opaque and tested with different alpha value, no changes.
P.S.: I wish the blendmode to be applied on any views, not only images.
You can't apply a blend mode to a single view and hope it'll have any effect on the views below, like you would with layers in Photoshop (the only compositing you can do between two separate views are change their opacity).
The only thing you can do is, on a single view's drawRect, draw with a specific fill mode over the previous drawing instructions.

Transparent UILabel textColor on superview.superview (sort of)

I would like to achieve the same effect as in the new iTunes remote update for iOS 7 for my UILabel.
If you look at this screen:
(The one on the right) you'll notice that the UILabel text color is the background blurred album cover without the black mask.
At the moment I have transparent UILabel textColor (http://cl.ly/SInK), my code is similar to https://github.com/robinsenior/RSMaskedLabel
My first assumption is to have a view hierarchy like that
UIImageView (Light blurred image)
|
UIImageView/UIView (Dark blurred image or just a dark mask for the superview)
|
UILabel (And all my other view).
I would like the UILabel to have a transparent text color on the first UIImageView, ignoring the second one/Mask).
I can't wrap my head around a solution to achieve this effect.
Since iOS 8 Apple offer a new class, UIVibrancyEffect, which can be added to a UIVisualEffectView. This combined with a UIBlurEffect can achieve the exact same result as my screenshot above.
Source: https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIVibrancyEffect/index.html
I don't think you're going to be able to directly do this with a UILabel. What I did was decompose it into several pieces:
How to draw only the background of a label. For this I cribbed code from CGPathRef from string to turn the string into a path. Then the subclassing UILabel and adding the following drawRect did the appropriate thing.
-(void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
// Convert the attributed text to a UIBezierPath
CGPathRef path = [self.attributedText createPath];
// Adjust the path bounds horizontally as requested by the view
CGRect bounds = [self textRectForBounds:rect limitedToNumberOfLines:self.numberOfLines];
CGAffineTransform xform = CGAffineTransformMakeTranslation(bounds.origin.x, bounds.origin.y);
// Adjust the path bounds vertically because it doesn't seem to be taken into account yet
bounds = CGPathGetBoundingBox(path);
xform = CGAffineTransformTranslate(xform, 0., (self.bounds.size.height - bounds.size.height) / 2.);
// Apply the transform to the path
path = CGPathCreateCopyByTransformingPath(path, &xform);
// Set colors, the fill color should be the background color because we're going
// to draw everything BUT the text, the text will be left clear.
CGContextSetFillColorWithColor(ctx, self.textColor.CGColor);
// Flip and offset things
CGContextScaleCTM(ctx, 1., -1.);
CGContextTranslateCTM(ctx, 0., 0. - self.bounds.size.height);
// Invert the path
CGContextAddRect(ctx, self.bounds);
CGContextAddPath(ctx, path);
CGContextDrawPath(ctx, kCGPathEOFill);
// Discard the path
CFRelease(path);
// Restore gstate
CGContextRestoreGState(ctx);
}
If you create a UILabel in interface builder, set the class, set the background color to clear and the foreground color to your proposed fill color, the background will show through where the text is.
To blur the body showing through the label, I dropped an FXBlurView (https://github.com/nicklockwood/FXBlurView) under the label with sizing constraints to keep them aligned.
You can see it all working here https://github.com/dwb357/TransparentLabel.
The color is not uniform. But it's actually "cut out" to let the blurred and tinted background shine through.
One way to do it is to construct a CGPath for the glyphs, clip the graphics context to them, then clear the context, leaving the area outside black and the area inside fhe glyths translucent.
An alternative approach is to create a pattern color from this large blurred tinted cover art and use this pattern color on a UILabel.

iPhone - Draw transparent rectangle on UIView to reveal view beneath

I currently have two UIViews: one of a red background and the other blue. The blue view is a subview of the red view. What I would like to do is be able to "cut" out rectangles on the blue view so that the red view can be visible. How do you go about doing this?
You have to override the top view's drawRect method. So, for example, you might create a HoleyView class that derives from UIView (you can do that by adding a new file to your project, selecting Objective-C subclass, and setting "Subclass of" to UIView). In HoleyView, drawRect would look something like this:
- (void)drawRect:(CGRect)rect {
// Start by filling the area with the blue color
[[UIColor blueColor] setFill];
UIRectFill( rect );
// Assume that there's an ivar somewhere called holeRect of type CGRect
// We could just fill holeRect, but it's more efficient to only fill the
// area we're being asked to draw.
CGRect holeRectIntersection = CGRectIntersection( holeRect, rect );
[[UIColor clearColor] setFill];
UIRectFill( holeRectIntersection );
}
If you're using Interface builder, make sure to change the holey view's class to HoleyView. You can do that by selecting in the view in Interface Builder and selecting the "Identity" pane in the inspector (its the one on the far right the the "i" icon).
You also have to set the top view to be non-opaque either with the following code snippet, or by un-checking the Opaque checkbox in the view's properties in Interface Builder (you'll find it in the View section of the view's attributes) and set its background color's opacity to 0% (background color is set in the same section).
topView.opaque = NO;
topView.backgroundColor = [UIColor clearColor];
If you want to do circles, you have to use Core Graphics (aka Quartz 2D). You'll probably want to read the programming guide, which is available here.
To draw an ellipse instead of the rectangle, your drawRect would look something like this:
- (void)drawRect:(CGRect)rect {
// Get the current graphics context
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor( context, [UIColor blueColor].CGColor );
CGContextFillRect( context, rect );
if( CGRectIntersectsRect( holeRect, rect ) )
{
CGContextSetFillColorWithColor( context, [UIColor clearColor].CGColor );
CGContextFillEllipseInRect( context, holeRect );
}
}
There is truth in all the other answers, but it is quite possible to draw with clear colour, or so to say erase the existing colours within any path, even with the -[UIBezierPath fill] or similar convenience methods. All you have to do is to set the context blend mode to an appropriate value depending on the effect you are trying to achieve, like so:
CGContextSetBlendMode(context, kCGBlendModeClear);
[[UIColor clearColor] set];
[myArbitraryPolygonPath fill];
There are around two dozen different options you could choose from, take a look around the CGContext reference.
to draw an ellipse, instead of a rect, just set the blendMode to clear:
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor( context, [UIColor blackColor].CGColor );
CGContextFillRect( context, rect );
CGRect holeRectIntersection = CGRectIntersection( holeRect, rect );
CGContextSetFillColorWithColor( context, [UIColor clearColor].CGColor );
CGContextSetBlendMode(context, kCGBlendModeClear);
CGContextFillEllipseInRect( context, holeRect );
}
These may be the dumb ways but I would not do it the way you describe, but make it look the way you want it to look.
(Jacques' answer just popped up - looks good to me)
Approach 1:
In the view controller to build a list of rectangles that tile around the exposed "hole". As your holes increase in number the number of tiling rects will also increase.
Approach 2:
Reverse your thinking. The blue view should be at the back with sections of the red view placed on top of it. You still see a red view with all but the "holes" masked by the blue view, but what you are really doing is copying regions from the view you want to expose and putting them on top of the mask as you make each hole. If you have some effect simulating depth you could add that as required with each hole.
Neither requires subclassing or drawRect:.
Some of the answers are quite old.
2023, Latest techniques include...
class CompImage: UIIImageView {
override func common() {
super.common()
layer.compositingFilter = "multiplyBlendMode"
print("Filters available to you ...\n",
CIFilter.filterNames(inCategory: kCICategoryCompositeOperation))
}
}
and
guard let ctx = UIGraphicsGetCurrentContext() else { return }
ctx.saveGState()
ctx.setStrokeColor(
..
ctx.setBlendMode(.multiply) // review the choices available
..

Resources