How to display custom password character with some delay like EditText control using Java.Util.Timer

EswaranEswaran INMember ✭✭

I have created a custom control by inheriting the EditText control. My requirements are to display the custom password character and when typing there should be some delay like EditText when setting the input type. I have achieved the custom password character displaying but I am unable to achieve the second requirement. I tried to achieve the second requirement by using Java.Util.Timer. I have attached the sample in the below link: https://github.com/Eswaran17392/CustomSamples/blob/master/CustomEditboxTimer.zip. Anyone, please suggest me how to achieve the delay similar to EditText using Timer or any possible solutions. For applying delay, I used below code snippet:

    if(ShowPasswordDelay)
                    {
                        if (timer != null)
                        {
                            timer.Cancel();
                            timer.Dispose();
                            timer = null;

                            this.Text = value;
                        }

                        timer = new Timer();
                        MyTask = new MyTask(timer, this, value);
                        timer.Schedule(MyTask, 1000);

                    }
                    else
                    {
                        this.Text = value;
                    }

internal class MyTask : TimerTask
    {
        private Timer timer;
        private CustomEditboxcontrol Edittext;
        string text;

        public MyTask(Timer timer, CustomEditboxcontrol edittext, string value)
        {
            this.timer = timer;
            Edittext = edittext;
            text = value;
        }

        public override void Run()
        {
            Edittext.Text=text;
        }
    }

When typing a single character I faced some issue like the below-attached image:

Answers

  • LeonLuLeonLu Member, Xamarin Team Xamurai

    If you use Java.Util.Timer, it will create a thread, If you update the UI in thread, not in the main UI thread, you will get this exception.

    I add follow line when you want to update your thread.

     context.RunOnUiThread(() =>
            {
                Edittext.Text = text;
    
            });
    

    Here is CustomEditboxcontrol

         class CustomEditboxcontrol : EditText
    {
        private char passwordChar;
        string data = string.Empty;
        string typedString = string.Empty;
        private string displayString;
        MainActivity context;
        private bool isBackPressed;
        private bool showPasswordDelay;
        private Handler handler;
        Timer timer;
        MyTask MyTask;
        internal string DisplayString
        {
            get
            {
                return this.displayString;
            }
            set
            {
                this.displayString = value;
                if(ShowPasswordDelay)
                {
                    if (timer != null)
                    {
                        timer.Cancel();
                        timer.Dispose();
                        timer = null;
                        context.RunOnUiThread(() =>
                        {
    
                            this.Text = value;
                        }
    
                        );
    
    
    
                    }
    
                    timer = new Timer();
                    MyTask = new MyTask(timer, this, value, context);
                    timer.Schedule(MyTask, 1000);
                   // Task.Delay(100);
                }
                else
                {
                    context.RunOnUiThread(() =>
                    {
    
                        this.Text = value;
                    }
    
                      );
                }
            }
        }
        public bool ShowPasswordDelay
        {
            get
            {
                return this.showPasswordDelay;
            }
            set
            {
                this.showPasswordDelay = value;
            }
        }
    
        public char PasswordChar
        {
            get
            {
                return this.passwordChar;
            }
    
            set
            {
                this.passwordChar = value;
            }
        }
    
        public CustomEditboxcontrol(MainActivity context): base(context)
        {
            this.context = context;
            this.OnLoading();
        }
    
        private void OnLoading()
        {
            this.TextChanged += CustomEditboxcontrol_TextChanged;
        }
    
        private void CustomEditboxcontrol_TextChanged(object sender, Android.Text.TextChangedEventArgs e)
        {
            typedString += e.Text.ToString();
            if (showPasswordDelay)
            {
                ChangeToPasswordChar(typedString);
            }
            else
            {
                ChangeToPasswordChar(typedString);
            }
        }
    
        private void ChangeToPasswordChar(string typedString)
        {
            data = string.Empty;
            for (int i = 0; i < typedString.Length; i++)
            {
                data += this.PasswordChar;
            }
            this.DisplayString = data;
        }
    }
    
    internal class MyTask : TimerTask
    {
        private Timer timer;
        private CustomEditboxcontrol Edittext;
        string text;
        MainActivity context;
        public MyTask(Timer timer, CustomEditboxcontrol edittext, string value,MainActivity context)
        {
            this.timer = timer;
            Edittext = edittext;
            text = value;
            this.context = context;
        }
    
        public override void Run()
        {
            context.RunOnUiThread(() =>
            {
                Edittext.Text = text;
    
            });
    
        }
    }
    
  • EswaranEswaran INMember ✭✭

    Hi @LeonLu ,

    How to cancel the scheduled timer or how to stop the action which is scheduled?

  • LeonLuLeonLu Member, Xamarin Team Xamurai
    edited August 9

    @Eswaran timer.Cancel();will cancle the timer, but in your code, this this.TextChanged +=CustomEditboxcontrol_TextChanged; this line, when you change the text, it will run many times. If you still want to achieve the delay result. you can add a AddTextChangedListener, then achieve the ITextWatcher interface like this code.

    editText1.AddTextChangedListener(new mytextWater());

      class mytextWater : Java.Lang.Object,ITextWatcher
        {
          //  public IntPtr Handle => null;
            Timer timer;
            public void AfterTextChanged(IEditable s)
            {
                Thread.Sleep(1000);
    
            }
    
            public void BeforeTextChanged(ICharSequence s, int start, int count, int after)
            {
    
            }
    
    
    
            public void OnTextChanged(ICharSequence s, int start, int before, int count)
            {
    
            }
        }
    

    Here is running GIF.

  • EswaranEswaran INMember ✭✭

    Hi @LeonLu ,

    Sorry for the delay. Using "Thread.Sleep" after the text changed, makes my custom control to wait for each second after typing as well as the typed character is not displayed while typing. So I cannot use the above solution in my case.

  • LeonLuLeonLu Member, Xamarin Team Xamurai

    I change the code like following CustomEditboxcontrol_TextChanged, it will not execute at many times.

    private void CustomEditboxcontrol_TextChanged(object sender, Android.Text.TextChangedEventArgs e)
    {
    // typedString += ;

            if (showPasswordDelay)
            {
    
                ChangeToPasswordChar(e.Text.ToString());
               //await Task.Delay(100);
            }
            else
            {
                ChangeToPasswordChar(e.Text.ToString());
            }
        }
    

    But still have issue. I did not know following code, if the timer!=null, why need execute following code.

     if(ShowPasswordDelay)
                    {
                        if (timer != null)
                        {
                            timer.Cancel();
                            timer.Dispose();
                            timer = null;
    
                            this.Text = value;
                        }
    
                        timer = new Timer();
                        MyTask = new MyTask(timer, this, value);
                        timer.Schedule(MyTask, 1000);
    
                    }
                    else
                    {
                        this.Text = value;
                    }
    
Sign In or Register to comment.