button reversed when pressed - swift

Would like to create a button "scan" that is reversed and outlined when pressed (see image below)
Was using a button configurator (with storyboard) but am having trouble getting background color to update with isHighlighted. Happy to switch to SwiftUI from Storyboard if necessary.
#IBOutlet var imageView: UIImageView!
let scanButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .black
configButton()
scanButton.configurationUpdateHandler = { button in
//this transform is for testing and works
button.transform = button.isHighlighted ? CGAffineTransform(scaleX: 0.95, y: 0.95) : .identity
var config = button.configuration
//changing the title works
config?.title = button.isHighlighted ? "pressed" : "scan"
//config?.background = button.isHighlighted ? //need some help
button.configuration = config
}
}
func configButton(){
scanButton.configuration = .filled()
scanButton.configuration?.baseBackgroundColor = .green
scanButton.configuration?.title = "scan"
scanButton.configuration?.baseForegroundColor = .black
addButtonConstraints()
}
func addButtonConstraints(){
view.addSubview(scanButton)
scanButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
scanButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
scanButton.centerYAnchor.constraint(equalTo: view.centerYAnchor),
scanButton.widthAnchor.constraint(equalToConstant: 125),
scanButton.heightAnchor.constraint(equalToConstant: 30)
])
}

Does this work for you?
The button in this example was placed using Interface Builder as a Filled Button in Main.storyboard, then connected to the View Controller code with an #IBOutlet. The code example is ViewController.swift.
The button inverts its color scheme and gains a contrasting outline when it is pressed down, then reverts to its original appearance when it is released.
import UIKit
class ViewController: UIViewController {
// Set up this outlet to allow accessing the button's layer and configuration properties
#IBOutlet weak var swapColorsButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Set up the button's outline. Since the button has a white background when not pressed down, the outline does not become visible until the button is pressed.
swapColorsButton.layer.borderWidth = 3
swapColorsButton.layer.borderColor = CGColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
swapColorsButton.layer.cornerRadius = 5
}
// This is a Touch Down action -- it inverts the button's colors when it is pressed
#IBAction func pressDown(_ sender: UIButton) {
swapColorsButton.configuration?.baseBackgroundColor = .black
swapColorsButton.configuration?.baseForegroundColor = .white
}
// This is a Touch Up Inside action -- releasing the button resets it to its original colors
#IBAction func buttonReleased(_ sender: UIButton) {
swapColorsButton.configuration?.baseBackgroundColor = .white
swapColorsButton.configuration?.baseForegroundColor = .black
}
}
In order to detect being pressed down and released without using the isHighlighted property, the example code has two separate #IBActions controlling the color changes. Pressing the button down is a Touch Down action, and releasing the button is Touch Up Inside. To get the full menu of #IBAction options, instead of just the default one, right click on the button in Main.storyboard. You can then drag and drop from the menu options to ViewController.swift.

Related

Strange cornerRadius behaviour on UIView from xib

I created a custom Numpad keyboard through xib and wanted to initialize it with a rounded corners.
Here is the code I use:
import UIKit
class NumpadView: UIView {
#IBOutlet weak var resetButton: NumpadButton!
#IBOutlet weak var decimalButton: NumpadButton!
var target: UITextInput?
var view: UIView?
init(target: UITextInput, view: UIView) {
super.init(frame: .zero)
self.target = target
self.view = view
initializeSubview()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
initializeSubview()
}
func initializeSubview() {
let xibFileName = "NumpadView"
let view = Bundle.main.loadNibNamed(xibFileName, owner: self, options: nil)![0] as! UIView
self.layer.cornerRadius = 30
self.layer.masksToBounds = true
self.addSubview(view)
view.frame = self.bounds
self.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
}
But then I receive the strange view look in area where cornerRadius is implemented:
How to remove that grey background which is visible near the rounded corners?
UPDATE:
According to View Debugger it seems like this grey layer between yellow square and Visual Effect View is a UICompatibilityInputViewController:
How I presenting the Numpad:
1.I created a NumpadView as a UIView subclass in a xib:
2.In my VC I just change a standard textField.inputView property on my custom NumpadView:
import UIKit
class NumpadViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
setupKeyboardHide()
textField.delegate = self
textField.inputView = NumpadView(target: textField, view: view)
}
}
Test project on Github
Another option to get your "rounded corners"...
Get rid of the Visual Effect View in your Numpad class, and set a layer mask on the superview at run-time.
In class NumpadView: UIView, UIInputViewAudioFeedback:
override func layoutSubviews() {
super.layoutSubviews()
guard let sv = superview else { return }
let maskLayer = CAShapeLayer()
let bez = UIBezierPath(roundedRect: bounds, cornerRadius: 16)
maskLayer.path = bez.cgPath
sv.layer.mask = maskLayer
}
Looks like this:
Sure, the NumpadView object has rounded corner. However, you are using it like this:
textField.inputView = NumpadView(target: textField, view: view)
So, that part which is not rounded is the textField's inputView. I'm not quite sure if you can modify its layer to have corner radius. But, if you really want to get that rounded corner effect, an easier approach is just to add the NumpadView directly to the parent view and anchored to the bottom. Then show it via the begin editing delegate of the textfield (and hide via end editing).

Height of view changes upon calculation?

Swift 3
I have a view with some labels in it that I'm animating into the field of view when a user taps a button. I've used this identical code in another view controller and it worked just fine. For some reason, though, I can't get it to work now. It's always off by 1.5 pixels. Really weird.
This is what is supposed to happen: The scene loads, and the view is hidden to start. The user taps the "show details" button, and the view slides down into view.
But what happens is this: The scene loads and the view is hidden. So far so good. The user taps the "show details button", and the button doesn't do anything. It just slides down a negligible amount. Then the user taps it again, and it finally reveals the view. Why the two taps? I don't know.
I had the console print out the height of the view, and when the scene first loads, the view is at 237.0 for height, but when I tap the button, the height becomes 235.5. Why? This is really puzzling me.
Here's the code:
class Step5IncomeSummaryVC: UIViewController {
#IBOutlet weak var detailsView: UIView!
#IBOutlet weak var viewTop: NSLayoutConstraint!
#IBOutlet weak var showDetailsButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
showDetailsButton.setTitle("show details", for: .normal)
viewTop.constant = -(detailsView.bounds.height)
detailsView.isHidden = true
print("Initial view height: \(detailsView.bounds.height)") // check height of view BEFORE animation
}
#IBAction func showDetailsButtonTapped(_ sender: UIButton) {
print("Button pressed view height: \(detailsView.bounds.height)") // check height of view AFTER button press
if viewTop.constant == -(detailsView.bounds.height) {
detailsView.isHidden = false
showDetailsButton.setTitle("hide details", for: .normal)
UIView.animate(withDuration: 0.25, animations: {
self.viewTop.constant = 0
self.view.layoutIfNeeded()
})
print("After animation view height: \(detailsView.bounds.height)") // check height of view after animation
} else {
UIView.animate(withDuration: 0.25, animations: {
self.viewTop.constant = -(self.detailsView.bounds.height)
self.view.layoutIfNeeded()
})
showDetailsButton.setTitle("show details", for: .normal)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
self.detailsView.isHidden = true
}
}
}

How to add buttons when NSVisualEffectView is used

I have created a window using NSVisualEffectView to get blur and rounded corners. Like here
The problem is I don't see my button in the window when I have NSVisualEffectView code. If I remove the code, the button is displayed. What is going wrong?
NSVisualEffectView code in AppDelegate.swift:
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
guard let window = NSApplication.shared().windows.first else { return }
let effect = NSVisualEffectView(frame: NSRect(x: 0, y: 0, width: 0, height: 0))
effect.blendingMode = .behindWindow
effect.state = .active
effect.material = .dark
effect.wantsLayer = true
effect.layer?.cornerRadius = 15.0
effect.layer?.masksToBounds = true
window.isOpaque = false
window.backgroundColor = .clear
window.contentView = effect
window.titlebarAppearsTransparent = true
window.titleVisibility = .hidden
}
I have added some buttons in storyboard. When I run the project I don't see any buttons.
When I remove everything from applicationDidFinishLaunching(_ aNotification: Notification) i.e., NSVisualEffectView code, I can see the buttons.
Can anyone tell me what is happening?
I think I should have corrected you in your previous question only but I didn't.
You are using Storyboard so why are you creating NSVisualViewEffect variable in your code?
Search for nsvisualeffectview in the right panel(Utilities panel) where you search for buttons etc. (object library).
Drag it and resize it according to your main view controller.
To add the blur effect and mode, go to "Attribites Inspector" in the "Utilities panel"
and set window.backgroundColor = .clear and window.isOpaque = false
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
guard let window = NSApplication.shared.windows.first else { return }
window.isOpaque = false
window.backgroundColor = .clear
}
Now you can add your buttons, text fields and run the project. You can see all your added elements.
I hope it helps!
window is above the view you are adding buttons to, so the buttons are below the blurred-out window, and are therefore impossible to see. Why not add the visualEffectView to the same view as the buttons? You'd need to insert it below the buttons to make the buttons visible.

Swift UIButton not appearing on screen

I have a view in my tabbar controller where I would like to show a button. I create this button programmatically based of a condition, therefore I use the following code but nothing is appearing:
override func viewDidLoad() {
super.viewDidLoad()
if !Settings.getIsConnected() {
notConnected()
}
}
func notConnected() {
let connectBtn = UIButton(frame: CGRect(x: self.view.center.x, y: self.view.center.y, width: 200, height: 45))
connectBtn.setTitle("Connect", forState: .Normal)
connectBtn.addTarget(self, action:#selector(self.pressedConnect(_:)), forControlEvents: .TouchUpInside)
self.view.addSubview(connectBtn)
print("Button created")
}
func pressedConnect(sender: UIButton!) {
}
I am clueless on what I am doing wrong. Anyone got suggestions? Cause it does print out "Button created" so it definitely runs the code inside the noConnected() method.
Add a background color to your UIButton and add a tint color to the title. This will resolve the problem
Try moving the code to viewDidAppear and see if the button is showing up.
The frame is not correctly set when in viewDidLoad. Use the method viewDidLayoutSubviews for the earliest possible time where the frame is correctly setup for a ViewController.
With this code change, you will need some additional logic for when your button should be added as a subview though.
A programmatically created button may not show up because of more reasons, e.g:
the tint color is not set
the background color is not set
the button is not added to the view hierarchy
the button is hidden
In your case, you should change the tint color or the background color of your button.
E.g.:
Swift 4.2:
private lazy var connectButton: UIButton = {
let button = UIButton(type: .custom)
button.backgroundColor = .green
button.setTitleColor(.black, for: .normal)
button.setTitle(NSLocalizedString("Connect", comment: ""), for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(connectButton)
}
You can re-check the button properties in the storyboard that it is not hidden.

How to add another textfield to UISearchController when focus is on Search Bar?

I'm trying to add another textfield for a 'Location' input to a UISearchController when the user focuses on the Search Bar, just below the Search Bar on the navigation bar.
Example of what I have and where I'd like it to go:
I've tried something like this, which doesn't work:
var searchController: UISearchController!
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
var myTextField: UITextField = UITextField(frame: CGRect(x: 0, y: 0, width: 200.00, height: 40.00))
myTextField.backgroundColor = UIColor.purpleColor()
myTextField.text = "Location"
myTextField.borderStyle = UITextBorderStyle.None
searchController.view.addSubview(myTextField)
}
Any help would be great! Thanks.
Don't know whether you found your answer or not. Let me suggest my solution.
Nothing wrong in your code. It works fine. But the reason why it doesn't show is , when you click in the search bar func searchBarTextDidBeginEditing(searchBar: UISearchBar) has no effect on it because you might forget to set the delegate for the search bar.
I tried your code and after setting the delegate it just works fine. Also it hides behind the navbar as the Y position is 0. The solution is,
Add the UISearchBarDelegate to your class
In viewDidLoad()
override func viewDidLoad(){
super.viewDidLoad()
searchcontroller.searchbar.delegate = self
}
In searchBarTextDidBeginEditing
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
var myTextField: UITextField = UITextField(frame: CGRect(x: 0, y: searchController.searchBar.frame.height + 20, width: view.frame.size.width, height: 40.00))
myTextField.backgroundColor = UIColor.purpleColor()
myTextField.text = "Location"
myTextField.borderStyle = UITextBorderStyle.None
searchController.view.addSubview(myTextField)
}
Hope it helps.
Try like This:
you just create a custom NavigationBar add your text field to that and override the SearchController Delegate Methods
try it may works .