Changement retour à être fait/suivant key in Xamarin Forms Shared Project
est-il possible de changer le texte de la touche 'Retour' du clavier pour 'next' ou 'done'? J'ai un formulaire de connexion avec nom d'utilisateur et mot de passe. Je veux que la touche de retour indique 'next' quand sur le champ username et ensuite 'done' quand sur le champ password mais n'ai pas vu de toute façon de faire cela. C'est pour un projet partagé, android et iOS.
3 réponses
personnalisé EntryRenderer
peut gérer de changer le clavier touche retour description.
iOS :
UITextField
a unReturnKeyType
propriété que vous pouvez définir pour un pré-attribuées liste (voir la sectionUIReturnType
enum).Android :
EntryEditText
a unImeOptions
propriété qui contrôle ce que le bouton "Action" du clavier fait et unSetImeActionLabel
méthode que vous pouvez utiliser pour définir une chaîne de texte pour il.
exemple D'utilisation de l'entrée personnalisée / EntryRenderer:
new EntryExt {
Text = "Next Key",
ReturnKeyType = ReturnKeyTypes.Next
},
new EntryExt {
Text = "Done Key",
ReturnKeyType = ReturnKeyTypes.Done
}
Xamarin.Forms
personnalisé Entry
catégorie:
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
}
}
iOS custom 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}");
}
}
}
Android custom 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}");
}
}
}
Voici une approche alternative, mais similaire à la solution de SushiHangover. Il inclut le support UWP:
ReturnType.cs en mode d'émulation PCL
public enum ReturnType
{
Go,
Next,
Done,
Send,
Search
}
BaseEntry.cs en mode d'émulation PCL
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);
}
}
BaseEntryRenderer.cs pour Android
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;
}
}
}
BaseEntryRenderer.cs pour iOS
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;
}
}
}
BaseEntryRenderer.cs for UWP
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;
}
};
}
}
}
}
On UWP it ne semble pas être possible de modifier la clé suivante/fait/... Vous devez ajouter ExportRenderer
les attributs de vous-même de tous les moteurs de rendu.
Utilisation
fichier XAML
<renderer:BaseEntry x:Name="username" Text="Username" ReturnType="Next" />
<renderer:BaseEntry x:Name="password" Text ="Password" IsPassword="true" ReturnType="Done" />
fichier Code-behind:
this.username.Completed += (object sender, EventArgs e) => this.password.Focus();
sur la Base de ce source.
le dernier paquet de formulaires Xamarin ajoute l'attribut ReturnType pour les éléments D'entrée. Il exécutera également une commande lorsque le bouton fait est cliqué. Les types IMEAction pour Done, Next, Search, Go et Send sont tous supportés maintenant.