Reputation: 5441
I currently have a UITextfield
with an eye icon in it that when pressed is supposed to toggle the secure text entry on and off.
I know you can check mark the "secure text entry" box in the attributes inspector but how to do it so it toggles whenever the icon is pressed?
Upvotes: 86
Views: 122886
Reputation: 180
Here is the updated version of Aimanzaki's answer which supports iOS 15.0 and later.
UITextField
extension UITextField {
fileprivate func setPasswordToggleImage(_ button: UIButton) {
var config = UIButton.Configuration.plain()
if(isSecureTextEntry) {
config.image = UIImage(systemName: "eye.slash.fill")?.withTintColor(.black, renderingMode: .alwaysOriginal)
} else {
config.image = UIImage(systemName: "eye.fill")?.withTintColor(.black, renderingMode: .alwaysOriginal)
}
config.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 16)
button.configuration = config
}
func enablePasswordToggle(){
let button = UIButton(type: .custom)
setPasswordToggleImage(button)
button.addTarget(self, action: #selector(self.togglePasswordView), for: .touchUpInside)
self.rightView = button
self.rightViewMode = .always
}
@IBAction func togglePasswordView(_ sender: Any) {
self.isSecureTextEntry.toggle()
setPasswordToggleImage(sender as! UIButton)
}
}
UITextField
outlet in viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
txtPassword.enablePasswordToggle()
}
Upvotes: 0
Reputation: 3245
Use this code,
iconClick is bool variable, or you need other condition check it,
var iconClick = true
eye Action method:
@IBAction func iconAction(sender: AnyObject) {
if iconClick {
passwordTF.isSecureTextEntry = false
} else {
passwordTF.isSecureTextEntry = true
}
iconClick = !iconClick
}
hope its helpful
Upvotes: 103
Reputation: 1421
var viewingPassword = true
@IBAction func btnEyeAction(_ sender: Any) {
passwordTF.isSecureTextEntry = viewingPassword ? false : true
viewingPassword.toggle()
}
Upvotes: 0
Reputation: 1078
Swift 5 Please use this
var btnClick = true
if(btnClick == true) {
passwordTextField.isSecureTextEntry = false
} else {
passwordTextField.isSecureTextEntry = true
}
btnClick = !btnClick
}
Upvotes: 0
Reputation: 71
This worked for me on Swift 5.0
@IBAction func changePasswordVisibility(_ sender: UIButton) {
passwordField.isSecureTextEntry.toggle()
if passwordField.isSecureTextEntry {
if let image = UIImage(systemName: "eye.fill") {
sender.setImage(image, for: .normal)
}
} else {
if let image = UIImage(systemName: "eye.slash.fill") {
sender.setImage(image, for: .normal)
}
}
}
Button attributes:
Result:
Upvotes: 4
Reputation: 634
I wrote extension for the same. To provide Password toggle.
In your Assets first add images that you want for toggle.
Add following extension for UITextField.
extension UITextField {
fileprivate func setPasswordToggleImage(_ button: UIButton) {
if(isSecureTextEntry){
button.setImage(UIImage(named: "ic_password_visible"), for: .normal)
}else{
button.setImage(UIImage(named: "ic_password_invisible"), for: .normal)
}
}
func enablePasswordToggle(){
let button = UIButton(type: .custom)
setPasswordToggleImage(button)
button.imageEdgeInsets = UIEdgeInsets(top: 0, left: -16, bottom: 0, right: 0)
button.frame = CGRect(x: CGFloat(self.frame.size.width - 25), y: CGFloat(5), width: CGFloat(25), height: CGFloat(25))
button.addTarget(self, action: #selector(self.togglePasswordView), for: .touchUpInside)
self.rightView = button
self.rightViewMode = .always
}
@IBAction func togglePasswordView(_ sender: Any) {
self.isSecureTextEntry = !self.isSecureTextEntry
setPasswordToggleImage(sender as! UIButton)
}
}
Call extension on your UITextField
Outlet
override func viewDidLoad() {
super.viewDidLoad()
txtPassword.enablePasswordToggle()
txtConfirmPassword.enablePasswordToggle()
}
Upvotes: 39
Reputation: 501
sender.isSelected = !sender.isSelected
if(sender.isSelected == true) {
RegPasswordField.isSecureTextEntry = false
sender.setBackgroundImage(UIImage(systemName: "eye.fill"), for: .normal)
} else {
RegPasswordField.isSecureTextEntry = true
sender.setBackgroundImage(UIImage(systemName: "eye"), for: .normal)
}
Upvotes: 0
Reputation: 398
only add this line into your code replace you TextField name with "textfield" Done: you need to change the isSecureTextEntry propertity to change true for password type textFiled like ......
textField.isSecureTextEntry = true
Upvotes: 0
Reputation: 497
Hope this is simpler solution rather than creating a BOOL object globally.
@IBAction func passwordToggleButton(sender: UIButton) {
let isSecureTextEntry = passwordTextField.isSecureTextEntry
passwordTextField.isSecureTextEntry = isSecureTextEntry ? false : true
if isSecureTextEntry {
visibilityButton.setImage(UIImage(named: "visibility"), for: .normal)
} else {
visibilityButton.setImage(UIImage(named: "visibility_off"), for: .normal)
}
}
Upvotes: 0
Reputation: 158
@objc func togglePasscode(){
switch textfield.isSecureTextEntry{
case true:
textfield.isSecureTextEntry = false
case false:
textfield.isSecureTextEntry = true
}
}
Here is a easy and more readable solution using Switch statement.
Upvotes: 0
Reputation: 3526
I think this is the shortest solution for secure entry as well as updating the picture of the button.
@IBAction func toggleSecureEntry(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
textfieldPassword.isSecureTextEntry = !sender.isSelected
}
Assign the show/hide picture of the button according to the state selected /default , no need to create any variable or outlet.
Upvotes: 4
Reputation: 1233
Use UITextFiled rightView to show toggle button
var rightButton = UIButton(type: .custom)
rightButton.frame = CGRect(x:0, y:0, width:30, height:30)
yourtextfield.rightViewMode = .always
yourtextfield.rightView = rightButton
Upvotes: 12
Reputation: 1250
Try this code in swift 4, tried to make a reusable code within a controller. I have set different image for buttons in storyboard as shown in the link https://stackoverflow.com/a/47669422/8334818
@IBAction func clickedShowPassword(_ sender: UIButton) {
var textField :UITextField? = nil
print("btn ",sender.isSelected.description)
switch sender {
case encryptOldPswdBtn:
encryptOldPswdBtn.isSelected = !encryptOldPswdBtn.isSelected
textField = oldPasswordTextField
default:
break
}
print("text ",textField?.isSecureTextEntry.description)
textField?.isSecureTextEntry = !(textField?.isSecureTextEntry ?? false)
}
Upvotes: 0
Reputation: 1704
Swift 4 solution
You don't need extra if statement for simple toggle isSecureTextEntry property
func togglePasswordVisibility() {
password.isSecureTextEntry = !password.isSecureTextEntry
}
But there is a problem when you toggle isSecureTextEntry UITextField doesn't recalculate text width and we have extra space to the right of the text. To avoid this you should replace text this way
func togglePasswordVisibility() {
password.isSecureTextEntry = !password.isSecureTextEntry
if let textRange = password.textRange(from: password.beginningOfDocument, to: password.endOfDocument) {
password.replace(textRange, withText: password.text!)
}
}
UPDATE
Swift 4.2
Instead of
password.isSecureTextEntry = !password.isSecureTextEntry
you can do this
password.isSecureTextEntry.toggle()
Upvotes: 25
Reputation: 2600
If you need TextField with similar feature in multiple places its best to subclass the UITextField
like follwing example -
import UIKit
class UIShowHideTextField: UITextField {
let rightButton = UIButton(type: .custom)
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
required override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
func commonInit() {
rightButton.setImage(UIImage(named: "password_show") , for: .normal)
rightButton.addTarget(self, action: #selector(toggleShowHide), for: .touchUpInside)
rightButton.frame = CGRect(x:0, y:0, width:30, height:30)
rightViewMode = .always
rightView = rightButton
isSecureTextEntry = true
}
@objc
func toggleShowHide(button: UIButton) {
toggle()
}
func toggle() {
isSecureTextEntry = !isSecureTextEntry
if isSecureTextEntry {
rightButton.setImage(UIImage(named: "password_show") , for: .normal)
} else {
rightButton.setImage(UIImage(named: "password_hide") , for: .normal)
}
}
}
After which you can use it in any ViewController,
class ViewController: UIViewController {
@IBOutlet var textField: UIShowHideTextField!
override func viewDidLoad() {
super.viewDidLoad()
textField.becomeFirstResponder()
}
}
Upvotes: 8
Reputation: 3960
Why to use an extra var
. In the action method of the eye button just do as below
password.secureTextEntry = !password.secureTextEntry
UPDATE
Swift 4.2 (as per @ROC comment)
password.isSecureTextEntry.toggle()
Upvotes: 54
Reputation: 1105
An unintended side-effect of this is that if the user toggles to insecure, and then back to secure, the existing text will be cleared if the user continues typing. The cursor may also end up in the wrong position unless we reset the selected text range.
Below is an implementation that handles these cases (Swift 4)
extension UITextField {
func togglePasswordVisibility() {
isSecureTextEntry = !isSecureTextEntry
if let existingText = text, isSecureTextEntry {
/* When toggling to secure text, all text will be purged if the user
continues typing unless we intervene. This is prevented by first
deleting the existing text and then recovering the original text. */
deleteBackward()
if let textRange = textRange(from: beginningOfDocument, to: endOfDocument) {
replace(textRange, withText: existingText)
}
}
/* Reset the selected text range since the cursor can end up in the wrong
position after a toggle because the text might vary in width */
if let existingSelectedTextRange = selectedTextRange {
selectedTextRange = nil
selectedTextRange = existingSelectedTextRange
}
}
}
This snippet is using the replace(_:withText:)
function because it triggers the .editingChanged
event, which happens to be useful in my application. Just setting text = existingText
should be fine as well.
Upvotes: 70
Reputation: 11244
In Swift 4
var iconClick : Bool!
override func viewDidLoad() {
super.viewDidLoad()
iconClick = true
}
@IBAction func showHideAction(_ sender: Any)
{
let userPassword = userPasswordTextFiled.text!;
if(iconClick == true) {
userPasswordTextFiled.isSecureTextEntry = false
iconClick = false
} else {
userPasswordTextFiled.isSecureTextEntry = true
iconClick = true
}
}
Upvotes: 1
Reputation: 484
For Xamarin folks:
passwordField.SecureTextEntry = passwordField.SecureTextEntry ? passwordField.SecureTextEntry = false : passwordField.SecureTextEntry = true;
Upvotes: 0
Reputation: 500
First you need to set image(visible or hide) of button of eye for different state (selected or normal)
than connect IBAction and write code like
@IBAction func btnPasswordVisiblityClicked(_ sender: Any) {
(sender as! UIButton).isSelected = !(sender as! UIButton).isSelected
if (sender as! UIButton).isSelected {
txtfPassword.isSecureTextEntry = false
} else {
txtfPassword.isSecureTextEntry = true
}
}
Upvotes: 1
Reputation: 1358
Swift 3
// MARK: Btn EyeAction
@IBAction func btnEyeAction(_ sender: Any) {
if(iconClick == true) {
txtPassword.isSecureTextEntry = false
iconClick = false
} else {
txtPassword.isSecureTextEntry = true
iconClick = true
}
}
Upvotes: 4
Reputation: 1411
Swift 3
passwordTF.isSecureTextEntry = true
passwordTF.isSecureTextEntry = false
Upvotes: 2
Reputation: 2251
Use button with eye image
and make buttonHandler method
set Tag for button with value 1
-(IBAction) buttonHandlerSecureText:(UIButton *)sender{
if(sender.tag ==1){
[self.textField setSecureTextEntry:NO];
sender.tag = 2;
}
else{
[self.textField setSecureTextEntry:YES];
sender.tag = 1;
}
}
Upvotes: 0
Reputation: 541
For Objective c
set image for RightButton In viewdidload Method
[RightButton setImage:[UIImage imageNamed:@"iconEyesOpen"] forState:UIControlStateNormal];
[RightButton setImage:[UIImage imageNamed:@"iconEyesClose"] forState:UIControlStateSelected];
and then set action method for that RightButton
-(IBAction)RightButton:(id)sender
{
if (_rightButton.selected)
{
_rightButton.selected = NO;
_passwordText.secureTextEntry = YES;
if (_passwordText.isFirstResponder) {
[_passwordText resignFirstResponder];
[_passwordText becomeFirstResponder];
}
}
else
{
_rightButton.selected = YES;
_passwordText.secureTextEntry = NO;
if (_passwordText.isFirstResponder) {
[_passwordText resignFirstResponder];
[_passwordText becomeFirstResponder];
}
}
}
Upvotes: 5
Reputation: 6611
Here is your answer no need to take any bool var:
@IBAction func showHideAction(sender: AnyObject) {
if tfPassword.secureTextEntry{
tfPassword.secureTextEntry = false
}else{
tfPassword.secureTextEntry = true;
}
}
Upvotes: 1
Reputation: 3244
try this line:
@IBAction func btnClick(sender: AnyObject) {
let btn : UIButton = sender as! UIButton
if btn.tag == 0{
btn.tag = 1
textFieldSecure.secureTextEntry = NO
}
else{
btn.tag = 0
textFieldSecure.secureTextEntry = NO;
}
}
Upvotes: 1
Reputation: 114836
As others have noted, the property is secureTextEntry
, but you won't find this in the UITextField
documentation, as it is actually inherited by a UITextField
through the UITextInputTraits
protocol- https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/#//apple_ref/occ/intfp/UITextInputTraits/secureTextEntry
You can simply toggle this value each time your button is tapped:
@IBAction func togglePasswordSecurity(sender: UIButton) {
self.passwordField.secureTextEntry = !self.passwordField.secureTextEntry
}
Upvotes: 1
Reputation: 1531
Assignment values change from YES/NO
to true/false
boolean values.
password.secureTextEntry = true //Visible
password.secureTextEntry = false //InVisible
You can try this code.. i think it's helpful.
Upvotes: 0
Reputation: 3317
@IBAction func eye_toggle_clicked(sender: AnyObject)
{
if toggleBtn.tag == 0
{
passwordTxt.secureTextEntry=true
toggleBtn.tag=1
}
else
{
passwordTxt.secureTextEntry=false
toggleBtn.tag=0
}
}
Upvotes: 1