I haven't written on the blog for a while and I can't say it's due to lack of time, but simply due to lack of its organization.
This article is about mobile programming, using Xamarin with Visual Studio 2019, because it is cross-platform: to a large extent, we write the code only once for all mobile operating systems (we will focus on iOS and Android).
I say to a large extent because there are certain parts that need to be written separately for each OS.
We will write the code that allows us to see what we have typed in a password-type textbox.
First, we create a new project -> MyProject. This will eventually have 3 projects: MyProject, MyProject.Android, and MyProject.iOS.
Then we will create a new folder (Effects) in all 3 projects of our solution. In each of the 3 folders, we will create a new class named ShowHidePassEffects.
We start with the class in the MyProject project. It will have the following content:
using Xamarin.Forms;
namespace MyProject.Effects
{
public class ShowHidePassEffect : RoutingEffect
{
public string EntryText { get; set; }
public ShowHidePassEffect() : base("Xamarin.ShowHidePassEffect") { }
}
}
The class in the MyProject.Android project will have a larger content:
using Android.Text.Method;
using Android.Views;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(MyProject.Droid.Effects.ShowHidePassEffect), "ShowHidePassEffect")]
namespace MyProject.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.HidePass, 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.HidePass, 0);
editText.SetSelection(editText.Length());
}
else
{
editText.TransformationMethod = null;
editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, Resource.Drawable.ShowPass, 0);
editText.SetSelection(editText.Length());
}
return true;
}
}
return false;
}
}
}
Finally, the class in the MyProject.iOS project:
using System;
using MyProject.iOS.Effects;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(ShowHidePassEffect), "ShowHidePassEffect")]
namespace MyProject.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("HidePass"), UIControlState.Normal);
buttonRect.TouchUpInside += (object sender, EventArgs e1) =>
{
if (vUpdatedEntry.SecureTextEntry)
{
vUpdatedEntry.SecureTextEntry = false;
buttonRect.SetImage(new UIImage("ShowPass"), UIControlState.Normal);
}
else
{
vUpdatedEntry.SecureTextEntry = true;
buttonRect.SetImage(new UIImage("HidePass"), UIControlState.Normal);
}