In a previous post, we looked at how easy it was to add a Password Toggle button in our Xamarin.Android apps (or native Android since it was only in the xml layout): Xamarin.Tip – Adding a Password Toggle Button in Android
So in this post, let’s work toward a similar behavior in our Xamarin Native iOS!
The basic premise is to extend the UITextField
control and add a SubView
to it for the button. Then on this UIButton.TouchUpInside
, we want to toggle the UITextField.SecureTextEntry
boolean property.
With that in mind, there are a number of ways we can do this!
- Create a custom
PasswordToggleTextField
and design it in a xib to drag and drop the button - Add the
UIButton
at runtime everywhere we want to use it - My Favorite: Use NativeBehaviors and create a reusable behavior that can be attached to any given
UITextField
.
Let’s continue down this path with the NativeBehaviors approach. Of course, if you don’t want to do it this way, you can simply copy the code within the Behavior we create and apply it anywhere else.
NativeBehaviors is a package I created just a little while back that brings the Xamarin.Forms style Behavior pattern to native iOS, Android, and UWP controls. So if you’ve written Xamarin.Forms Behaviors before, this should be super familiar!
- Xamarin.Forms Behaviors: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/behaviors/
- NativeBehaviors: https://alexdunn.org/2018/01/29/xamarin-nuget-native-behaviors/
Let’s do this by creating a simple TextFieldTogglePasswordBehavior
.
TextFieldTogglePasswordBehavior.cs
/// <summary> /// Text field toggle password behavior. /// </summary> public class TextFieldTogglePasswordBehavior : NativeBehavior<UITextField> { public override string BehaviorName => nameof(TextFieldTogglePasswordBehavior); private UIButton _togglePasswordButton; /// <summary> /// Attach show/hide button /// </summary> /// <param name="bindable">Bindable.</param> protected override void OnAttachedTo(UITextField bindable) { _togglePasswordButton = new UIButton() { Frame = new CGRect(0, 0, 50, 8) }; _togglePasswordButton.SetTitle(bindable.SecureTextEntry ? "Show" : "Hide", UIControlState.Normal); _togglePasswordButton.SetTitleColor(UIColor.White, UIControlState.Normal); _togglePasswordButton.SetAttributedTitle(new Foundation.NSAttributedString(bindable.SecureTextEntry ? "Show" : "Hide", UIFont.SystemFontOfSize(12)), UIControlState.Normal); _togglePasswordButton.TouchUpInside += (sender, e) => { var updatedIsPassword = !bindable.SecureTextEntry; bindable.SecureTextEntry = updatedIsPassword; _togglePasswordButton.SetTitle(updatedIsPassword ? "Show" : "Hide", UIControlState.Normal); _togglePasswordButton.SetAttributedTitle(new Foundation.NSAttributedString(updatedIsPassword ? "Show" : "Hide", UIFont.SystemFontOfSize(12)), UIControlState.Normal); }; _togglePasswordButton.TitleLabel.TextColor = UIColor.White; bindable.RightViewMode = UITextFieldViewMode.Always; bindable.RightView = _togglePasswordButton; bindable.RightViewRect(new CGRect(0,0, 50,8)); } /// <summary> /// Kill the button /// </summary> /// <param name="bindable">Bindable.</param> protected override void OnDetachingFrom(UITextField bindable) { _togglePasswordButton = null; bindable.RightView = null; } }
If you read through the code a bit, you noticed that we simply create a UIButton
, set its text to UIColor.White
, and then update the text of the button to either “Show” or “Hide” depending on the state, and then in the TouchUpInside
handler, we update that state as well as the SecureTextEntry
property of the parent UITextField
this behavior gets attached to!
You can also update this to use icons instead of regular text buttons to get a behavior closer to the Android treatment if you wanted. It’s just a button, so go crazy.
Now let’s take this behavior and attach it to an existing UITextField
control that we have added to a UIViewController
in our Storyboard.
In this example, I’m using a custom UITextField
called MaterialTextField
to show that this behavior is usable on the built in controls as well as any other custom UITextField
:
LoginViewController.cs
public class LoginViewController : UIViewController { // note: this is now reusable if you want to apply the behavior to multiple fields // without creating a bunch of new instances. private readonly TextFieldTogglePasswordBehavior _togglePasswordBehavior = new TextFieldTogglePasswordBehavior(); protected void ViewDidLoad() { PasswordTextField.AttachBehavior(_togglePasswordBehavior); } }
And that’s it! If we want to remove the button and detach the behavior, all we have to do is call:
PasswordTextField.DetachBehavior(_togglePasswordBehavior);
With all that together, we get a pretty neat control!
In a future post, we can look at how to achieve this same concept in Xamarin.Forms – without using custom renderers!
If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!
Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.
One thought on “Xamarin.Tip – Adding a Password Toggle Button in iOS”