I'm trying to show a UIAlertController over a UIButton. The button is of type custom, and I have set the tint color to UIColor.clear, because I don't want any tint color. I've read that setting your UIButton to custom turns off the tint color, but that doesn't work for me. This method works out ok, until I show an alert controller on top.
This is before adding the alert:
This is what it looks like when I show the alert:
There's a clear grey tint color around the UIButton. It does this with any .selected UIButtons. How do I get rid of this tint? I really don't want to make my own button class just to get rid of this.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var starBtn: UIButton!
var selected: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
starBtn.isSelected = selected
starBtn.setImage(UIImage(named: "StarButtonSelected"), for: .selected)
starBtn.setImage(UIImage(named: "StarButtonDeselected"), for: .normal)
starBtn.isHighlighted = false
starBtn.tintColor = UIColor.clear
starBtn.backgroundColor = UIColor.clear
}
#IBAction func starBtnUp(_ sender: Any) {
selected = !selected
starBtn.isSelected = selected
}
#IBAction func showAlertBtnUp(_ sender: Any) {
let shareFileAction = UIAlertAction(title: "Share File", style: .default) { action in
}
let shareWebLink = UIAlertAction(title: "Share Link", style: .default) { action in
}
let alert = UIAlertController(title: "Share", message: "What do you want to share?", preferredStyle: .alert)
alert.addAction(shareFileAction)
alert.addAction(shareWebLink)
self.present(alert, animated: true) {
}
}
}
Edit: Okay, so if I create the button programmatically only, without using IB, it doesn't do the grey tint thing. I really don't want to have to not use IB though. Here's the re-written code that works how I want it to.
class ViewController: UIViewController {
var starBtn: UIButton!
var selected: Bool = true
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
starBtn = UIButton(type: .custom)
self.view.addSubview(starBtn)
starBtn.translatesAutoresizingMaskIntoConstraints = false
starBtn.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
starBtn.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
starBtn.heightAnchor.constraint(equalToConstant: 60).isActive = true
starBtn.widthAnchor.constraint(equalToConstant: 60).isActive = true
starBtn.isSelected = selected
starBtn.tintColor = UIColor.clear
starBtn.setImage(UIImage(named: "StarButtonSelected"), for: .selected)
starBtn.setImage(UIImage(named: "StarButtonDeselected"), for: .normal)
starBtn.isHighlighted = false
starBtn.backgroundColor = UIColor.clear
starBtn.addTarget(self, action: #selector(starBtnUp(_:)), for: .touchUpInside)
}
#IBAction func starBtnUp(_ sender: Any) {
selected = !selected
starBtn.isSelected = selected
}
#IBAction func showAlertBtnUp(_ sender: Any) {
let shareFileAction = UIAlertAction(title: "Share File", style: .default) { action in
}
let shareWebLink = UIAlertAction(title: "Share Link", style: .default) { action in
}
let alert = UIAlertController(title: "Share", message: "What do you want to share?", preferredStyle: .actionSheet)
alert.addAction(shareFileAction)
alert.addAction(shareWebLink)
self.present(alert, animated: true) {
}
}
}
Related
I am using this library https://github.com/kciter/Floaty, I have a tab bar and in the middle I put the Floaty button
It looks like this:
However the hit area of the floaty button is way too big that I cannot tap the tab bar items on the right
Like this:
Code:
import UIKit
import Floaty
class TabBarController: UITabBarController, FloatyDelegate {
var floaty = Floaty()
override func viewDidLoad() {
super.viewDidLoad()
layoutFAB()
//floaty.addDragging()
}
#IBAction func endEditing() {
view.endEditing(true)
}
func layoutFAB() {
let item = FloatyItem()
item.hasShadow = false
item.buttonColor = UIColor.blue
item.circleShadowColor = UIColor.red
item.titleShadowColor = UIColor.blue
item.titleLabelPosition = .right
item.title = "titlePosition right"
item.handler = { item in
}
floaty.hasShadow = false
floaty.addItem(title: "I got a title")
floaty.addItem("I got a icon", icon: UIImage(named: "icShare"))
floaty.addItem("I got a handler", icon: UIImage(named: "icMap")) { item in
let alert = UIAlertController(title: "Hey", message: "I'm hungry...", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Me too", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
floaty.addItem(item: item)
floaty.paddingX = self.view.frame.width/2 - floaty.frame.width/2
floaty.paddingY = 44
floaty.buttonColor = #colorLiteral(red: 0.986409843, green: 0.4042935669, blue: 0.4366002679, alpha: 1)
floaty.plusColor = .white
floaty.fabDelegate = self
floaty.backgroundColor = .red
self.view.addSubview(floaty)
}
// MARK: - Floaty Delegate Methods
func floatyWillOpen(_ floaty: Floaty) {
print("Floaty Will Open")
}
func floatyDidOpen(_ floaty: Floaty) {
print("Floaty Did Open")
}
func floatyWillClose(_ floaty: Floaty) {
print("Floaty Will Close")
}
func floatyDidClose(_ floaty: Floaty) {
print("Floaty Did Close")
}
}
Any thoughts please? Thank you
You are using padding, adding space between frame of the button and its content. This is why the whole box is still counts as hit area. Try changing the position of the button, not padding. Floaty is a UIView subclass after all.
I know this question has been asked before but nothing worked for me and I had to ask it again.
I want an image as my back button in navigation bar, just want to change the appearance of the back button. I don't want to add a button and add selectors for it.
I tried the following code:
let backImage = UIImage(named: "Back_button")
let backAppearance = UIBarButtonItem.appearance()
backAppearance.setBackButtonBackgroundImage(backImage, for: .normal, barMetrics: .default)
navigationController?.navigationBar.backIndicatorTransitionMaskImage = backImage
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItem.Style.plain, target: nil, action: nil)
I also tried setting the back image and back mask using storyboard but both these approaches place a black circle on my back image.
I tried setting another image as back mask by setting its alpha content equal to zero using the code but it didn't work either.
please help.
let backButton = UIBarButtonItem()
backButton.title = "Back"
backButton.image = UIImage(named: "Back_button")
self.navigationController?.navigationBar.topItem?.backBarButtonItem = backButton
You can do this to customize your Back button. And you don't have to worry about adding selectors.
This code works with Swift 5.
let backButton: UIButton = UIButton()
backButton.setImage(UIImage(named: "back"), for: UIControl.State())
backButton.addTarget(self, action:#selector(SearchResultsViewController.onBack), for: UIControl.Event.touchUpInside)
let leftBarButtonItem = UIBarButtonItem(customView: backButton)
navigationItem.leftBarButtonItem = leftBarButtonItem
I used this code to customize the back button on only one of my views:
self.navigationController?.navigationBar.topItem?.backButtonTitle = ""
let backButton = UIBarButtonItem(image: UIImage(named: "back"), style: .plain, target: self, action: #selector(goBack))
navigationItem.leftBarButtonItem = backButton
#objc func goBack() {
self.navigationController?.popViewController(animated: true)
}
Create a custom class for define navigation bar traits
Create an extension to UINavigationController for configure it
import UIKit
private final class MyNavigationBarTraits {
public var backIndicatorImage: UIImage?
public var backIndicatorTransitionMaskImage: UIImage?
public func apply(to navigationBar: UINavigationBar) {
navigationBar.backIndicatorImage = backIndicatorImage
navigationBar.backIndicatorTransitionMaskImage = backIndicatorTransitionMaskImage
}
public init(navigationBar: UINavigationBar) {
backIndicatorImage = navigationBar.backIndicatorImage
backIndicatorTransitionMaskImage = navigationBar.backIndicatorTransitionMaskImage
}
}
public typealias Callback<T> = (_: T) -> Void
public extension UINavigationController {
private struct AssociationKeys {
static var navigationBarTraits = "ws_nc_navigationBarTraits"
}
private var navigationBarTraits: MyNavigationBarTraits? {
get {
return objc_getAssociatedObject(self, &AssociationKeys.navigationBarTraits) as? MyNavigationBarTraits
}
set {
objc_setAssociatedObject(self, &AssociationKeys.navigationBarTraits, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
func configureBar(block: Callback<UINavigationBar>) {
navigationBarTraits = MyNavigationBarTraits(navigationBar: navigationBar)
block(navigationBar)
}
func resetBar() {
navigationBarTraits?.apply(to: navigationBar)
navigationBarTraits = .none
}
}
And then you can configure your navigation bar in your ViewController's viewWillAppear (for example tintColor)
public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.configureBar { navigationBar in
// You can customize your navigation bar in here!
navigationBar.tintColor = .red
}
}
If you want to use this customization just in one View Controller you should reset bar in your View Controller's viewWillDisappear
public override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationController?.resetBar()
}
Simply Add Below Methods in Your ViewController :
func setLeftBarBackItem() {
let leftBarBackItem = UIBarButtonItem(image: #imageLiteral(resourceName: "imgBack"), style: .plain, target: self, action: #selector(self.clickToBtnBackItem(_:)))
self.navigationItem.leftBarButtonItem = leftBarBackItem
}
func clickToBtnBackItem(_ sender: UIBarButtonItem) {
view.endEditing(true)
_ = navigationController?.popViewController(animated: true)
}
func setTranspertNavigation()
{
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = true
self.navigationController?.view.backgroundColor = .clear
}
Inside Your ViewController's ViewDidLoad Method, Set backButton As :
self.navigationController?.isNavigationBarHidden = false
AppDelegate.shared().setupNavigationBar()
setLeftBarBackItem()
setTranspertNavigation()
self.title = "Title Here"
I have a UIAlertController of action sheet style, it has 2 normal actions and one cancel action, I wanted to have different colors of text for them and cus of this, I subclassed UIAlertController:
class CustomAlertViewController: UIAlertController {
internal var cancelText: String?
private let fontRegular = UIFont(name: "IRANSans", size: 16)
private let fontBold = UIFont(name: "IRANSans-Bold", size: 16)
override func viewDidLoad() {
super.viewDidLoad()
self.view.tintColor = UIColor.black
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.findLabel(scanView: self.view)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.findLabel(scanView: self.view)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.findLabel(scanView: self.view)
}
func findLabel(scanView: UIView!) {
if (scanView.subviews.count > 0) {
for subview in scanView.subviews {
if let label: UILabel = subview as? UILabel {
if (self.cancelText != nil && label.text == self.cancelText!) {
DispatchQueue.main.async {
label.tintColor = UIColor.red
label.highlightedTextColor = UIColor.green
label.font = self.fontBold
}
} else {
label.font = self.fontRegular
label.tintColor = UIColor(rgb: 0x2699FB)
label.highlightedTextColor = UIColor.black
}
}
self.findLabel(scanView: subview)
}
}
}
} // class end
so now normal labels has blue color and cancel label has red color. but when I select them, I don't want them to highlight as same color. this is where problem accurs, it seems that the labels highlight as UIAlertController's view.tintColor. does anyone know how can I do what I want? I mean how can I define my own highlight color for different labels?
Jafar Khoshtabiat, see below code for display red text in action sheet, I hope it's helps you. see following link for more details https://nshipster.com/uialertcontroller/
//UIActionSheet
let actionSheet = UIActionSheet(title: "Takes the appearance of the bottom bar if specified; otherwise, same as UIActionSheetStyleDefault.", delegate: self, cancelButtonTitle: "Cancel", destructiveButtonTitle: "Destroy", otherButtonTitles: "OK")
actionSheet.actionSheetStyle = .Default
actionSheet.showInView(self.view)
// MARK: UIActionSheetDelegate
func actionSheet(actionSheet: UIActionSheet, clickedButtonAtIndex buttonIndex: Int) {
switch buttonIndex {
...
}
}
//UIAlertController
let alertController = UIAlertController(title: nil, message: "Takes the appearance of the bottom bar if specified; otherwise, same as UIActionSheetStyleDefault.", preferredStyle: .ActionSheet)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (action) in
// ...
}
alertController.addAction(cancelAction)
let OKAction = UIAlertAction(title: "OK", style: .Default) { (action) in
// ...
}
alertController.addAction(OKAction)
let destroyAction = UIAlertAction(title: "Destroy", style: .Destructive) { (action) in
println(action)
}
alertController.addAction(destroyAction)
self.presentViewController(alertController, animated: true) {
// ...
}
Below is my code. I have 9 buttons in my view whose background image is to be changed.
import UIKit
class ViewController: UIViewController {
let alerts = UIAlertController(title: "Hi", message: "Hello", preferredStyle: UIAlertControllerStyle.alert)
let action1 = UIAlertAction(title: "Yes", style: UIAlertActionStyle.default) { (<#UIAlertAction#>) in
for i in 0..<9
{
let newButton = self.view.viewWithTag(i) as! UIButton
newButton.setBackgroundImage(UIImage.init(named: ""), for: .normal)
}
}
#IBAction func buttonPressed(_ sender: UIButton)
{
sender.setBackgroundImage(UIImage.init(named: "cross.png"), for:.normal)
}
}
You need to add action to UIAlertController. Add following line after defining action1:
[alerts addAction: action1]
Try this:
first add button to the view and add action for it :
for i in 0..<9
{
let newButton = UIButton(frame : yourFrame)
newButton.setBackgroundImage(UIImage.init(named: ""), for: .normal)
newButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
newbutton.tag = i
self.view.addSubview(newButton:)
}
Try this :
newButton .setBackgroundImage(UIImage.init(named: ""), for: .normal)
newButton .setBackgroundImage(UIImage.init(named: "cross.png"), for: .selected)
#IBAction func buttonPressed(_ sender: UIButton)
{
sender.isSelected = !sender.isSelected;
}
I have two button namely programs and data.This two button have drop down option.But when i select the first drop down option for program and if i select any data from drop down .say like i select "super" from drop down .Then that super word are selecting in my both button.
With out selecting my second button drop down option.Its automatically changing.For clearly, if i select super data from drop down for program button,That word "super" is updating in my both drop down button.
Please help me to fix this problem :
Here is my code:
import UIKit
class UserDetailsController: UIViewController {
var addString: String!
let dropDown = DropDown()
#IBOutlet weak var programBtn: UIButton!
#IBOutlet weak var dataBtn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
dropdownmethod()
}
func dropdownmethod () {
dropDown.dataSource = [
"Car",
"Motorcycle",
"Van",
"Truck",
"Bus",
"Bicycle",
"Feet",
"add"
]
dropDown.selectionAction = { [unowned self] (index, item) in
self.SpectifBtn.setTitle(item, forState: .Normal)
self.organBtn.setTitle(item, forState: .Normal)
if item == "add" {
if #available(iOS 8.0, *) {
let alert = UIAlertController(title: "Duplicate file", message: "Afile with the same name already exists.", preferredStyle:
UIAlertControllerStyle.Alert)
alert.addTextFieldWithConfigurationHandler(self.configurationTextField)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler:{ (UIAlertAction)in
print("User click Ok button")
print(self.textField.text)
self.addString = self.textField.text
self.dropDown.dataSource = [ "Car",
"Motorcycle",
"Van",
"Truck",
"Bus",
"Bicycle",
"Feet", "\(self.addString)", "add"]
self.SpectifBtn.setTitle(self.addString, forState: .Normal)
self.organBtn.setTitle(self.addString, forState: .Normal)
}))
self.presentViewController(alert, animated: true, completion: {
print("completion block")
})
} else {
// Fallback on earlier versions
}
}
}
dropDown.cancelAction = { [unowned self] in
self.dropDown.selectRowAtIndex(0)
self.SpectifBtn.setTitle("Canceled", forState: .Normal)
self.organBtn.setTitle("Canceled", forState: .Normal)
}
dropDown.anchorView = SpectifBtn
dropDown.bottomOffset = CGPoint(x: 0, y:SpectifBtn.bounds.height)
dropDown.dismissMode = .Automatic
dropDown.selectRowAtIndex(3)
}
func configurationTextField(textField: UITextField!)
{
if let aTextField = textField {
textField.text = "Filename"
self.textField = aTextField
}
}
#IBAction func programBtnPressed(sender: AnyObject) {
if dropDown.hidden {
dropDown.show()
} else {
dropDown.hide()
}
}
#IBAction func dataBtnPressed(sender: AnyObject) {
if dropDown.hidden {
dropDown.show()
} else {
dropDown.hide()
}
}
}
My screen shot.When i select any option from my program drop down.That option name is automatically updating in my data button name also
After dropdown selection of some item, you should check from what button it comes(by tag for example), now it seems you just select them both here:
self.SpectifBtn.setTitle(item, forState: .Normal) self.organBtn.setTitle(item, forState: .Normal)