C# 使用Backspace按钮将焦点放在Xamarin中的上一个输入字段上

C# 使用Backspace按钮将焦点放在Xamarin中的上一个输入字段上,c#,.net,xamarin,xamarin.forms,C#,.net,Xamarin,Xamarin.forms,在我的Xamarin应用程序的PIN页面上,有8个输入字段,4个用于PIN,4个用于确认PIN(这里我只粘贴了2个) 当用户在一个字段中输入值时,光标会聚焦在下一个字段上,依此类推。但如果他们错误地输入了值并想清除它,他们就不能通过按Backspace按钮返回到上一个条目。他们必须按那个输入字段才能聚焦 下面是输入字段的代码。如何通过按Backspace按钮返回/聚焦最后一个输入字段 .xml <Entry x:Name="PasswordOne" Te

在我的Xamarin应用程序的PIN页面上,有8个输入字段,4个用于PIN,4个用于确认PIN(这里我只粘贴了2个)

当用户在一个字段中输入值时,光标会聚焦在下一个字段上,依此类推。但如果他们错误地输入了值并想清除它,他们就不能通过按Backspace按钮返回到上一个条目。他们必须按那个输入字段才能聚焦

下面是输入字段的代码。如何通过按Backspace按钮返回/聚焦最后一个输入字段

.xml

<Entry
    x:Name="PasswordOne"
    Text="{Binding PasswordOne}"
    IsPassword="True"
    Keyboard="Numeric"
    MaxLength="1"
    ReturnType="Next"
    TextChanged="Entry_FieldChanged" />
<local:CustomEntry
    x:Name="PasswordOne"
    IsPassword="True"
    Keyboard="Numeric"
    MaxLength="1"
    ReturnType="Next"
    TextChanged="Entry_FieldChanged"
    OnBackspace="CustomEntry_OnBackspace"
    Unfocused="Password_Unfocused" />
CustomEntryRenderer

[assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntryRenderer))]
namespace Mobile.App.Droid
{
    public class CustomEntryRenderer : EntryRenderer, IInputFilter
    {
        public CustomEntryRenderer(Context context) : base(context)
        {
        }

        public ICharSequence FilterFormatted(ICharSequence source, int start, int end, ISpanned dest, int dstart, int dend)
        {
            if (string.IsNullOrWhiteSpace(source.ToString()))
            {
                var entry = (CustomEntry)Element;
                entry.OnBackspacePressed();
            }
            return source;
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
            {
                return;
            }

            if (Control != null)
            {
                int length = Control.Text.Length;
                Control.SetSelection(length);
                SetColors();
            };

            Control.SetFilters(new IInputFilter[] { this });
        }

        private void SetColors()
        {
            Control.SetBackgroundColor(Android.Graphics.Color.Transparent);
        }
    }
}
[程序集:ExportRenderer(typeof(CustomEntry)、typeof(CustomEntryRenderer))]
命名空间Mobile.App.Droid
{
公共类CustomEntryRenderer:EntryRenderer,IIInputFilter
{
公共CustomEntryRenderer(上下文):基本(上下文)
{
}
公共ICharSequence FilterPerformatted(ICharSequence源、int开始、int结束、ISpanned结束、int开始、int结束)
{
if(string.IsNullOrWhiteSpace(source.ToString()))
{
var条目=(CustomEntry)元素;
entry.OnBackspacePressed();
}
返回源;
}
受保护的覆盖无效OnElementChanged(ElementChangedEventArgs e)
{
基础。一个要素发生变化(e);
if(Control==null)
{
返回;
}
if(控件!=null)
{
int length=Control.Text.length;
控制。设置选择(长度);
设置颜色();
};
Control.SetFilters(新的IIInputFilter[]{this});
}
私有void SetColors()
{
SetBackgroundColor(Android.Graphics.Color.Transparent);
}
}
}
.xml.cs

public PasswordPage()
{
    InitializeComponent();

    entryList = new List<Entry>();
    entryList.Add(PasswordOne);
    entryList.Add(PasswordTwo);

    entryList.Add(ConfirmPasswordOne);
    entryList.Add(ConfirmPasswordTwo);
}

private void Entry_FieldChanged(object sender, TextChangedEventArgs e)
{
    var entry = sender as Entry;

    const string numregex = "^[0-9]+$";

    if (!(!System.Text.RegularExpressions.Regex.IsMatch(entry.Text, numregex) || entry.Text == ""))
    {
        if (entry.Text.Length >= 1)
        {
            var index = entryList.IndexOf(entry);
            var nextIndex = (index + 1) >= entryList.Count ? 0 : index + 1;
            var next = entryList.ElementAt(nextIndex);
            if (entry == ConfirmPasswordTwo)
            { }
            else
            {
                next?.Focus();
            }
        }
    }
    else
    {
        var index = entryList.IndexOf(entry);
        var prevIndex = (index) == 0 ? 0 : index - 1;
        var prev = entryList.ElementAt(prevIndex);
        if (entry == PasswordOne)
        { }
        else
        {
            prev?.Focus();
        }
    }
}
namespace Mobile.App
{
    public class CustomEntry : Entry
    {

        public delegate void BackspaceEventHandler(object sender, EventArgs e);

        public event BackspaceEventHandler OnBackspace;
        public CustomEntry() { }

        public void OnBackspacePressed()
        {
            OnBackspace?.Invoke(null, null);
        }

    }
}
public partial class PasswordPage : ContentPage
{

    public List<Entry> entryList { get; set; }

    public PasswordPage()
    {
        InitializeComponent();
        ValidatePassword();

        entryList = new List<Entry>();
        entryList.Add(PasswordOne);
        entryList.Add(PasswordTwo);

        entryList.Add(ConfirmPasswordOne);
        entryList.Add(ConfirmPasswordTwo);
    }

    Entry entry;
    private void Entry_FieldChanged(object sender, TextChangedEventArgs e)
    {
        entry = sender as Entry;

        const string numregex = "^[0-9]+$";

        if (!(!System.Text.RegularExpressions.Regex.IsMatch(entry.Text, numregex) || entry.Text == ""))
        {
            if (entry.Text.Length >= 1)
            {
                var index = entryList.IndexOf(entry);
                var nextIndex = (index + 1) >= entryList.Count ? 0 : index + 1;
                var next = entryList.ElementAt(nextIndex);
                if (entry == ConfirmPasswordTwo)
                { }
                else
                {
                    next?.Focus();
                }
            }
        }
        //else
        //{
        //    var index = entryList.IndexOf(entry);
        //    var prevIndex = (index) == 0 ? 0 : index - 1;
        //    var prev = entryList.ElementAt(prevIndex);
        //    if (entry == PasswordOne)
        //    { }
        //    else
        //    {
        //        prev?.Focus();
        //    }
        //}
    }

    private void CustomEntry_OnBackspace(object sender, EventArgs e)
    {
        const string numregex = "^[0-9]+$";

        if (!(System.Text.RegularExpressions.Regex.IsMatch(entry.Text, numregex) || entry.Text == ""))
        {
            var last = entryList.ElementAt(entryList.Count - 1);
            last?.Focus();
        }
        else
        {
            return;
        }
    }
}
public部分类密码页:ContentPage
{
公共列表条目列表{get;set;}
公共密码页()
{
初始化组件();
验证密码();
entryList=新列表();
entryList.Add(PasswordOne);
entryList.Add(密码2);
entryList.Add(ConfirmPasswordOne);
entryList.Add(confirmPassword2);
}
入境;
私有无效条目\u字段已更改(对象发送方,textchangedventargs e)
{
条目=发送方作为条目;
常量字符串numregex=“^[0-9]+$”;
if(!(!System.Text.RegularExpressions.Regex.IsMatch(entry.Text,numregex)| | entry.Text==“”)
{
如果(entry.Text.Length>=1)
{
var指数=entryList.IndexOf(条目);
var nextIndex=(索引+1)>=entryList.Count?0:索引+1;
var next=entryList.ElementAt(nextIndex);
if(条目==ConfirmPasswordTwo)
{ }
其他的
{
下一步?.Focus();
}
}
}
//否则
//{
//var指数=entryList.IndexOf(条目);
//var prevIndex=(指数)==0?0:指数-1;
//var prev=entryList.ElementAt(prevIndex);
//if(entry==PasswordOne)
//    { }
//否则
//    {
//prev?.Focus();
//    }
//}
}
私有void CustomEntry\u OnBackspace(对象发送方,事件参数e)
{
常量字符串numregex=“^[0-9]+$”;
if(!(System.Text.RegularExpressions.Regex.IsMatch(entry.Text,numregex)| | entry.Text==“”)
{
var last=entryList.ElementAt(entryList.Count-1);
最后一个?.Focus();
}
其他的
{
返回;
}
}
}
.xml

<Entry
    x:Name="PasswordOne"
    Text="{Binding PasswordOne}"
    IsPassword="True"
    Keyboard="Numeric"
    MaxLength="1"
    ReturnType="Next"
    TextChanged="Entry_FieldChanged" />
<local:CustomEntry
    x:Name="PasswordOne"
    IsPassword="True"
    Keyboard="Numeric"
    MaxLength="1"
    ReturnType="Next"
    TextChanged="Entry_FieldChanged"
    OnBackspace="CustomEntry_OnBackspace"
    Unfocused="Password_Unfocused" />

如果要在按下
退格按钮时聚焦到最后一个条目,可以使用自定义渲染器

自定义条目:

 public class CustomEntry : Entry
{
     
    public delegate void BackspaceEventHandler(object sender, EventArgs e);
   
    public event BackspaceEventHandler OnBackspace;
    public CustomEntry() { }

    public void OnBackspacePressed()
    {
        OnBackspace?.Invoke(null, null);
    }

}
自定义渲染器:

[assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntryRenderer))]
namespace Test.Droid
{
public class CustomEntryRenderer : EntryRenderer, Android.Text.IInputFilter
{
    public CustomEntryRenderer(Context context) : base(context)
    {
    }

    public ICharSequence FilterFormatted(ICharSequence source, int start, int end, ISpanned dest, int dstart, int dend)
    {
        if (string.IsNullOrWhiteSpace(source.ToString()))
        {
            var entry = (CustomEntry)Element;
            entry.OnBackspacePressed();
        }
        return source;
    }

    protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
    {
        base.OnElementChanged(e);

        if (Control == null)
        {
            return;
        }

        Control.SetFilters(new IInputFilter[] { this });

    }

    

}
}
我的项目中已经有一个自定义渲染器条目(下面是代码)。OnBackspacePressed();表示条目不包含OnBackspacePressed()的定义

是否先创建自定义条目?我在我的CustomEntry控件中定义
OnBackspacePressed

在不点击/触摸/点击条目2的情况下,如果您在任何条目上点击退格按钮,您只需返回到上一条条目,再次不点击/点击/点击任何条目


你的退格按钮是什么?在键盘上?当你按下这个按钮时,你想关注最后一个吗?是的,是的,是的谢谢,我遇到了一些问题,我在上面的更新部分发布了它们。我已经更新了我的回复。请检查。我按照你说的更新了代码,没有错误,但是退格无效。。我在上面发布了我的更新代码。。请看一看……哦,对不起。我忘了在
CustomEntry\u OnBackspace
中更改代码。请检查一下。现在可以了。这是截图。谢谢,退格有效。。。我想我不清楚,我很抱歉。。我的意思是,如果你输入了错误的PIN,你只需按backspace按钮,你就会返回到上一个(不是上一个条目,而是上一个条目),你可以删除它。。
 xmlns:local="clr-namespace:Test"
 private void CustomEntry_OnBackspace(object sender, EventArgs e)
    {
        const string numregex = "^[0-9]+$";

        if (!(!System.Text.RegularExpressions.Regex.IsMatch(entry.Text, numregex) || entry.Text == ""))
        {
            //var last = entryList.ElementAt(entryList.Count - 1);
            //last?.Focus();
            var index = entryList.IndexOf(entry);
            var pre = entryList.ElementAt(index - 1);
            pre?.Focus();
        }
        else
        {
            return;
        }
    }