On my page, I'm using a picker that bound an ItemSource to 3 selectable items. When I select something from the list or cancel it, the focus stays on the picker and that allows me to type something.
Although this does not affect the value selected, it can be confusing to the user
Is there an easy way to prevent a user from entering data in this field?
Solution (or a work around) is disabling focus using a custom renderer:
internal class CustomPicker : PickerRenderer
{
public CustomPicker(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
EditText?.SetFocusable(ViewFocusability.NotFocusable);
}
}
I have done a sample to test and the picker's text will be changed if user tap the the physical keyboard, but the soft keyboard will not show.
If you don't want the picker accept the input from the user, you can use the coustom render just like Cfun said. You can just set the Focuseable property as false and then the picker will not accept the input from keyboard.
public class MyPickerRender : PickerRenderer
{
public MyPickerRender(Context context) : base(context)
{
}
protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
Control.Focusable = false;
}
}
Related
I have a custom Entry that takes text as input, I've noticed that if I go on the GIF keybord on my Xiaomi, when adding a GIF a Toast comes out saying "GIF are not supported in this text box" but it stills put the link to the GIF in the Entry. This does not happen in other phone but I still want to figure out why, or maybe a way to disable the GIF button.
When approacing to this problem I have tried different solution to disable the GIF keyboard such as this or this but they does not seems to work in my case.
Tried to implement this method like reported in the documentation but, in debug mode, it seems it does not even call it
public override IInputConnection OnCreateInputConnection(EditorInfo outAttrs)
{
IInputConnection ic = base.OnCreateInputConnection(outAttrs);
EditorInfoCompat.SetContentMimeTypes(outAttrs, new string[] { "image/*", "image/png", "image/gif", "image/jpeg" });
return InputConnectionCompat.CreateWrapper(ic, outAttrs, null);
}
Tried to add private ImeOptions but nothing
Control.PrivateImeOptions = "disableSticker=true;disableGifKeyboard=true";
Any idea ?
You could disable the emojis with custom renderer.
[assembly: ExportRenderer(typeof(Entry), typeof(MyEntryRenderer))]
namespace App10.Droid
{
public class MyEntryRenderer : EntryRenderer
{
public MyEntryRenderer(Android.Content.Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.ImeOptions = Android.Views.InputMethods.ImeAction.Done;
Control.InputType = Android.Text.InputTypes.ClassText | Android.Text.InputTypes.TextVariationVisiblePassword | Android.Text.InputTypes.TextFlagMultiLine;
Control.SetTypeface(Typeface.Default, TypefaceStyle.Normal);
}
}
}
}
I have a form with a few fields in my app in Xamarin.Forms. I need to provide text "Next" on the android soft keyboard
and on tap of "Next" it should take me to next field.
My Code in customRenderer:
Control.ImeOptions = Android.Views.InputMethods.ImeAction.Next;
Control.SetImeActionLabel("Next",Android.Views.InputMethods.ImeAction.Next);
This sets the text on the keypad to "Next", but it will not take me to the next field.
I also tried writing some code in the OnAppearing() of xaml.cs:
entryOne.Completed+= (object sender, EventArgs e) =>
{entryTwo.Focus(); };
Even this did not work.
Also the below code claims to show "Whatever" on the android soft keyboard button, but it shows the enum value of ImeAction, which in the below case will be "Next":
Control.SetImeActionLabel("Whatever",Android.Views.InputMethods.ImeAction.Next);
Xamarin.Forms Entryprovides this functionality, you can use property ReturnType to set keyboard and ReturnCommand to write code, which entry you want to focus on click of that.
In your xaml:
<Entry x:Name="txtUserName"
ReturnCommand="{Binding loginCompleted}"
ReturnType="Next"/>
<Entry x:Name="txtPassword"/>
In your view model:
public ICommand loginCompleted
{
get { return new Command(loginCompletedEvent); }
}
/// <summary>
/// Event for making the keyboard focus on password Entry
/// </summary>
private void loginCompletedEvent()
{
Entry entryPassword = m_view.FindByName<Entry>("txtPassword");
entryPassword.Focus();
}
Hope this will solve your issue.
I am writing a Xamarin Forms app (.net standard 2.0). Currently it is only being developed for Android but it may be released for other OSs in future. The scenario I am trying to manage is this:
The user goes into a ContentPage with a single Entry
I give the Entry focus by using native Android code in a custom renderer:
if (e.NewElement != null && e.NewElement is CustomEntry)
{
CustomEntry customEntry = (CustomEntry)e.NewElement;
if(customEntry.GiveFocus)
{
//this messes up the onback behaviour - you have to press onback twice to exit the screen, once to get out of the hidden SIP
Control.RequestFocus();
}
}
I do not want the soft keyboard to pop up automatically. Therefore I have added the below line to the OnCreate of the MainActivity:
Window.SetSoftInputMode(SoftInput.StateAlwaysHidden);
The reason I am requesting focus in the custom renderer and not in the Xamarin Forms Entry is I could see the keyboard popup and then immediately disappear when I requested it in the Xamarin Forms control. I don't want the keyboard to appear as this app will be primarily used by users of industrial devices with a hardware keyboard, but the entry will need to have focus as the users will want to enter text into it straight away.
My problem is the user has to press the back button twice to exit the ContentPage in this scenario. Once to get out of the hidden keyboard (and the Entry loses focus) and then again to exit the page. I want to avoid this - they should be able to exit the page with only one click when the keyboard is hidden. Does anyone know how to resolve this? I have tried overriding OnKeyPreIme in the custom renderer as other answers have suggested but it doesn't appear to detect the back click.
You can use Hide Keyboard method when your entry get focused. It might solved your problem.
public interface IKeyboardHelper
{
void HideKeyboard();
}
For Android use :
public class DroidKeyboardHelper : IKeyboardHelper
{
public void HideKeyboard()
{
var context = Forms.Context;
var inputMethodManager = context.GetSystemService(Context.InputMethodService) as InputMethodManager;
if (inputMethodManager != null && context is Activity)
{
var activity = context as Activity;
var token = activity.CurrentFocus?.WindowToken;
inputMethodManager.HideSoftInputFromWindow(token, HideSoftInputFlags.None);
activity.Window.DecorView.ClearFocus();
}
}
}
For iOS :
public class iOSKeyboardHelper : IKeyboardHelper
{
public void HideKeyboard()
{
UIApplication.SharedApplication.KeyWindow.EndEditing(true);
}
}
Use Dependency Injection and call this method while your entry get focused.
Try to use below method for handling back button pressed event.
protected override bool OnBackButtonPressed()
{
// you can handle back button pressed event in Xamarin forms page
return base.OnBackButtonPressed();
}
I've (finally) worked it out. The key is not to override OnKeyPreIME but DispatchKeyEventPreIme instead. This allows you to intercept the 'Back' press. So, in my CustomRenderer I added this method:
public override bool DispatchKeyEventPreIme(KeyEvent e)
{
//if this is back press and the sip is not visible then we need to call the 'OnBack' method at the view model level
if(!SIPVisibleListener.IsSIPVisible && e.KeyCode == Keycode.Back)
{
if(XamarinFormsControl != null && XamarinFormsControl is IOnBackHandler)
{
((IOnBackHandler)XamarinFormsControl).GoBack();
}
}
return base.DispatchKeyEventPreIme(e);
}
IOnBackHandler is an interface I created to handle the back key press. SIPVisibleListener is based on an answer to this question: How do I Detect if Software Keyboard is Visible on Android Device?
Hopefully this will help someone.
I have an Entry and a Button:
<StackLayout>
<CustomViews:ChatEntryView x:Name="ChatEntry" />
<Button Text="Send" Command="SendCommand"/>
</StackLayout>
What I wanted to achieve here is that when the user starts types something on the Entry control and then presses the button, it should not hide the keyboard (or lose the Entry Focus).
The ChatEntryView here is just actually a custom view that inherits from the Entry control and what I did inside:
1.) Added an Unfocused handler
Unfocused += ChatEntryView_Unfocused;
void ChatEntryView_Unfocused(object sender, FocusEventArgs e)
{
this.Focus();
}
2.) Tried Handling on PropertyChanged
protected override void OnPropertyChanged(string propertyName = null)
{
this.Focus();
base.OnPropertyChanged(propertyName);
}
3.) Tried Handling on PropertyChanging
protected override void OnPropertyChanging(string propertyName = null)
{
this.Focus();
base.OnPropertyChanging(propertyName);
}
But all the three methods doesn't seem to work. I was able to do a work around on IOS by making a custom renderer and it's not very neat (by actually interfacing to the Control.ShouldEndEditing on IOS).
But my problem now is on Android, as I don't exactly know how to do this on Android and there's no Control.ShouldEndEditing (the interface on Android) that I can work with.
What happens by using the handlers above is that, the keyboard for the entry view still loses focus and then immediately gets focuses again which is very odd.
The keyboard pushes down (loses focus) and then pushes up (forced focus).
I know it's too late to anwser this question, but it might be helpful for someone else, I added this code to MainActivity, it might not be a neat solution, but works for me:
private bool _lieAboutCurrentFocus;
public override bool DispatchTouchEvent(MotionEvent ev)
{
var focused = CurrentFocus;
bool customEntryRendererFocused = focused != null && focused.Parent is CustomEntryRenderer_Droid;
_lieAboutCurrentFocus = customEntryRendererFocused;
var result = base.DispatchTouchEvent(ev);
_lieAboutCurrentFocus = false;
return result;
}
public override View CurrentFocus
{
get
{
if (_lieAboutCurrentFocus)
{
return null;
}
return base.CurrentFocus;
}
}
In a Xamarin Forms app, I am trying to create a custom Entry implementation that does not automatically display the soft keyboard when it is focused. The goal is to use one instance of this entry alongside other conventional entries on a page.
I am familiar with the recommended Xamarin Forms pattern for custom view rendering, and have successfully created both the Entry and its renderer, as follows:
public class BlindEntry : Entry
{
}
[assembly: ExportRenderer(typeof(BlindEntry), typeof(BlindEntryRenderer))]
public class BlindEntryRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.FocusChange += Control_FocusChange;
}
}
private void Control_FocusChange(object sender, FocusChangeEventArgs e)
{
if (e.HasFocus)
{
// What goes here?
}
else
{
// What goes here?
}
}
}
To show and hide the soft keyboard, I imagine one of the recommendations from this question will provide the solution, but there are many different opinions on which is the best approach. Also, even after choosing a suitable pattern, I am not clear how to access the required native Android APIs from within the above custom renderer.
For example, I know that I can obtain a reference to an InputMethodManager using the following call (from within an Activity), but it is not obvious how to reference the containing activity from inside the renderer:
var imm = GetSystemService(InputMethodService)
Thanks, in advance, for your suggestions.
Tim
Try this instead inside OnElementChanged():
Control.InputType = Android.Text.InputTypes.Null;
This will prevent the keyboard from appearing when selecting the Entry without having to check its focus.
=== Edit ===
Turns out there is actually the ShowSoftInputOnFocus property available for doing exactly this.
Control.ShowSoftInputOnFocus = false;