是否可以将键盘上“return”键中的文字更改为“next”或“done”?我有一个包含用户名和密码的登录表单。我希望返回键在用户名字段上显示“下一步”,然后在密码字段上显示“完成”,但无论如何都没有看到这样做。 这是一个共享项目,Android和iOS。
答案 0 :(得分:25)
自定义EntryRenderer
可以处理更改键盘返回键说明。
iOS:UITextField
有一个ReturnKeyType
属性,您可以将其设置为预先分配的列表(请参阅UIReturnType
枚举)。
Android:EntryEditText
有一个ImeOptions
属性,用于控制" Action"键盘上的按钮和SetImeActionLabel
方法可用于为其设置任何文本字符串。
new EntryExt {
Text = "Next Key",
ReturnKeyType = ReturnKeyTypes.Next
},
new EntryExt {
Text = "Done Key",
ReturnKeyType = ReturnKeyTypes.Done
}
Xamarin.Forms
自定义Entry
类:namespace YourNameSpaceHere
{
public class EntryExt : Entry
{
public const string ReturnKeyPropertyName = "ReturnKeyType";
public EntryExt() { }
public static readonly BindableProperty ReturnKeyTypeProperty = BindableProperty.Create(
propertyName: ReturnKeyPropertyName,
returnType: typeof(ReturnKeyTypes),
declaringType: typeof(EntryExt),
defaultValue: ReturnKeyTypes.Done);
public ReturnKeyTypes ReturnKeyType
{
get { return (ReturnKeyTypes)GetValue(ReturnKeyTypeProperty); }
set { SetValue(ReturnKeyTypeProperty, value); }
}
}
// Not all of these are support on Android, consult EntryEditText.ImeOptions
public enum ReturnKeyTypes : int
{
Default,
Go,
Google,
Join,
Next,
Route,
Search,
Send,
Yahoo,
Done,
EmergencyCall,
Continue
}
}
EntryRenderer
:[assembly: ExportRenderer(typeof(Entry), typeof(EntryExtRenderer_iOS))]
namespace KeyboardDone.iOS
{
public class EntryExtRenderer_iOS : EntryRenderer
{
public EntryExtRenderer_iOS() { }
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if ((Control != null) && (e.NewElement != null))
Control.ReturnKeyType = (e.NewElement as EntryExt).ReturnKeyType.GetValueFromDescription();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == EntryExt.ReturnKeyPropertyName)
{
D.WriteLine($"{(sender as EntryExt).ReturnKeyType.ToString()}");
Control.ReturnKeyType = (sender as EntryExt).ReturnKeyType.GetValueFromDescription();
}
}
}
public static class EnumExtensions
{
public static UIReturnKeyType GetValueFromDescription(this ReturnKeyTypes value)
{
var type = typeof(UIReturnKeyType);
if (!type.IsEnum) throw new InvalidOperationException();
foreach (var field in type.GetFields())
{
var attribute = Attribute.GetCustomAttribute(field,
typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attribute != null)
{
if (attribute.Description == value.ToString())
return (UIReturnKeyType)field.GetValue(null);
}
else
{
if (field.Name == value.ToString())
return (UIReturnKeyType)field.GetValue(null);
}
}
throw new NotSupportedException($"Not supported on iOS: {value}");
}
}
}
EntryRenderer
:[assembly: ExportRenderer(typeof(Entry), typeof(EntryExtRenderer_Droid))]
namespace KeyboardDone.Droid
{
public class EntryExtRenderer_Droid : EntryRenderer
{
public EntryExtRenderer_Droid() { }
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if ((Control != null) && (e.NewElement != null))
{
var entryExt = (e.NewElement as EntryExt);
Control.ImeOptions = entryExt.ReturnKeyType.GetValueFromDescription();
// This is hackie ;-) / A Android-only bindable property should be added to the EntryExt class
Control.SetImeActionLabel(entryExt.ReturnKeyType.ToString(), Control.ImeOptions);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == EntryExt.ReturnKeyPropertyName)
{
var entryExt = (sender as EntryExt);
Control.ImeOptions = entryExt.ReturnKeyType.GetValueFromDescription();
// This is hackie ;-) / A Android-only bindable property should be added to the EntryExt class
Control.SetImeActionLabel(entryExt.ReturnKeyType.ToString(), Control.ImeOptions);
}
}
}
public static class EnumExtensions
{
public static ImeAction GetValueFromDescription(this ReturnKeyTypes value)
{
var type = typeof(ImeAction);
if (!type.IsEnum) throw new InvalidOperationException();
foreach (var field in type.GetFields())
{
var attribute = Attribute.GetCustomAttribute(field,
typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attribute != null)
{
if (attribute.Description == value.ToString())
return (ImeAction)field.GetValue(null);
}
else
{
if (field.Name == value.ToString())
return (ImeAction)field.GetValue(null);
}
}
throw new NotSupportedException($"Not supported on Android: {value}");
}
}
}
答案 1 :(得分:13)
这是另一种方法,但类似于SushiHangover的解决方案。它包括UWP支持:
PCL中的ReturnType.cs
public enum ReturnType
{
Go,
Next,
Done,
Send,
Search
}
PCL中的BaseEntry.cs
public class BaseEntry : Entry
{
// Need to overwrite default handler because we cant Invoke otherwise
public new event EventHandler Completed;
public static readonly BindableProperty ReturnTypeProperty = BindableProperty.Create(
nameof(ReturnType),
typeof(ReturnType),
typeof(BaseEntry),
ReturnType.Done,
BindingMode.OneWay
);
public ReturnType ReturnType
{
get { return (ReturnType)GetValue(ReturnTypeProperty); }
set { SetValue(ReturnTypeProperty, value); }
}
public void InvokeCompleted()
{
if (this.Completed != null)
this.Completed.Invoke(this, null);
}
}
适用于Android的BaseEntryRenderer.cs
public class BaseEntryRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
BaseEntry entry = (BaseEntry)this.Element;
if(this.Control != null)
{
if(entry != null)
{
SetReturnType(entry);
// Editor Action is called when the return button is pressed
Control.EditorAction += (object sender, TextView.EditorActionEventArgs args) =>
{
if (entry.ReturnType != ReturnType.Next)
entry.Unfocus();
// Call all the methods attached to base_entry event handler Completed
entry.InvokeCompleted();
};
}
}
}
private void SetReturnType(BaseEntry entry)
{
ReturnType type = entry.ReturnType;
switch (type)
{
case ReturnType.Go:
Control.ImeOptions = ImeAction.Go;
Control.SetImeActionLabel("Go", ImeAction.Go);
break;
case ReturnType.Next:
Control.ImeOptions = ImeAction.Next;
Control.SetImeActionLabel("Next", ImeAction.Next);
break;
case ReturnType.Send:
Control.ImeOptions = ImeAction.Send;
Control.SetImeActionLabel("Send", ImeAction.Send);
break;
case ReturnType.Search:
Control.ImeOptions = ImeAction.Search;
Control.SetImeActionLabel("Search", ImeAction.Search);
break;
default:
Control.ImeOptions = ImeAction.Done;
Control.SetImeActionLabel("Done", ImeAction.Done);
break;
}
}
}
适用于iOS的BaseEntryRenderer.cs
public class BaseEntryRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
BaseEntry entry = (BaseEntry)this.Element;
if (this.Control != null)
{
if(entry != null)
{
SetReturnType(entry);
Control.ShouldReturn += (UITextField tf) =>
{
entry.InvokeCompleted();
return true;
};
}
}
}
private void SetReturnType(BaseEntry entry)
{
ReturnType type = entry.ReturnType;
switch (type)
{
case ReturnType.Go:
Control.ReturnKeyType = UIReturnKeyType.Go;
break;
case ReturnType.Next:
Control.ReturnKeyType = UIReturnKeyType.Next;
break;
case ReturnType.Send:
Control.ReturnKeyType = UIReturnKeyType.Send;
break;
case ReturnType.Search:
Control.ReturnKeyType = UIReturnKeyType.Search;
break;
case ReturnType.Done:
Control.ReturnKeyType = UIReturnKeyType.Done;
break;
default:
Control.ReturnKeyType = UIReturnKeyType.Default;
break;
}
}
}
UWP BaseEntryRenderer.cs
public class BaseEntryRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
BaseEntry entry = (BaseEntry)this.Element;
if(this.Control != null)
{
if(entry != null)
{
this.Control.KeyDown += (object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs eventArgs) =>
{
if (eventArgs.Key == Windows.System.VirtualKey.Enter)
{
entry.InvokeCompleted();
// Make sure to set the Handled to true, otherwise the RoutedEvent might fire twice
eventArgs.Handled = true;
}
};
}
}
}
}
在UWP上似乎无法将返回键更改为next / done / ...您需要自己为所有自定义渲染器添加ExportRenderer
属性。
<强>用法强>
XAML文件
<renderer:BaseEntry x:Name="username" Text="Username" ReturnType="Next" />
<renderer:BaseEntry x:Name="password" Text ="Password" IsPassword="true" ReturnType="Done" />
代码隐藏文件:
this.username.Completed += (object sender, EventArgs e) => this.password.Focus();
基于此source。
答案 2 :(得分:3)
是的,最新的Xamarin表单直接允许ReturnType作为属性,只需在Xaml中添加ReturnType
<Entry x:Name="myEntry" ReturnType="Done"/>
答案 3 :(得分:2)
最新的Xamarin Forms包为Entry元素添加ReturnType属性。 单击“完成”按钮时,它还将执行命令。 现在支持“完成”,“下一步”,“搜索”,“继续”和“发送”的IMEAction类型。