What is the correct syntax for this function in Swift?
The following works fine, and colors the background purple:
self.view.backgroundColor = UIColor.purpleColor()
When I chain the colorWithAlphaComponent function, the view shows the correct alpha for a moment, and then changes to an opaque purple that is relatively dark:
self.view.backgroundColor = UIColor.purpleColor().colorWithAlphaComponent(0.5)
Is this the recommended function for adding an alpha value to a UIColor?
Furthermore, why does the intellisense popup say that this function expects a UIColor as a parameter? E.g.,
self.view.backgroundColor = UIColor.colorWithAlphaComponent(<#UIColor#>)
EDIT: The behavior is strange. I am setting the background color on a view controller that is being loaded in a modal. As the modal slides up from the bottom, the alpha is correct. When the modal finishes loading, the background color changes to opaque?!
EDIT 2: The problem was not with the code--both the code above and the suggestion below were properly applying the alpha. The issue is the way that modals are being presented--the underlying view is being removed. See:
Transparent Modal View on Navigation Controller
It's not strange, it's behaving exactly as it should. Although many of UIColor's methods are class methods, there are still a few instance methods, and this is one of them. From the UIColor documentation.
colorWithAlphaComponent:
Creates and returns a color object that has the same color space and component values as the receiver, but has the specified alpha component.
So, colorWithAlphaComponent: just changes the alpha value of its receiver. Example:
let purple = UIColor.purpleColor() // 1.0 alpha
let semi = purple.colorWithAlphaComponent(0.5) // 0.5 alpha
And the reason why you're seeing autocompletion for this instance method on the type, is because Swift allows you to use instance methods as curried type methods. In the example you provided, colorWithAlphaComponent actually returns a function that takes a CGFloat as input and returns a UIColor.
let purple = UIColor.purpleColor()
let purpleFunc: (CGFloat -> UIColor) = UIColor.colorWithAlphaComponent(purple)
So, if you wanted to, you could call the type method passing in the instance you want to modify, and then call the resulting function with the alpha that you want to apply, like so.
let purple = UIColor.purpleColor()
let purpleTrans = UIColor.colorWithAlphaComponent(purple)(0.5)
Then as far as the issues you're having with the modal view controller go, you shouldn't be attempting to change the alpha of the view of a modal view controller. See this for more info. Instead, you should be manually creating a view and adding it to the view hierarchy of your existing view controller (if you absolutely have to alter its alpha)
Swift 5.0
self.view.backgroundColor = UIColor.black.withAlphaComponent(0.7)
in Swift 3.0
This works for me in xcode 8.2.
yourView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
It may helps you.
Since UIColor is part of UIKit, it has been replaced in SwiftUI with Color. The equivalent method is .opacity(_ opacity: Double) for example:
Color.purple.opacity(0.5)
Try smth like this to set color
view.backgroundColor = UIColor(red: (64/255.0), green: (54/255.0), blue: (105/255.0), alpha: 1.0)
UIColor.black.withAlphaComponent(0.5).cgColor
Related
I'm presenting a UISearchController from my controller embedded in a navigation controller. The default animation occurs, where the search box drops down from the top on the navigation bar.
This isn't a good UX in my case because I present the search when a user taps into a UITextField in the middle of the screen. What I'd like to do is have the UITextField float to the top and morph into the search box, but I can't figure how to do this.
This is what I have:
class PlacesSearchController: UISearchController, UISearchBarDelegate {
convenience init(delegate: PlacesAutocompleteViewControllerDelegate) {
let tableViewController = PlacesAutocompleteContainer(
delegate: delegate
)
self.init(searchResultsController: tableViewController)
self.searchResultsUpdater = tableViewController
self.hidesNavigationBarDuringPresentation = false
self.definesPresentationContext = true
self.searchBar.placeholder = searchBarPlaceholder
}
}
private extension ShowAddressViewController {
#objc func streetAddressTextFieldEditingDidBegin() {
present(placesSearchController, animated: true, completion: nil)
}
}
Instead of the search dropping down from the top, I'm hoping to get the text field fly up to the nav bar. What I’m after is the same effect that’s on the iOS 11 File app:
It has a text field in the middle of the screen then animated up to the navigation bar when you tap on it. In my case though, the text field is way lower in the screen and not originally part of the navigation bar.
UISearchController
UISearchController is a component that highly difficult to customize. From my experience I can say, that it is better to use it as is without any drastic or significant customization. Otherwise, customization could result in messy code, global state variables, runtime tricks with UIView hierarchy etc.
If specific behavior still needed, it is better to implement search controller from scratch or use third party one.
Default implementation
Looks like UISearchController was designed to be used in couple with UITableView and UISearchBar installed in the table header view. Even apple official code samples and documentation provides such example of usage (see UISearchController). Attempt to install UISearchBar somewhere else often results in numerous ugly side effects with search bar frame, position, twitching animations, orientation changes etc.
Starting with iOS 11, UINavigationItem got searchController property. It allows to integrate search controller into your navigation interface, so search will look exactly like iOS Files or iOS AppStore app. UISearchController's behavior still coupled with another component, but I believe it is better than coupling with UITableView all the time.
Possible solutions
From my perspective there are several possible solutions for your problem. I will provide them in order of increasing effort, which is needed for implementation:
If you still want to use UISearchController, consider to use it as is without significant customizations. Apple provides sample code, that demonstrates how to use UISearchController (see Table Search with UISearchController).
There are several third party libraries which may be more flexible with lots of additional features. For example: YNSearch, PYSearch. Please, have a look.
Along with UISearchController presentation, you could try to move UITextField up with changing alpha from 1 to 0. This will create a feeling that UITextField is smoothly transforming to UISearchBar. This approach described in article that was provided by Chris Slowik (see comment to your original post). The only thing I would improve is animations using transition coordinators (see example here), it will make animations smoother with synchronized timing. Final implementation also will be much cleaner.
As an option, you could try to design your own search controller using only UISearchBar or even plain UITextField.
You could subclass UISearchController and add UITextField object. UISearchController conforms to UIViewControllerAnimatedTransitioning and UIViewControllerTransitioningDelegate protocols, where UITextFiled could be removed or added along with transition animations.
I hope this helps.
Update:
I have implemented approach I described under point 3. Here is how it works:
You can find code snippet here. Please note, that it is only code example, there are might be situations which are not handled. Check it twice then.
Create one UIView in XIB. name it searchView.
Add UIButton inside above UIView in same xib and name it btnSearch. Like below

Setup search controller in ViewDidLoad as below:
func setupSearchController() {
self.searchController = UISearchController(searchResultsController: nil)
self.searchController.delegate = self
self.searchController.searchBar.delegate = self
definesPresentationContext = true
self.searchController.dimsBackgroundDuringPresentation = false
self.searchController.searchBar.sizeToFit()
searchView.addSubview(self.searchController.searchBar)
self.searchController.searchBar.isHidden = true
self.searchController.searchBar.tintColor = UIColor.white
self.searchController.searchBar.showsCancelButton = false
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).tintColor = session?.makeColor(fromHexString: TYPE_COLOR, alpha: 1.0)
self.searchController.searchBar.isTranslucent = false
self.searchController.searchBar.barTintColor = UIColor(red: 239.0 / 255.0, green: 135.0 / 255.0, blue: 1.0 / 255.0, alpha: 1.0)
}
This method will setup searchcontroller programatically inside searchview.
Now you just need to show searchcontroller programatically. add On click method of button in step 2. Call this below method name showsearchAnimation:
func ShowSeachAnimation() {
searchFrame = searchView.frame (add one global variable "searchFrame" in controller which saves searchView.frame so it will be used when cancel button clicked on search)
self.btnSearch.isHidden = true
var yAxis : CGFloat = 20
if #available(iOS 11 , *) {
yAxis = 8
} else {
yAxis = 20
}
searchView.translatesAutoresizingMaskIntoConstraints = true
searchView.frame = CGRect(x: 0, y: yAxis, width: view.frame.size.width, height: view.frame.size.height - yAxis)
self.searchController.searchBar.isHidden = false
self.searchController.searchBar.becomeFirstResponder()
self.searchController.searchBar.showsCancelButton = true
self.searchBar(self.searchController.searchBar, textDidChange: "")
searchView.layoutIfNeeded()
}
For hide searchbar, Add search hide method named "searchbarcancelbuttonclicked" in searchcontroller delegate:
func searchViewHideAnimation() {
self.removeNavigationBar()
self.navigationController?.isNavigationBarHidden = false
self.searchController.searchBar.text = " "
self.searchController.searchBar.isHidden = true
UIView.animate(withDuration: 0.3, animations: {() -> Void in
self.searchView.frame = self.searchFrame!
self.btnSearch.isHidden = false
}, completion: {(_ finished: Bool) -> Void in
self.searchView.layoutIfNeeded()
})
}
you can try to use my https://github.com/Blackjacx/SHSearchBar Which essentially will be your text field. You can add constraints to the left, right and top and adjust the top constraint when the text field editing begins. At the same time, you hide the navigation bar animated and gray out the background by using an overlay view. This way you have maximized control over your animations and this appüroach is not so difficult as it might sound.
I've been trying to use the appearance proxy API to apply some default colors to some controls, but I've run into a problem.
When I apply a tint color to UISegmentedControl using something like...
UISegmentedControl.appearance().tintColor = UIColor.red
It generates this...
All good, but when I add...
UIImageView.appearance().tintColor = UIColor.green
it changes to...
Just to be clear, I have BOTH this lines in my code
UISegmentedControl.appearance().tintColor = UIColor.red
UIImageView.appearance().tintColor = UIColor.green
It doesn't matter in what order I call them, the result is the same, the UIImageView properties override the UISegmentedControls
I've spent over half a day trying to find a solution to this problem but can't seem to find anything that works.
Running Xcode 8.2, iOS 10, Swift 3
What am I doing wrong and how can I fix?
I am not sure about this, but I guess, UISegmentedControl uses UIImageView to create segments, i.e. the segments we see inside segmented control are UIImageViews and not UIViews. UISegmentedControl even has methods to setImage for a particular segment.
If above is true, we can use appearanceWhenContainedIn API of UIAppearance to set image view tint colour like this:
UIImageView.appearance(whenContainedInInstancesOf: [UISegmentedControl.self]).tintColor = UIColor.red
UIImageView.appearance().tintColor = UIColor.green
I'm trying to implement a color-blind mode for my iOS app. Right now, I have 3 global variables for red, green, and blue defined as such:
var red : UIColor = UIColor(...)
var green : UIColor = UIColor(...)
var blue : UIColor = UIColor(...)
Now, I have a UIButton that the user can press to change to color-blind mode. Once this happens, I'm changing the global variables as such:
red = newRed
green = newGreen
blue = newBlue
However, this does not update the colors for any existing views that have already been loaded. Is there a way for me to update all controls that were red to the new red, green to the new green, and blue to the new blue without reloading the entire app? Thanks!
Update to post my button action:
func changeColor(sender: AnyObject) {
red = UIColor(...) //this is different from the previous red
green = UIColor(...) //this is different from the previous green
blue = UIColor(...) //this is different from the previous blue
//if I call viewDidLoad() again, then the colors are changed for all objects. However, I don't think this is the correct thing to do.
}
Never directly call viewDidLoad(). You need to ensure that your IBOutlets are attached to your views inside of your view controller. Also, ensure that you are directly changing the backgroundColor property of the view. For example:
myView.backgroundColor = UIColor.redColor()
I have a button in the storyboard, I gave it a color magnesium. I am doing some programming on the button which will change its color on certain situations.
I like the original color of the button in the storyboard and I want to return back to that color at some event.
Now the problem is that color I am using doesn't have a text name (yellowcolor, purplecolor) in UIColor and I can't find the RGB values from the storyboard color picker.
Any ideas?
Follow this screen shot. I am on Windows 8 right now so i just edited the picture but it will certainly give you the way to achieve what you want.
(I combined two DIFFERENT images. So don't freak out. Sorry.)
Xcode->Select Object->Attributes Inspector->Text Color->Other->Color Sliders->Dropdown Menu->RGB Sliders
You can do this to get the RBG from UIColor:
CGFloat red = self.btn.backgroundColor.CIColor.red;
CGFloat blue = self.btn.backgroundColor.CIColor.blue;
CGFloat green = self.btn.backgroundColor.CIColor.green;
CGFloat alpha = self.btn.backgroundColor.CIColor.alpha;
I have a custom UIButton which is a cloud, transparent black and white .png file, with no down state, just one image. When tapping and holding the finger over it, it turns dark grey. I'm trying to change that dark grey to something a little less oppressive. The button is out in the open in a view, not in a tab bar, tool bar, or navigation controller.
I've already tried setting tintColor (which the documentation helpfully informs me is only suitable for 'some' types of buttons, which no indication as to which).
I've also tried changing everything I can find in Interface Builder relating to highlight colours, default states, etc. Nothing has made a difference at all.
I've even tried setting the button's own image for its UIControlStateHighlighted state, but even this causes the dark grey overlay to appear when I hold my finger over it.
How can I change that colour? I've looked at numerous other issues here on SO and have been unable to find a solution that works for me. Any help would be greatly appreciated!
EDIT: I Solved the problem using a category of UIImage which adds a method that uses CoreGraphics to apply a tint to a provided UIImage. I then set THAT image as the highlight, and all is well. Seems a lot of hoop-la to change a colour Apple should've let us change, but c'est la vie.
You said you set a custom image for the UIControlStateHighlighted state. This should disable the default behaviour.
If you still have problems you can disable this effect by setting the adjustsImageWhenHighlighted property to NO and use whatever custom effect you want.
If adjustsImageWhenHighlighted = NO is not working,
set Button-Type to Custom (IB or programmatically).
Default Button-Type: System, changes behavior of highlighted button.
Swift 3:
myButton.adjustsImageWhenHighlighted = false
I was having a similar issue with a custom UIButton when the button was highlighting in grey every time it was pressed. I solved that problem by subclassing UIButton and in the implementation I overrode a single method, (void)setHighlighted: method and kept it empty:
- (void)setHighlighted:(BOOL)highlighted
{
// Leave empty to prevent super from doing whatever
// that it is doing to show the grey highlight.
}
That stopped any type of highlighting as I was not doing anything in the method. It's a better approach if all that you're trying to do is remove any highlighting effect.
So in your code, create a subclass of UIButton, override the setHighlighted method, and then make your custom button a subclass of this custom class.
You can write a custom button that does it
class ActionButton: UIButton {
var originalBackgroundColor: UIColor!
override var backgroundColor: UIColor? {
didSet {
if originalBackgroundColor == nil {
originalBackgroundColor = backgroundColor
}
}
}
override var isHighlighted: Bool {
didSet {
guard let originalBackgroundColor = originalBackgroundColor else {
return
}
backgroundColor = isHighlighted ? originalBackgroundColor.darken() : originalBackgroundColor
}
}