Title of UIButton is not visible when UIVibrancyEffect is applied - ios

I'm having trouble applying UIVibrancyEffect to my UIButtons in iOS today widget. I want them to like default "Edit" button in notification centre's Today section:
As you can see in the screenshot, default button is vibrant and looks much better.
I tried replacing widget's View with UIVisualEffectView like that:
UIVisualEffectView effectView = new UIVisualEffectView(UIVibrancyEffect.CreateForNotificationCenter ());
effectView.Frame = this.View.Bounds;
effectView.AutoresizingMask = this.View.AutoresizingMask;
UIView oldView = this.View;
this.View = effectView;
effectView.ContentView.AddSubview(oldView);
this.View.TintColor = UIColor.Clear;
And it appears to be working, but titles of my buttons become vibrant as well (I want them to remain black):
Is there a way to prevent button titles from becoming vibrant when UIVibrancyEffect is applied?
I should also add that I'm using Xamarin.iOS.

I seem to have a solution to my own problem. I ended up creating UIVisualEffectView with blank UIView inside and adding it behind UIButton.
This code snippet shows how to style one button:
// Create effect view
var effectView = new UIVisualEffectView(UIVibrancyEffect.CreateForNotificationCenter ());
// This color looks best for me. You can play around with it to make it look better
effectView.BackgroundColor = UIColor.FromRGBA(55, 55, 55, 100);
// Position effectView
effectView.Frame = myButton.Frame;
// Add effectView and send it to back, behind actual button
this.View.AddSubview(effectView);
this.View.SendSubviewToBack (effectView);
// Create UIView and add it to effectView's ContentView
var view = new UIView ();
view.BackgroundColor = UIColor.White;
effectView.ContentView.AddSubview(view);
view.Frame = new CGRect(0, 0, effectView.Frame.Width, effectView.Frame.Height);
// Make sure your effect view has rounded corners
effectView.Layer.MasksToBounds = true;
effectView.Layer.CornerRadius = 4.0f;
And this is how it looks:

Related

Change background color of UIToolbar in a WKWebView

I am coding my app using Xamarin, but I can translate any swift/objective-C responses.
I have a WKWebView that I using to display data with LoadHtmlString(). I want to change the background color of the UIToolbar that is displayed above the keyboard when a user focuses an input field. Right now, the button text color and background color are both white, so the buttons aren't visible.
I can change the button text color by using UIBarButtonItem.Appearance.TintColor = UIColor.White;, but this will also change the text color of the buttons in my UINavigationBar. I would rather leave the text white, and change the background color of the UIToolbar.
I can slightly modify the background color using UIToolbar.Appearance.BackgroundColor = UIColor.Red;, but this just adds a subtle tint of the color to the UIToolbar, and doesn't actually make the toolbar dark enough for the white text to be visible.
Here is my complete code for setting up my Appearance defaults:
UIColor lightColor = UIColor.White;
UIColor themeColor = UIColor.Red;
UIApplication.SharedApplication.SetStatusBarStyle(UIStatusBarStyle.LightContent, false);
UINavigationBar.Appearance.BarStyle = UIBarStyle.Black;
UINavigationBar.Appearance.BarTintColor = themeColor;
UINavigationBar.Appearance.Translucent = false;
UINavigationBar.Appearance.TintColor = lightColor;
UINavigationBar.Appearance.SetTitleTextAttributes(new UITextAttributes()
{
TextColor = lightColor
});
UIStringAttributes navBarAttributes = new UIStringAttributes();
navBarAttributes.ForegroundColor = lightColor;
UINavigationBar.Appearance.TitleTextAttributes = navBarAttributes;
UITabBar.Appearance.BarTintColor = themeColor;
UITabBar.Appearance.TintColor = lightColor;
UIToolbar.Appearance.BarTintColor = themeColor;
UIToolbar.Appearance.TintColor = lightColor;
UIBarButtonItem.Appearance.TintColor = lightColor;
UIButton.AppearanceWhenContainedIn(typeof(UINavigationBar)).TintColor = lightColor;
UIToolbar.Appearance.BackgroundColor = themeColor;
Is there a way to change the WKWebView's toolbar background color without having to retheme my entire app?
If I can't change the background color of the toolbar, I am open to changing the button text color when displayed in a WKWebView. I have tried adding the following code, but nothing seems to work.
//Using green to see if the code is working.
UIBarButtonItem.AppearanceWhenContainedIn(typeof(WKWebView)).TintColor = UIColor.Green;
UIBarButtonItem.AppearanceWhenContainedIn(typeof(MyViewController)).TintColor = UIColor.Green;
You can have a try with custom UIToolBar to change its background color by an image :
public class MyToolBar: UIToolbar
{
public override void Draw(CGRect rect)
{
base.Draw(rect);
CGContext c = UIGraphics.GetCurrentContext();
UIImage image = new UIImage("background.png");
//here set image to be background color
c.DrawImage(rect, image.CGImage);
}
}
And toolbar will only used for where you used , can not affecting other toolbar in app.
MyToolBar myToolBar = new MyToolBar();
myToolBar.Frame = new CoreGraphics.CGRect(0, 0, UIScreen.MainScreen.Bounds.Size.Width, 50);
UIBarButtonItem doneItem = new UIBarButtonItem("Done", UIBarButtonItemStyle.Done, doneClickMethod);
List<UIBarButtonItem> list = new List<UIBarButtonItem>();
list.Add(doneItem);
myToolBar.Items = list.ToArray();
MySearchBar.InputAccessoryView = myToolBar;

AVRoutePickerView Won't Change Color when Airplay is Active

I have a AVRoutePickerView in a ViewController that I can't get to change color when it's using Airplay.
AVRoutePickerView *routePickerView = [AVRoutePickerView new];
routePickerView.backgroundColor = [UIColor clearColor];
routePickerView.activeTintColor = [UIColor blueColor];
routePickerView.tintColor = [UIColor whiteColor];
//I put it in a StackView, incidentally
[self.bottomButtonStack insertArrangedSubview:routePickerView atIndex: 3];
[routePickerView.layer setFrame:CGRectMake(80,80,80,80)];
[routePickerView.heightAnchor constraintEqualToConstant:52].active = true;
[routePickerView.widthAnchor constraintEqualToConstant:52].active = true;
This works fine, but the button always stays the tintColor even when an AirPlay source is being used from the picker.
How do I get the button to change to the activeTintColor when Airplay is active?
I thought it was automatically supposed to use the activeTintColor when Airplay was active. If no colors are set, the color of the button is always blue no matter what.
Thanks in advance!
I first noticed this problem after upgrading to iOS 12.3. I have since discovered that creating an instance of AVRouteDetector causes AVRoutePickerView to correctly apply the activeTintColor. Just create the detector and retain in a member variable:
self.myDetector = AVRouteDetector()
// create route picker view as usual
you need set routePickerButtonStyle
let routePickerView = AVRoutePickerView(frame: CGRect(x: 200, y: 200, width: 100, height: 100))
routePickerView.routePickerButtonStyle = .custom
routePickerView.backgroundColor = UIColor.clear
routePickerView.delegate = self
self.view.addSubview(routePickerView)

Adding a layer of color over a UIImage

I was hoping to make my UIImage "highlight" briefly upon being tapped. Not sure of the color yet, but let's say blue for arguments sake. So you tap the image, it briefly looks blue and then it navigates you to a details page to edit something on another screen.
From some initial reading it seems the right course of action is to use the Quartz framework and do this:
imageView.layer.backgroundColor = UIColor.blueColor()
imageView.layer.opacity = 0.7
I guess the idea would be you change the background of the layer behind the image, and then by setting the opacity of the image, the blue "bleeds through" a little bit, giving you a slightly blue image?
When I try the above, however, a blue border goes around the image itself, and based upon the opacity, the blue is either dark or light. The actual image does not become any more blue, but it does react to the opacity (meaning if I set it to something like .1, the image is very faded and barely visible). Why does the image react correctly, but not show blue?
Thanks so much!
As far as I know changing the opacity will change the opacity for the WHOLE view, meaning not just the UIImage that the UIImageView holds. So instead of fading to reveal the UIImageView's background color, instead the opacity of the whole view is just decreased as you're seeing.
Another way you could do it though would be to add an initially transparent UIView on top of your UIImageView and change its opacity instead:
UIView *blueCover = [[UIView alloc] initWithFrame: myImageView.frame];
blueCover.backgroundColor = [UIColor blueColor];
blueCover.layer.opacity = 0.0f;
[self.view addSubview: blueCover];
[UIView animateWithDuration:0.2f animations^{
blueCover.layer.opacity = 0.5f
}];
Here's how I use tint and tint opacities in IOS 9 with Swift -
//apply a color to an image
//ref - http://stackoverflow.com/questions/28427935/how-can-i-change-image-tintcolor
//ref - https://www.captechconsulting.com/blogs/ios-7-tutorial-series-tint-color-and-easy-app-theming
func getTintedImage() -> UIImageView {
var image : UIImage
var imageView : UIImageView
image = UIImage(named: "someAsset")!
let size : CGSize = image.size
let frame : CGRect = CGRectMake((UIScreen.mainScreen().bounds.width-86)/2, 600, size.width, size.height)
let redCover : UIView = UIView(frame: frame)
redCover.backgroundColor = UIColor.redColor()
redCover.layer.opacity = 0.75
imageView = UIImageView()
imageView.image = image.imageWithRenderingMode(UIImageRenderingMode.Automatic)
imageView.addSubview(redCover)
return imageView
}
Is this tap highlight perhaps something you could do with a UIButton? UIButton has all these states off the bat and might be a bit easier to work with, specially if there's something that actually needs to happen after you tap it. Worst case scenario is you have a UIButton that does not trigger any method when tapped.
You can try changing the tint color instead:
UIImage *image = [UIImage imageNamed:#"yourImageAsset"];
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
imageView.tintColor = [UIColor blueColor];
imageView.image = image;

iOS 7 Translucent Modal View Controller

The App Store app on iOS 7 uses a frosted glass-type effect where it is possible to see the view behind. Is this using an API built into iOS 7 or is it custom code. I was hoping it would be the former but I can't see any obvious references in the documentation. Obvious things like (like setting the alpha property on the modal view) don't seem to have any effect.
To see an example, open the App Store app and press the button at the top-right.
With the release of iOS 8.0, there is no need for getting an image and blurring it anymore. As Andrew Plummer pointed out, you can use UIVisualEffectView with UIBlurEffect.
UIViewController * contributeViewController = [[UIViewController alloc] init];
UIBlurEffect * blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *beView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
beView.frame = self.view.bounds;
contributeViewController.view.frame = self.view.bounds;
contributeViewController.view.backgroundColor = [UIColor clearColor];
[contributeViewController.view insertSubview:beView atIndex:0];
contributeViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:contributeViewController animated:YES completion:nil];
Solution that works before iOS 8
I would like to extend on rckoenes' answer:
As emphasised, you can create this effect by:
Convert the underlying UIView to an UIImage
Blur the UIImage
Set the UIImage as background of your view.
Sounds like a lot of work, but is actually done pretty straight-forward:
1. Create a category of UIView and add the following method:
-(UIImage *)convertViewToImage
{
UIGraphicsBeginImageContext(self.bounds.size);
[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
2. Make an image of the current view and blur it by using Apple's Image Effect category (download)
UIImage* imageOfUnderlyingView = [self.view convertViewToImage];
imageOfUnderlyingView = [imageOfUnderlyingView applyBlurWithRadius:20
tintColor:[UIColor colorWithWhite:1.0 alpha:0.2]
saturationDeltaFactor:1.3
maskImage:nil];
3. Set it as background of your overlay.
-(void)viewDidLoad
{
self.view.backgroundColor = [UIColor clearColor];
UIImageView* backView = [[UIImageView alloc] initWithFrame:self.view.frame];
backView.image = imageOfUnderlyingView;
backView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
[self.view addSubview:backView];
}
Just reimplemented Sebastian Hojas' solution in Swift:
1. Create a UIView extension and add the following method:
extension UIView {
func convertViewToImage() -> UIImage{
UIGraphicsBeginImageContext(self.bounds.size);
self.drawViewHierarchyInRect(self.bounds, afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext();
return image;
}
}
2. Make an image of the current view and blur it by using Apple's Image Effect (I found a reimplementation of this in Swift here: SwiftUIImageEffects
var imageOfUnderlyingView = self.view.convertViewToImage()
imageOfUnderlyingView = imageOfUnderlyingView.applyBlurWithRadius(2, tintColor: UIColor(white: 0.0, alpha: 0.5), saturationDeltaFactor: 1.0, maskImage: nil)!
3. Set it as background of your overlay.
let backView = UIImageView(frame: self.view.frame)
backView.image = imageOfUnderlyingView
backView.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.5)
view.addSubview(backView)
I think this is the easiest solution for a modal view controller that overlays everything with a nice blur (iOS8)
UIViewController * contributeViewController = [[UIViewController alloc] init];
UIBlurEffect * blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *beView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
beView.frame = self.view.bounds;
contributeViewController.view.frame = self.view.bounds;
contributeViewController.view.backgroundColor = [UIColor clearColor];
[contributeViewController.view insertSubview:beView atIndex:0];
contributeViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:contributeViewController animated:YES completion:nil];
There is no API available in the iOS 7 SDK which will allow you to "frost" the underlaying view controller.
What I have done is render the underlaying view to an image, which I then frosted and set that as background the the view that is being presented.
Apple provides a good example for this: https://developer.apple.com/downloads/index.action?name=WWDC%202013
The project you want is called, iOS_RunningWithASnap
A little simplier way to achieve this (based on Andrew Plummer's answer) with Interface Builder (also it removes side effect that appears in Andrews answer):
In IB add Visual Effect View to your View Controller under your other views;
Make top, bottom, left, right constraints from Visual Effect View to top (parent) View, set all of them to 0;
Set Blur Style;
Add the code where you present your new fancy View Controller:
UIViewController *fancyViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"yourStoryboardIDFOrViewController"];
fancyViewController.view.backgroundColor = [UIColor clearColor];
fancyViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:fancyViewController
animated:YES
completion:nil];
Actually, the second and third lines are VERY important - otherwise controller will blink and then turn black.
Since iOS 8, this works:
let vc = UIViewController()
vc.view = UIVisualEffectView(effect: UIBlurEffect(style: .Light))
vc.modalPresentationStyle = .OverFullScreen
let nc = UINavigationController(rootViewController: vc)
nc.modalPresentationStyle = .OverFullScreen
presentViewController(nc, animated: true, completion: nil)
The key is the .OverFullScreen flag and ensuring the viewControllers have a blur UIVisualEffectView that is the first visible view.
As #rckoenes said, there is no Apple provided framework to get that effect. But some people out there already built good alternatives, like this one for example:
https://github.com/JagCesar/iOS-blur/
A couple of alternative approaches that also work on iOS 5 and 6:
FXBlurView: https://github.com/nicklockwood/FXBlurView
iOS RealtimeBlur: https://github.com/alexdrone/ios-realtimeblur
Fast & easy solution
with XIB support you can use for the old school boys
https://github.com/cezarywojcik/CWPopup
Instead of presenting the viewController as a modalView, you could add it as a child viewController and create a custom animation. You would then only need to change the default view of the viewController to a UIToolBar in viewDidLoad.
This will allow you to mimic the appstore's blurred modal view as closely as possible.
I have uploaded my take of the blurred view controller to [GitHub][1]. It also comes with a segue subclass so you can use it in your storyboards.
Repository: https://github.com/datinc/DATBlurSegue
Apple released the UIImageEffect category for those effects. Those category should be added manually to the project, and it support iOS7.
You can use UIToolbar as background.
By default UIToolbar have 50px height.
Add auto layout constraints on UIToolbar.
Then select height constraint and modify it.
Hierarchy will look like this:
UIView -> clear colour for background.
- UIToolbar
- Other contents.

How to round the corners of a button

I have a rectangle image (jpg) and want to use it to fill the background of a button with rounded corner in xcode.
I wrote the following:
UIButton *button = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
CGRect frame = CGRectMake(x, y, cardWidth, cardHeight);
button.frame = frame;
[button setBackgroundImage:backImage forState:UIControlStateNormal];
However, the button I get with that approach doesn't have its corners rounded: it is instead a plain rectangle that looks exactly like my original image. How can I get instead an image with rounded corner to represent my button?
Thanks!
I tried the following solution with the UITextArea and I expect this will work with UIButton as well.
First of all import this in your .m file -
#import <QuartzCore/QuartzCore.h>
and then in your loadView method add following lines
yourButton.layer.cornerRadius = 10; // this value vary as per your desire
yourButton.clipsToBounds = YES;
You can achieve by this RunTime Attributes
we can make custom button.just see screenshot attached.
kindly pay attention :
in runtime attributes to change color of border follow this instruction
create category class of CALayer
in h file
#property(nonatomic, assign) UIColor* borderIBColor;
in m file:
-(void)setBorderIBColor:(UIColor*)color {
self.borderColor = color.CGColor;
}
-(UIColor*)borderIBColor {
return [UIColor colorWithCGColor:self.borderColor];
}
now onwards to set border color check screenshot
thanks
Pushing to the limits corner radius up to get a circle:
self.btnFoldButton.layer.cornerRadius = self.btnFoldButton.frame.height/2.0;
If button frame is an square it does not matter frame.height or frame.width. Otherwise use the largest of both ones.
You may want to check out my library called DCKit. It's written on the latest version of Swift.
You'd be able to make a rounded corner button/text field from the Interface builder directly:
It also has many other cool features, such as text fields with validation, controls with borders, dashed borders, circle and hairline views etc.
UIButton* closeBtn = [[UIButton alloc] initWithFrame:CGRectMake(10, 50, 90, 35)];
//Customise this button as you wish then
closeBtn.layer.cornerRadius = 10;
closeBtn.layer.masksToBounds = YES;//Important
Import QuartCore framework if it is not there in your existing project, then import #import <QuartzCore/QuartzCore.h> in viewcontroller.m
UIButton *button = [[UIButton buttonWithType:UIButtonTypeRoundedRect]];
CGRect frame = CGRectMake(x, y, width, height); // set values as per your requirement
button.layer.cornerRadius = 10;
button.clipsToBounds = YES;
First set width=100 and Height=100 of button
Objective C Solution
YourBtn1.layer.cornerRadius=YourBtn1.Frame.size.width/2;
YourBtn1.layer.borderColor=[uicolor blackColor].CGColor;
YourBtn1.layer.borderWidth=1.0f;
Swift 4 Solution
YourBtn1.layer.cornerRadius = YourBtn1.Frame.size.width/2
YourBtn1.layer.borderColor = UIColor.black.cgColor
YourBtn1.layer.borderWidth = 1.0
Try my code. Here you can set all properties of UIButton like text colour, background colour, corner radius, etc.
extension UIButton {
func btnCorner() {
layer.cornerRadius = 10
clipsToBounds = true
backgroundColor = .blue
}
}
Now call like this
yourBtnName.btnCorner()
For Objective C:
submitButton.layer.cornerRadius = 5;
submitButton.clipsToBounds = YES;
For Swift:
submitButton.layer.cornerRadius = 5
submitButton.clipsToBounds = true
If you want a rounded corner only to one corner or two corners, etc... read this post:
[ObjC] – UIButton with rounded corner - http://goo.gl/kfzvKP
It's a XIB/Storyboard subclass. Import and set borders without write code.
For Swift:
button.layer.cornerRadius = 10.0
updated for Swift 3 :
used below code to make UIButton corner round:
yourButtonOutletName.layer.cornerRadius = 0.3 *
yourButtonOutletName.frame.size.height
Swift 4 Update
I also tried many options still i wasn't able to get my UIButton round cornered.
I added the corner radius code inside the viewDidLayoutSubviews() Solved My issue.
func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
anyButton.layer.cornerRadius = anyButton.frame.height / 2
}
Also we can adjust the cornerRadius as follows:
func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
anyButton.layer.cornerRadius = 10 //Any suitable number as you prefer can be applied
}
An alternative answer which sets a border too (making it more like a button) is here ... How to set rectangle border for custom type UIButton
For iOS SWift 4
button.layer.cornerRadius = 25;
button.layer.masksToBounds = true;
You can use outlet connection and didSet function for your button on the view;
#IBOutlet weak var button: UIButton!{
didSet {
button.layer.cornerRadius = 5;
button.layer.masksToBounds = true;
}
}

Resources