キーボードの「return」キーのテキストを「next」または「done」に変更することは可能ですか?ユーザー名とパスワードを含むログインフォームがあります。ユーザー名フィールドではリターンキーに「次へ」、パスワードフィールドでは「完了」と言って欲しいのですが、どうしてもこれをやったことがありません。これは、共有プロジェクト、AndroidおよびiOS用です。
カスタムEntryRenderer
は、キーボードのリターンキーの説明の変更を処理できます。
iOS:UITextField
には、preassignedリストに設定できるReturnKeyType
プロパティがあります(UIReturnType
enumを参照)。
Android:EntryEditText
には、キーボードの「アクション」ボタンの動作を制御するImeOptions
プロパティと、テキスト文字列を設定するために使用できる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}");
}
}
}
これは代替アプローチですが、SushiHangoverのソリューションに似ています。 UWPサポートが含まれています。
PCLのReturnType.cs
public enum ReturnType
{
Go,
Next,
Done,
Send,
Search
}
PCEntryの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 。
はい、最新のXamarin FormsはReturnTypeをプロパティとして直接使用できます。ReturnTypeをXamlに追加するだけです
<Entry x:Name="myEntry" ReturnType="Done"/>
最新のXamarin Formsパッケージは、Entry要素のReturnType属性を追加します。また、[完了]ボタンがクリックされたときにコマンドを実行します。 Done、Next、Search、Go、SendのIMEActionタイプがすべてサポートされるようになりました。