Entry show and hide password

2020-07-09 06:38发布

问题:

I want an entry to have an icon before the placeholder, and a icon in the end of the entry, to show and hide the text in the entry, i had an entry with the show and hide icon using this tutorial: https://www.techierathore.com/2017/09/xamarin-forms-tip-implement-show-hide-password-using-effects/

But now I want to have icons before the entry too, I can do that with this tutorial: https://xamgirl.com/image-entry-in-xamarin-forms/

But if i add the effect of the first tutorial to the custom entry, only the and hide/show icon shows up.

Is possible to do what i want?

回答1:

You could use editText.SetCompoundDrawablesRelativeWithIntrinsicBounds() to add both icon.

SetCompoundDrawablesRelativeWithIntrinsicBounds takes four parameters for start, top, end, and bottom drawable. In the first tutorial, the hide/show icon is added to the end, you can change the first parameter from 0 to your drawable. There are three places need to modify.

For example:

public class ShowHidePassEffect : PlatformEffect
{
    protected override void OnAttached()
    {
        ConfigureControl();
    }

    protected override void OnDetached()
    {
    }

    private void ConfigureControl()
    {
        EditText editText = ((EditText)Control);
        editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(Resource.Drawable.Password, 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(Resource.Drawable.Password, 0, Resource.Drawable.ShowPass, 0);
                }
                else
                {
                    editText.TransformationMethod = null;
                    editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(Resource.Drawable.Password, 0, Resource.Drawable.HidePass, 0);
                }
                return true;
            }
        }
        return false;
    }
}

And the result is:



回答2:

You can use something like this (solution for Xamarin iOS):

txt.TextWithIcon(myIcon, Colors.Black, Colors.Blue, UIReturnKeyType.Next);

Who calls this method

public static UITextField TextWithIcon(this UITextField text,
            string icon, UIColor colorBorder, UIColor colorText,
            UIReturnKeyType returnkey)
{
    text.LeftView = null; 
    var myImg = Images.LoadImageView(icon, UIViewContentMode.Center);
    myImg.Frame = new CGRect(10, 7, myImg.Frame.Width, myImg.Frame.Height);
    myImg.SizeToFit();

    var view = new UIView(new CGRect(0, 0, widthScreen, 70));
    view.AddSubview(myImg);

    text.LeftView = view;
    text.LeftViewMode = UITextFieldViewMode.Always;
    text.colorText = textColor;
    text.Layer.BorderWidth = 1f;
    text.Layer.BorderColor = colorBorder.CGColor;

    text.AttributedPlaceholder = new Foundation.NSAttributedString("placeholder", null, Colors.Black);
    text.ReturnKeyType = returnkey;
    text.SecureTextEntry = false;
    return text;
}

Hope this helps



回答3:

I cant reply to comment directly as per stack-overflow weird rating. @Phil as per your comment about icon sizing below:

Works, but is possible to create method or something to change the size of the icons ? – Phill May 29 '18 at 9:22

To change the icon size you will need to implement a ScaledBitmap. Something like this:

public static BitmapDrawable GetDrawable(int resID)
     {
            var context = global::Android.App.Application.Context;
            var drawable = ContextCompat.GetDrawable(context, resID);
            var bitmap = ((BitmapDrawable)drawable).Bitmap;
            return new BitmapDrawable(Resources.System, Bitmap.CreateScaledBitmap(bitmap, 60, 60, true));
     }```

//And call like this:


textCtrl.SetCompoundDrawablesRelativeWithIntrinsicBounds(null, null, BitMapHelper.GetDrawable(Resource.Mipmap.eye), null);

You can tweak the scale value to your taste.

Thanks to Billy Liu for the great answer.



回答4:

Short and simple way is below

<AbsoluteLayout >
  <Entry Keyboard="Default" IsPassword="{Binding IsPasswordShow}" Placeholder="Password" ></Entry>
  <Image Margin="2" AbsoluteLayout.LayoutBounds="1,.5, 25, 100" AbsoluteLayout.LayoutFlags="PositionProportional" HeightRequest="30" WidthRequest="30" Source="{Binding ShowHideIcon}" >
    <Image.GestureRecognizers>
      <TapGestureRecognizer Command="{Binding ShowHideTapCommand}" NumberOfTapsRequired="1" />
    </Image.GestureRecognizers>
  </Image>
</AbsoluteLayout>

and C# code is in view Model:

public class LoginPasswordViewModel : BaseViewModel
    {
        public LoginPasswordViewModel()
        {

            ShowHideTapCommand = new Command(() =>
            {
                IsPasswordShow = !IsPasswordShow;
            });
        }

        private bool _isPasswordShow;
        public bool IsPasswordShow
        {
            get { return _isPasswordShow; }
            set
            {
                _isPasswordShow = value;
                OnPropertyChanged();
                OnPropertyChanged("ShowHideIcon");
            }
        }

        public string ShowHideIcon
        {
            get
            {
                return IsPasswordShow ? "show.png" : "hide.png";
            }
        }

        public ICommand LoginCommand { get; }
        public ICommand ShowHideTapCommand { get; }
    }