Xamarin.Forms Tip : Implement Show Hide Password using effects

Xamarin.Forms Tip : Implement Show Hide Password using effects

While developing login pages we usually get a requirement that there should be icon in password entry to show/hide password while entering the password. While looking for solution for this requirement I found that most of the implementation is done using custom controls whereas we can do these kind of small small platform specific customization using effects. Last year I wrote this article about implementing custom fonts using effects so I thought lets try this also using the same.

Creating the Effect:

  1. Changes in PCL project:
  2. Create a new class file named ‘ShowHidePassEffect’ and add following code to it:

    	public class ShowHidePassEffect : RoutingEffect
    	{
                    public string EntryText { get; set; }
    		public ShowHidePassEffect() : base("Xamarin.ShowHidePassEffect"){}
    	}
    

    In the above mentioned code we are creating a custom effect where we are creating a new property named ‘EntryText’ to show the entered password text. The implementation of this effect will have to be written in Platform specific projects.

  3. Changes in Android project:
  4. In your Android project, create a new class file named ‘ShowHidePassEffect’ and add following code to it:

    using Android.Text.Method;
    using Android.Views;
    using Android.Widget;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.Android;
    
    [assembly: ResolutionGroupName("Xamarin")]
    [assembly: ExportEffect(typeof(ShowHidePassEx.Droid.Effects.ShowHidePassEffect), "ShowHidePassEffect")]
    namespace ShowHidePassEx.Droid.Effects
    {
        public class ShowHidePassEffect : PlatformEffect
    	{
    
    
    		protected override void OnAttached()
    		{
    			ConfigureControl();
    		}
    
    		protected override void OnDetached()
    		{
    		}
    
    		private void ConfigureControl()
    		{
    			EditText editText = ((EditText)Control);
    			editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, Resource.Drawable.ShowPass, 0);
    			editText.SetOnTouchListener(new OnDrawableTouchListener());
    
    		}
    	}
    
    	public class OnDrawableTouchListener : Java.Lang.Object, Android.Views.View.IOnTouchListener
    	{
    		public bool OnTouch(Android.Views.View v, MotionEvent e)
    		{
    			if (v is EditText && e.Action == MotionEventActions.Up)
    			{
    				EditText editText = (EditText)v;
    				if (e.RawX >= (editText.Right - editText.GetCompoundDrawables()[2].Bounds.Width()))
    				{
    					if (editText.TransformationMethod == null)
    					{
    						editText.TransformationMethod = PasswordTransformationMethod.Instance;
                            editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, Resource.Drawable.ShowPass, 0);
    					}
    					else
    					{
    						editText.TransformationMethod = null;
                            editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, Resource.Drawable.HidePass, 0);
    					}
    
    					return true;
    				}
    			}
    
    			return false;
    		}
    	}
    }
    

    In the above mentioned Android implementation of the effect we are adding the code to create the control manually in ‘OnDrawableTouchListener’ method where we are adding the ShowPass and HidePass icons to the entry control, changing them on the basis of user touch action and attaching it on effect invocation which will be fired when the effect will be added to the control.
    Before writing this code make sure that you have ShowPass and HidePass images in your Resources/Drawable folder of Android project. like following image :

    These images can be downloaded from internet or your project’s designer can provide it.

  5. Changes in Android project:
  6. Similarly in your iOS project create a new class file named ‘ShowHidePassEffect’ and add following code to it:

    using System;
    using ShowHidePassEx.iOS.Effects;
    using UIKit;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.iOS;
    
    
    [assembly: ResolutionGroupName("Xamarin")]
    [assembly: ExportEffect(typeof(ShowHidePassEffect), "ShowHidePassEffect")]
    namespace ShowHidePassEx.iOS.Effects
    {
        public class ShowHidePassEffect: PlatformEffect
        {
           
    		protected override void OnAttached()
    		{
                ConfigureControl();
    		}
    
    		protected override void OnDetached()
    		{
                
    		}
    
    		private void ConfigureControl()
    		{
                if (Control != null)
                {
    				UITextField vUpdatedEntry = (UITextField)Control;
    				var buttonRect = UIButton.FromType(UIButtonType.Custom);
    				buttonRect.SetImage(new UIImage("ShowPass"), UIControlState.Normal);
    				buttonRect.TouchUpInside += (object sender, EventArgs e1) =>
    				{
    					if (vUpdatedEntry.SecureTextEntry)
    					{
    						vUpdatedEntry.SecureTextEntry = false;
    						buttonRect.SetImage(new UIImage("HidePass"), UIControlState.Normal);
    					}
    					else
    					{
    						vUpdatedEntry.SecureTextEntry = true;
    						buttonRect.SetImage(new UIImage("ShowPass"), UIControlState.Normal);
    					}
    				};
    
    				vUpdatedEntry.ShouldChangeCharacters += (textField, range, replacementString) =>
    				{
    					string text = vUpdatedEntry.Text;
    					var result = text.Substring(0, (int)range.Location) + replacementString + text.Substring((int)range.Location + (int)range.Length);
    					vUpdatedEntry.Text = result;
    					return false;
    				};
    
    
    				buttonRect.Frame = new CoreGraphics.CGRect(10.0f, 0.0f, 15.0f, 15.0f);
    				buttonRect.ContentMode = UIViewContentMode.Right;
    
    				UIView paddingViewRight = new UIView(new System.Drawing.RectangleF(5.0f, -5.0f, 30.0f, 18.0f));
    				paddingViewRight.Add(buttonRect);
    				paddingViewRight.ContentMode = UIViewContentMode.BottomRight;
    
    
    				vUpdatedEntry.LeftView = paddingViewRight;
    				vUpdatedEntry.LeftViewMode = UITextFieldViewMode.Always;
    
    				Control.Layer.CornerRadius = 4;
    				Control.Layer.BorderColor = new CoreGraphics.CGColor(255, 255, 255);
    				Control.Layer.MasksToBounds = true;
    				vUpdatedEntry.TextAlignment = UITextAlignment.Left;
    			}
    
    		}
        }
    }
    

    In the above mentioned iOS implementation of the effect we are adding the code to create the control manually in ‘ConfigureControl’ method where we are adding the ShowPass and HidePass icons to the entry control, changing them on the basis of user touch action and attaching it on effect invocation which will be fired when the effect will be added to the control.
    Just like Android here too, make sure that you have ShowPass and HidePass images in your Resources folder of iOS project. like following image :

    Using the Effect:
    In order to use the effect we will just have to add the effect to the entry control in XAML like following code :

            <Entry IsPassword="true" Placeholder="Password" Text="Password">
                <Entry.Effects>
                    <ef:ShowHidePassEffect />
                </Entry.Effects>
            </Entry>
    

    And if you want to use it inside your c# code you can do that like following code.

         var vPasswordEntry = new Entry() { IsPassword=true };
         vPasswordEntry.Effects.Add(new FontEffect());
    

    This is how sample application whose code is published on Github looks on executing.

    iOS Simulator

    Android Simulator

    This is one simple tip to implement Show/Hide password feature in your Xamarin.Forms mobile apps, will try to come up with more such tips in future let me know if I has missed anything or have any suggestions/concerns/queries.

    🙂 🙂 Happy Coding 🙂 🙂

7 thoughts on “Xamarin.Forms Tip : Implement Show Hide Password using effects

  1. Very useful post. I implemented the same way you have described.
    You forgot to include the namespace in the xaml page for the

    Thanks
    Visakh

    1. Hi Visakh, If you see clearly the XAML is not the complete XAML, it’s only the syntax on where to add the effect to the control. If you go through the accompanying code of the blog you will see that the it has the effects implimented, that’s why the code is working otherwise it wouldn’t have.

      Thanks
      Ravi

  2. Have you noticed anything around Android tablets not showing the keyboard? We have a login screen and with the effect the keyboard doesn’t come up at all when the user taps into the password field. With the effect removed, it works fine. Android phones are fine, as are all iOS devices, so just Android tablets, which is kind of weird.

    1. Hi, Sorry I haven’t tried this on Android Tablets and neither I have access to one so that I can test on it. I had tested this on mobiles (both iOS and Android) and just like you I got the desired results.

      1. Yeah, it was really weird. It worked fine on emulators, but when we test in TestCloud and on physical devices that we have here it doesn’t seem to work. We ended up having to remove it unfortunately.

Leave a Reply

Your email address will not be published. Required fields are marked *