如何解决使用退格按钮专注于 Xamarin 中的上一个输入字段
在我的 Xamarin 应用程序的 PIN 页面上,有 8 个输入字段,4 个用于 PIN,4 个用于确认 PIN(这里我只粘贴 2 个)。
当用户在一个字段中输入一个值时,光标会聚焦在下一个字段上,依此类推。但是如果他们错误地输入了值并想要清除它,他们不能通过按退格按钮返回到最后一个条目。他们必须按下那个输入字段才能获得焦点。
以下是输入字段的代码。如何通过按 Backspace 按钮返回/关注最后一个输入字段?
.xml
<Entry
x:Name="PasswordOne"
Text="{Binding PasswordOne}"
IsPassword="True"
Keyboard="Numeric"
MaxLength="1"
ReturnType="Next"
TextChanged="Entry_FieldChanged" />
.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();
}
}
}
更新
CustomEntry.xml.cs
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);
}
}
}
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);
}
}
}
.xml.cs
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;
}
}
}
.xml
<local:CustomEntry
x:Name="PasswordOne"
IsPassword="True"
Keyboard="Numeric"
MaxLength="1"
ReturnType="Next"
TextChanged="Entry_FieldChanged"
OnBackspace="CustomEntry_OnBackspace"
Unfocused="Password_Unfocused" />
解决方法
如果您想在按下 Backspace
按钮时聚焦到最后一个条目,可以使用自定义渲染器。
自定义条目:
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 });
}
}
}
XML:
<local:CustomEntry
x:Name="PasswordOne"
IsPassword="True"
Keyboard="Numeric"
MaxLength="1"
OnBackspace="CustomEntry_OnBackspace"
ReturnType="Next"
Text="{Binding PasswordOne}"
TextChanged="Entry_FieldChanged" />
<local:CustomEntry
x:Name="PasswordTwo"
IsPassword="True"
Keyboard="Numeric"
MaxLength="1"
OnBackspace="CustomEntry_OnBackspace"
ReturnType="Next"
Text="{Binding PasswordTwo}"
TextChanged="Entry_FieldChanged" />
<local:CustomEntry
x:Name="ConfirmPasswordOne"
IsPassword="True"
Keyboard="Numeric"
MaxLength="1"
OnBackspace="CustomEntry_OnBackspace"
ReturnType="Next"
Text="{Binding ConfirmPasswordOne}"
TextChanged="Entry_FieldChanged" />
<local:CustomEntry
x:Name="ConfirmPasswordTwo"
IsPassword="True"
Keyboard="Numeric"
MaxLength="1"
OnBackspace="CustomEntry_OnBackspace"
ReturnType="Done"
Text="{Binding ConfirmPasswordTwo}"
TextChanged="Entry_FieldChanged" />
背后的代码:
public List<Entry> entryList { get; set; }
public Page3()
{
InitializeComponent();
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;
}
}
请注意,我们需要注释 Entry_FieldChanged
的 else 部分。
更新:
在 .xml.cs 页面上,我不能使用 Entry 作为基类。它返回一个错误。目前,我正在使用 ContentPage
创建一个新类,不要直接使用 Entry 作为 ContentPage 的基类。
如果您仍然有错误,请提供错误信息。
对于 local:Entry,我添加了 xmlns:local="http://xamarin.com/schemas/2014/forms" 作为参考,对吗?
不,local 是 CustomEntry
的位置。对我来说,CustomEntry
位于名为 Test 的 Xamarin.forms 项目中。
xmlns:local="clr-namespace:Test"
我的项目中已经有一个 Entry Custom Renderer(下面是代码)。 OnBackspacePressed();说 Entry 不包含 OnBackspacePressed() 的定义。
您是否先创建自定义条目?我在 CustomEntry 控件中定义了 OnBackspacePressed
。
无需点击/触摸/点击条目编号。 2,如果您从任何条目单击退格按钮,您只需返回上一个条目,无需在任何条目上手动点击/点击/触摸
private void CustomEntry_OnBackspace(object sender,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;
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。