How to apply borders and corner radius to UIBarButtonItem? - swift

I have programatically created a toolbar to which I have added a UIBarButtonItem.
This is what is currently looks like:
I want the the button to have a border and a corner radius(curved corners).
How will the same be implemented?
UIBarButtonItem Implementation code:
let okBarBtn = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: "donePressed:")

If you can find the UIView associated with the UIBarButtonItem, you can modify the UIView.layer. But, finding the UIView is not made easy. I used the technique from Figure out UIBarButtonItem frame in window? . Starting with the navigationController.navigationBar, which itself is a UIView, I recursed through the subviews, one of which will be the button I wanted. Which one? Pick your own criteria! Here's my code:
func recurseViews(view:UIView) {
print("recurseViews: \(view)") // helpful for sorting out which view is which
if view.frame.origin.x > 700 { // find _my_ button
view.layer.cornerRadius = 5
view.layer.borderColor = UIColor.redColor().CGColor
view.layer.borderWidth = 2
}
for v in view.subviews { recurseViews(v) }
}
then in viewDidAppear (or similar)
recurseViews((navigationController?.navigationBar)!)
which is a bit of a hack but does the job:

There's no built-in automatic way to do this, unfortunately. You have two choices:
You could make this a bar button item with a custom view, make that view a UIButton, and then do the usual stuff to that UIButton (which you can do because it's a view), by way of its layer (give it a border and corner radius).
You could just draw (in code) a background image with a curved border and use that as the bar button item's image.

I do it with a storyboard. Just add UIButton inside UiBarButtonItem. Like here
And after that added a border to the UIButton

Related

Why can't I edit the button shape?

Hello I am a very new and inexperienced developer and I am trying to border around a button. I'm using the Storyboard and when I used ViewController.swift, I can't make the button a weak var. It is only allowing me to edit the actions. Please help, thank you!
When I usually do this it allows me to choose if I insert "Action, Outlet or Outlet Collection."
Your screenshot shows "Mates Scene" but your class name is ViewController. It also looks like "Mates Scene" has an embed segue to a ViewController, so it looks like you might be trying to add an IBOutlet to a child view controller from one of the parent view controller's views (the "Home Button").
If so, you can't do that. You may have meant to add "Home Button" to the class of your "Mates" view controller instead.
In recent versions of iOS Buttons don't have any shape by default. They are displayed as clickable text.
Make sure you are trying to connect your outlet and action from IB to the right target view controller, as suggested by Tyler.
Once you've got the outlet and action links working you can add code to change the appearance.
If you want to make your button a rounded rectangle, say, you can do that with code that manipulates the buttons' layer settings (corner radius, borderWidth, borderColor, and backgroundColor are pretty common properties to edit.)
Here is code that turns a button into a rounded rectangle withe a 1-pixel blue outline and a yellow background color:
#IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
if let button = button {
button.layer.cornerRadius = 5
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.blue.cgColor
button.layer.backgroundColor = UIColor.yellow.cgColor
}
}
Edit:
That creates a button that looks like this:
(Note that if you use a border you may need to add some padding so that the border doesn't "crowd" the button title as in my example.)
Drag and release, then from the little menu that appears select outlet rather than action. Then, to set borders do something like:
yourButton.layer.borderWidth = 10
yourButton.layer.borderColor = UIColor.red.cgColor

How I can show/hide view inside another view with height changing of root swift?

I have two views one inside another, it looks like picture below:
when I press on orange arrow I would like to show/hide view above grey line and grey line too. I did it by such way:
#objc func showHide(tapGestureRecognizer: UITapGestureRecognizer)
{
let tappedImage = tapGestureRecognizer.view as! UIImageView
UIView.animate(withDuration: 0.2, animations: { () -> Void in
self.jobDataView.isHidden = !self.jobDataView.isHidden
self.view.layoutIfNeeded()
})
tappedImage.image = self.jobDataView.isHidden ? UIImage(systemName: "arrow.down"):UIImage(systemName: "arrow.up")
}
and my view above gray line can be hidden and shown. But root view doesn't change its' height and it has similar sizes before and after btn click. I tried to add constraint of height, but I it didn't solve my problem. Maybe someone knows how to solve my problem?
You need to use UIStackView either through Storyboard or from code. when you hide subview inside stackview it will automatically change stackview height. what you need to do is to make stackView distribution = fill and use vertical stack...
Hide view on button tap and when you need to show it .. add it in stack at. 0th index ..

Reapply constraints after hiding UITabBar

I have a UIButton that is constrained to the view's safeAreaLayoutGuide bottom anchor and a UITabBar in that UIView. Everything is okay there. However, when I fullscreen an image, I hide the UITabBar. When I dismiss the fullscreen, I show the UITabBar again. However, the UIButton moves down and doesn't constrain to the UITabBar as it did before the UITabBar was hidden. The UIButton is covered partially by the UITabBar. Any solutions?
Here is the dismiss fullscreen code.
#objc func dismissFullscreenImage(_ sender: UITapGestureRecognizer) {
sender.view?.removeFromSuperview()
self.navigationController?.isNavigationBarHidden = false
self.tabBarController?.tabBar.isHidden = false
}
Here are two things you can try:
Solution 1:
Add this line to dismissFullscreenImage():
self.view.setNeedsLayout()
This invalidates the layout of self.view and causes it to be laid out again.
Solution 2:
You can avoid the need to relayout the view by making the navigationBar and tabBar invisible.
Instead of hiding/showing the navigationBar and tabBar by changing their isHidden properties, try setting their alpha values:
// hide
self.navigationController?.navigationBar.alpha = 0
self.tabBarController?.tabBar.alpha = 0
// show
self.navigationController?.navigationBar.alpha = 1
self.tabBarController?.tabBar.alpha = 1

Swift: Round UIButton with Blur background

I am wanting to make a round UIButton but with a light blur effect with vibrancy as it's background
So far I've got a rounded UIButton, but the code I have found online (I'm new to iOS development so don't really understand how the blur etc works) to add a blur just puts it as the entire button's frame, essentially making the button appear square again.
I've also tried adding a view, then the UIButton and then the blur effect and applied the cornerRadius code to that view but it also didn't work.
Here is what I've tried:
shortcutButton.layer.cornerRadius = 0.5 * shortcutButton.bounds.size.width // add the round corners in proportion to the button size
let blur = UIVisualEffectView(effect: UIBlurEffect(style:
UIBlurEffectStyle.Light))
blur.frame = shortcutButton.bounds
blur.userInteractionEnabled = false //This allows touches to forward to the button.
shortcutButton.insertSubview(blur, atIndex: 0)
Add the following two lines of code to your project, before you add the subview:
blur.layer.cornerRadius = 0.5 * shortcutButton.bounds.size.width
blur.clipsToBounds = true
Enjoy! :)

Right align magnifying glass icon in UISearchBar

In Cocoa-Touch we find a control UISearchBar. I need to customize it so that the search icon (which we click performs the respective action) present in the textfield is right aligned. Normally we find it left aligned. Is it possible to do so? I have done R & D but couldn't find it ...
How can I do it? Are there any good tutorials where we can find it?
Unfortunately the UISearchBar wasn't designed to directly support this. In accomplishing what we want it's likely that we're going to have to use workarounds that compromise visually or functionality wise or write a lot of customising code.
I've outlined a couple of approaches that get close to what we want and may be of use.
Accessing Subviews Approach
The text within a UISearchBar is a UITextField that is a subview of that UISearchBar and is accessible through the usually means i.e. view.subviews.
The magnifying glass search icon is a UIImageView in the leftView property of the UITextField. We can switch it over to the right using the following code:
// The text within a UISearchView is a UITextField that is a subview of that UISearchView.
UITextField *searchField;
for (UIView *subview in self.searchBar.subviews)
{
if ([subview isKindOfClass:[UITextField class]]) {
searchField = (UITextField *)subview;
break;
}
}
// The icon is accessible through the 'leftView' property of the UITextField.
// We set it to the 'rightView' instead.
if (searchField)
{
UIView *searchIcon = searchField.leftView;
if ([searchIcon isKindOfClass:[UIImageView class]]) {
NSLog(#"aye");
}
searchField.rightView = searchIcon;
searchField.leftViewMode = UITextFieldViewModeNever;
searchField.rightViewMode = UITextFieldViewModeAlways;
}
Which gives us the following result:
As you can see the icon overruns the edge of the rounded rectangle and the clear icon has disappeared. In addition, the rightView property was intended for other content such as the search results button and bookmarks button. Putting the search icon here may conflict with this functionality in some way even if you were able to use padding of offsets to position it appropriately.
In the very least you can use this approach to extract the icon as a UIImageView and position it explicitly where you see fit as you would any other view and write custom code to handle tap events etc.
Customizing Appearance Approach
In iOS v5.0 and later, you can customize the appearance of search bars using the methods listed here. The following code makes use of offsets to position the icon and text within the UISearchBar:
[self.searchBar setPositionAdjustment:UIOffsetMake(255, 0) forSearchBarIcon:UISearchBarIconSearch];
[self.searchBar setSearchTextPositionAdjustment:UIOffsetMake(-270, 0)];
On a standard UISearchBar of 320 width it looks like the following:
This would keep all event functionality associated with the icon working as expected but unfortunately the UITextField is confused and despite its width, it only displays a very small portion of its text. If you could find a way to allow the text to display beyond what it believes to be the end of the UITextField, this will probably be your best bet.
My requirement was that the search icon should be on the right, and that it should hide whenever the X icon showed up.
I came up with a similar solution as above, but a bit different and also using Swift 2 and AutoLayout. The basic idea is to hide the left view, create a new view with the magnifying glass image, and use autolayout to pin it to the right. Then use UISearchBarDelegate methods to hide the search icon whenever the searchbar text is not empty.
class CustomSearchView: UIView {
//the magnifying glass we will put on the right
lazy var magnifyingGlass = UIImageView()
#IBOutlet weak var searchBar: UISearchBar!
func commonInit() {
searchBar.delegate = self
searchBar.becomeFirstResponder()
//find the search bar object inside the subview stack
if let searchField = self.searchBar.subviews.firstObject?.subviews.filter(
{($0 as? UITextField) != nil }).firstObject as? UITextField {
//hides the left magnifying glass icon
searchField.leftViewMode = .Never
//add a magnifying glass image to the right image view. this can be anything, but we are just using the system default
//from the old left view
magnifyingGlass.image = (searchField.leftView! as? UIImageView)?.image
//add the new view to the stack
searchField.addSubview(magnifyingGlass)
//use autolayout constraints to pin the view to the right
let views = ["view": magnifyingGlass]
magnifyingGlass.translatesAutoresizingMaskIntoConstraints = false
searchField.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(
"H:[view(12)]-|", options: [], metrics: nil, views: views))
searchField.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(
"V:[view]-|", options: [], metrics: nil, views: views))
}
}
//hides whenever text is not empty
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
magnifyingGlass.hidden = searchText != ""
}
}