Swift: Add done, next, previous functions in toolbar - ios

I want to add the function next provious and done but i don't know. Please help me because I am new in swift. Here is the code:
var inputToolbar: UIToolbar = {
var toolbar = UIToolbar()
toolbar.barStyle = .default
toolbar.isTranslucent = true
toolbar.sizeToFit()
var doneButton = UIBarButtonItem(title: "Done", style: .bordered, target: self, action: Selector("doneButtonAction"))
var flexibleSpaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
var fixedSpaceButton = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
var nextButton = UIBarButtonItem(image: UIImage(named: "1"), style: .bordered, target: self, action:Selector(("nextButtonAction")))
nextButton.width = 13.0
var previousButton = UIBarButtonItem(image: UIImage(named: "2"), style: .bordered, target: self, action: Selector("previousButtonAction"))
previousButton.width = 13.0
toolbar.setItems([fixedSpaceButton, nextButton, fixedSpaceButton, previousButton, flexibleSpaceButton, doneButton], animated: true)
toolbar.isUserInteractionEnabled = true
return toolbar
}()
func doneButtonAction()
{
// here should be the code for Done button
}
func nextButtonAction()
{
// here should be the code for Next button
}
func previousButtonAction()
{
// here should be the code for Previous button
}
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
percentageField.inputAccessoryView = inputToolbar
valueField.inputAccessoryView = inputToolbar
}
The design is OK now i need actions to be functional
Thanks in advance.

extension UIViewController {
func addInputAccessoryForTextFields(textFields: [UITextField], dismissable: Bool = true, previousNextable: Bool = false) {
for (index, textField) in textFields.enumerated() {
let toolbar: UIToolbar = UIToolbar()
toolbar.sizeToFit()
var items = [UIBarButtonItem]()
if previousNextable {
let previousButton = UIBarButtonItem(image: UIImage(named: "prevArrow"), style: .plain, target: nil, action: nil)
previousButton.width = 30
if textField == textFields.first {
previousButton.isEnabled = false
} else {
previousButton.target = textFields[index - 1]
previousButton.action = #selector(UITextField.becomeFirstResponder)
}
let nextButton = UIBarButtonItem(image: UIImage(named: "nextArrow"), style: .plain, target: nil, action: nil)
nextButton.width = 30
if textField == textFields.last {
nextButton.isEnabled = false
} else {
nextButton.target = textFields[index + 1]
nextButton.action = #selector(UITextField.becomeFirstResponder)
}
items.append(contentsOf: [previousButton, nextButton])
}
let spacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: view, action: #selector(UIView.endEditing))
items.append(contentsOf: [spacer, doneButton])
toolbar.setItems(items, animated: false)
textField.inputAccessoryView = toolbar
}
}
}
In your viewDidLoad() add this
addInputAccessoryForTextFields(textFields: [textFld1, textFld2, textFld3, textFld4], dismissable: true, previousNextable: true)

Made few changes in your code. For inputToolbar check below code:
var inputToolbar: UIToolbar = {
var toolbar = UIToolbar()
toolbar.barStyle = .default
toolbar.isTranslucent = true
toolbar.sizeToFit()
//Removed bordered because it's deprecated. And corrected all selectors for all buttons
var doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(doneButtonAction))
var flexibleSpaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
var fixedSpaceButton = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
//Set image instead of title here
var nextButton = UIBarButtonItem(title: "left", style: .plain, target: self, action: #selector(previousButtonAction))
nextButton.width = 13.0
var previousButton = UIBarButtonItem(title: "right", style: .plain, target: self, action: #selector(nextButtonAction))
previousButton.width = 13.0
toolbar.setItems([fixedSpaceButton, nextButton, fixedSpaceButton, previousButton, flexibleSpaceButton, doneButton], animated: true)
toolbar.isUserInteractionEnabled = true
return toolbar
}()
Now for the helper function add #objc before func to make #selector working.
check update code with working functionality.
#objc func doneButtonAction()
{
self.view.endEditing(true)
}
#objc func nextButtonAction()
{
if let selectedRange = percentageField.selectedTextRange {
// and only if the new position is valid
if let newPosition = percentageField.position(from: selectedRange.start, offset: 1) {
// set the new position
percentageField.selectedTextRange = percentageField.textRange(from: newPosition, to: newPosition)
}
}
}
#objc func previousButtonAction()
{
if let selectedRange = percentageField.selectedTextRange {
// and only if the new position is valid
if let newPosition = percentageField.position(from: selectedRange.start, offset: -1) {
// set the new position
percentageField.selectedTextRange = percentageField.textRange(from: newPosition, to: newPosition)
}
}
}
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
percentageField.inputAccessoryView = inputToolbar
return true
}
In your textFieldShouldBeginEditing method you have two textField so you need to manage which textField is tapped. And according to that you can manage nextButtonAction and previousButtonAction method.
here you can see the result:
And here is demo project for more info.

Related

How to create programmatically a toolbar that will fill all the bottom space in Swift

How can I force the toolbar to fill all bottom space? Because, as you can see, right now toolbar only took a small line, and the space under the toolbar is empty.
import UIKit
import CoreData
import Foundation
class AllChecklistsT1: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let b1 = UIBarButtonItem(title: "Button 1", style: .plain, target: self, action: nil)
let b2 = UIBarButtonItem(title: "Button 2", style: .plain, target: self, action: nil)
self.toolbarItems = [b1, spaceButton, b2]
self.navigationController?.isToolbarHidden = false
self.tabBarController?.tabBar.isHidden = true
self.navigationController?.toolbar.backgroundColor = .systemPink
self.view.backgroundColor = .darkGray
}
}

How can I show done button on the decimal pad keyboard?

I'm trying to learn Swift and I've done on the view screens. But as you can understand more easily by checking the screenshot, when I enter a value into a text field, there isn't any done button showing up so I can not hide the keyboard from the screen. And that makes it impossible to press the submit button which is located bottom of the screen view.
Firstly, create a new Swift File. Add this to the file :
import Foundation
import UIKit
extension UIViewController{
func toolBar() -> UIToolbar{
let toolBar = UIToolbar()
toolBar.barStyle = .default
toolBar.isTranslucent = true
toolBar.barTintColor = UIColor.init(red: 0/255, green: 25/255, blue: 61/255, alpha: 1) //Write what you want for color
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
var buttonTitle = "Done" //Or "Tamam"
var cancelButtonTitle = "Cancel" //Or "İptal" for Turkish
let doneButton = UIBarButtonItem(title: buttonTitle, style: .done, target: self, action: #selector(onClickDoneButton))
let cancelButton = UIBarButtonItem(title: cancelButtonTitle, style: .plain, target: self, action: #selector(onClickCancelButton))
doneButton.tintColor = .white
cancelButton.tintColor = .white
toolBar.setItems([cancelButton, space, doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
toolBar.sizeToFit()
return toolBar
}
#objc func onClickDoneButton(){
view.endEditing(true)
}
#objc func onClickCancelButton(){
view.endEditing(true)
}
}
And add this toolbar to your textfield :
yourTextField.inputAccessoryView = toolBar()
Hope it helps...
You can add a toolbar as an input accessory :
let toolBar = UIToolbar()
toolBar.sizeToFit()
let button = UIBarButtonItem(title: "Done", style: .plain, target: self,
action: #selector(dismiss))
toolBar.setItems([button], animated: true)
toolBar.isUserInteractionEnabled = true
textField.inputAccessoryView = toolBar
Also you need to add dismiss method:
#objc func dismiss() {
view.endEditing(true)
}
Without switching back to UIKit Used the following library
Link: https://github.com/siteline/SwiftUI-Introspect
import SwiftUI
import Introspect
struct ContentView : View {
#State var text = ""
var body: some View {
TextField("placeHolder", text: $text)
.keyboardType(.default)
.introspectTextField { (textField) in
let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: textField.frame.size.width, height: 44))
let flexButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(textField.doneButtonTapped(button:)))
doneButton.tintColor = .systemPink
toolBar.items = [flexButton, doneButton]
toolBar.setItems([flexButton, doneButton], animated: true)
textField.inputAccessoryView = toolBar
}
}
extension UITextField {
#objc func doneButtonTapped(button:UIBarButtonItem) -> Void {
self.resignFirstResponder()
}
}

Done Button Issue In Toolbar

I added a toolbar with done and cancel buttons and everything was right. Suddenly, the done and cancel text is hidden. The buttons exist and are clickable but with no text. I tried everything but same problem.
This is the code regarding the toolbar:
func createDatePicker(){
//format for datepicker display
datePicker.datePickerMode = .date
datePicker.minimumDate = Date()
datePicker.backgroundColor = UIColor.white
// ToolBar
let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.default
toolBar.isTranslucent = true
toolBar.backgroundColor = UIColor(red: 253/255, green: 184/255, blue: 20/35, alpha: 1.0)
//datePicker.tintColor = UIColor.blue
toolBar.tintColor = UIColor.blue
toolBar.sizeToFit()
toolBar.isUserInteractionEnabled = true
//add a done button on this toolbar
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneClicked))
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelClicked))
toolBar.setItems([cancelButton,spaceButton,doneButton], animated: true)
testfield.inputAccessoryView = toolBar
testfield.inputView = datePicker
self.view.addSubview(testfield)
}
And this is the result:
Here is the Code is am using based on your code and it is working perfectly fine for me
import UIKit
class ViewController: UIViewController {
var datePicker = UIDatePicker()
var testfield: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
createDatePicker()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func createDatePicker(){
// TextField
testfield = UITextField(frame: CGRect(x: 20, y: 100, width: 300, height: 40))
testfield.placeholder = "testfiled"
self.view.addSubview(testfield)
//format for datepicker display
datePicker.datePickerMode = .date
datePicker.minimumDate = Date()
datePicker.backgroundColor = UIColor.white
// ToolBar
let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.default
toolBar.isTranslucent = true
toolBar.backgroundColor = UIColor(red: 253/255, green: 184/255, blue: 20/35, alpha: 1.0)
//datePicker.tintColor = UIColor.blue
toolBar.tintColor = UIColor.blue
toolBar.sizeToFit()
toolBar.isUserInteractionEnabled = true
//add a done button on this toolbar
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneClicked))
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelClicked))
toolBar.setItems([cancelButton,spaceButton,doneButton], animated: true)
testfield.inputAccessoryView = toolBar
testfield.inputView = datePicker
}
#objc func doneClicked(){
}
#objc func cancelClicked(){
}
}
Please try to test on both Device And Simulator
Or try clean(shift+cmd+k) project before build this helps in most of cases.
Result
I did a WORK AROUND by adding image to the done and cancel button
let DonebuttonIcon = UIImage(named: "done-calender.png")
let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: #selector(doneClicked))
doneButton.image = DonebuttonIcon
doneButton.tintColor = UIColor.gray
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let CancelbuttonIcon = UIImage(named: "cancel-calender.png")
let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.done, target: self, action: #selector(cancelClicked))
cancelButton.image = CancelbuttonIcon
cancelButton.tintColor = UIColor.gray

Change UIBarButtonItem Icon after pressed iOS swift

In the viewDidload method, I've declared a button and set RightBarButton...
let btnFavourite = UIButton(frame: CGRectMake(0,0,30,30))
btnFavourite.addTarget(self, action: "btnFavourite:", forControlEvents: .TouchUpInside)
btnFavourite.setImage(UIImage(named: "star"), forState: .Normal)
btnFavourite.setImage(UIImage(named: "star_filled"), forState: .Highlighted)
let rightButton = UIBarButtonItem(customView: btnFavourite)
self.navigationItem.setRightBarButtonItems([rightButton], animated: true)
How do I pressed the button from image 'star.png' then change to 'star_filled.png'? and press the button from 'star_filled.png' to 'star.png'?
How to make two functions like
func btnFavourite()
{
//clicked the favourite button then image change to star_filled.png
}
fun btnUnfavourite()
{
//clicked the button then the bar button image change to star.png
}
Create Method which will update you Button based on the state of self.isFavourited
var isFavourited = false;//declare this above the viewDidload()
func updateRighBarButton(isFavourite : Bool){
let btnFavourite = UIButton(frame: CGRectMake(0,0,30,30))
btnFavourite.addTarget(self, action: "btnFavouriteDidTap", forControlEvents: .TouchUpInside)
if isFavourite {
btnFavourite.setImage(UIImage(named: "star_filled"), forState: .Normal)
}else{
btnFavourite.setImage(UIImage(named: "star"), forState: .Normal)
}
let rightButton = UIBarButtonItem(customView: btnFavourite)
self.navigationItem.setRightBarButtonItems([rightButton], animated: true)
}
func btnFavouriteDidTap()
{
//do your stuff
self.isFavourited = !self.isFavourited;
if self.isFavourited {
self.favourite();
}else{
self.unfavourite();
}
self.updateRighBarButton(self.isFavourited);
}
func favourite()
{
//do your favourite stuff/logic
}
func unfavourite(){
//do your unfavourite logic
}
In the viewDidload method, call first time, i.e.
self.updateRighBarButton(self.isFavourited);//first time self.isFavourited will be false
I'm sure there's a more elegant way to do it, but this is what worked for me:
In viewDidLoad():
let share_button = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(shareTapped))
let fave_button = UIBarButtonItem(image: UIImage(named: "icon-star"), style: .plain, target: self, action: #selector(favorite))
let faved_button = UIBarButtonItem(image: UIImage(named: "icon-star-filled"), style: .plain, target: self, action: #selector(unfavorite))
if YOUROBJECT.faved{
navigationItem.rightBarButtonItems = [share_button, faved_button]
}
else{
navigationItem.rightBarButtonItems = [share_button, fave_button]
}
Then create the two #selector functions:
#objc func favorite(){
let share_button = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(shareTapped))
let faved_button = UIBarButtonItem(image: UIImage(named: "icon-star-filled"), style: .plain, target: self, action: #selector(unfavorite))
navigationItem.rightBarButtonItems = [share_button, faved_button]
YOUROBJECT.faved = true
}
#objc func unfavorite(){
let share_button = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(shareTapped))
let fave_button = UIBarButtonItem(image: UIImage(named: "icon-star"), style: .plain, target: self, action: #selector(favorite))
navigationItem.rightBarButtonItems = [share_button, fave_button]
YOUROBJECT.faved = false
}

Swift IOS - Using UIPickerView AND Keyboard

In my app when user clicks on UITextField he should be able to pick up a value from UIPickerView OR enter his own value using keyboard.
What's the best way of doing it in terms of user experience and ease of implementation?
UIPickerView with toolbar is already implemented.
I'd appreciate both advice on best way of doing it and example code of switching keyboard <-> pickerview.
I've tried adding a button "Show keyboard" on pickerview's toolbar and adding the following code:
func showKeyboard() {
selectedTextField.inputView = nil
}
But clicking this button doesn't do anything. Also I'm not sure it's a good way in terms of UX.
Here's the solution:
var useKeyboard:Bool = true
func showKeyboard() {
if useKeyboard {
useKeyboard = false
selectedTextField.inputView = nil
selectedTextField.reloadInputViews()
selectedTextField.keyboardAppearance = UIKeyboardAppearance.Default
selectedTextField.keyboardType = UIKeyboardType.Default
} else {
useKeyboard = true
selectedTextField.inputView = nil
selectedTextField.reloadInputViews()
createPicker(selectedTextField)
selectedTextField.resignFirstResponder()
selectedTextField.becomeFirstResponder()
}
}
// That's my custom picker - adjust whatever you need
func createPicker(sender: UITextField){
selectedTextField = sender
// Create picker view
var newPickerView: UIPickerView
newPickerView = UIPickerView(frame: CGRectMake(0, 200, view.frame.width, 300))
newPickerView.backgroundColor = .whiteColor()
// Only for UIPickerView
newPickerView.showsSelectionIndicator = true
newPickerView.delegate = self
newPickerView.dataSource = self
// Create toolbar
var toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.Default
toolBar.translucent = true
toolBar.tintColor = UIColor(red: 76/255, green: 217/255, blue: 100/255, alpha: 1)
toolBar.sizeToFit()
// Create buttons
var doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: self, action: "donePicker")
var spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
var cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.Plain, target: self, action: "cancelPicker")
var customButton = UIBarButtonItem(title: "Keyboard", style: UIBarButtonItemStyle.Plain, target: self, action: "showKeyboard")
// Assign buttons to toolbar
toolBar.setItems([cancelButton, spaceButton, customButton, doneButton], animated: false)
toolBar.userInteractionEnabled = true
// Add pickerview and toolbar to textfield
sender.inputView = newPickerView
sender.inputAccessoryView = toolBar
}
func donePicker() {
useKeyboard = true
selectedTextField.resignFirstResponder()
}
func cancelPicker() {
useKeyboard = true
selectedTextField.resignFirstResponder()
}

Resources