I have a webview based app in which i want the appropriate keypad to open whenever i give focus to some input. With the code i have provided below it opens up but it always opens qwerty keypad even for numeric type inputs.
private void ShowKeyboard(final boolean show) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (show) {
InputMethodManager mgr = (InputMethodManager) General.MainShellReference.getSystemService(Context.INPUT_METHOD_SERVICE);
mgr.showSoftInput(General.appView, InputMethodManager.SHOW_IMPLICIT);
((InputMethodManager) General.MainShellReference.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(General.appView, 0);
} else {
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
}
}
});
} catch (Exception ex) {
;
}
}
I think you have already tried to use <input type="number" /> and <input type="tel" />. Anyway try to do this.
Did you see this: Is there a way to have a masked numeric input field?
http://blog.pamelafox.org/2012/05/triggering-numeric-keyboards-with-html5.html
Related
I'm currently using Oppo F7 to test my app that I made using Android Studio. However, when I tested it and I clicked on a textbox (or EditText), the keyboard doesn't show/pop-up. Helpppp..
Note:
- My Oppo F7 is running on Android 8.1.0 (API 27)
- It works on the emulator on my laptop but it's far to laggy for me to test
use like this
public static void showSoftKeyboard(final Context context, final EditText editText) {
try {
editText.requestFocus();
editText.postDelayed(
new Runnable() {
#Override
public void run() {
InputMethodManager keyboard = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
keyboard.showSoftInput(editText, 0);
}
}
, 200);
} catch (NullPointerException npe) {
npe.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
in your activity call on text click
showSoftKeyboard(this, yourEditTextToFocus);
I have a custom entry field that prevents the soft keyboard from appearing when the entry field get focus. However this prevents the normal focus/unfocus events from occurring. Here is the code for the Android renderer
Control.FocusChange += (sender, eh) =>
{
new Handler().Post(delegate
{
if (eh.HasFocus)
if (Control != null)
{
var imm =
(InputMethodManager)Control.Context.GetSystemService(Android.Content.Context.InputMethodService);
imm.HideSoftInputFromWindow(Control.WindowToken, 0);
}
});
};
Is this a bug in Xamarin or is there a way to have the focus and unfocus events fire.
I had the same problem when trying to hide an already opened soft keyboard when focusing a DatePicker or TimePicker. (In some Android phones the soft keyboard stayed on top of the date/time picker dialogs).
When using Control.FocusChange event handler, the default behaviour of opening the picker dialogs was not being triggered.
Solution:
After hiding the keyboard, call the Focus() method on the element to trigger the normal focus events and default behaviour.
Here is my Android DatePicker renderer code:
protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
{
base.OnElementChanged(e);
if (Control == null)
{
return;
}
Control.ShowSoftInputOnFocus = false;
Control.FocusChange += (sender, args) => HideSoftKeyboard(e.NewElement, args);
}
private void HideSoftKeyboard(DatePicker e, FocusChangeEventArgs args)
{
if (args.HasFocus)
{
Device.BeginInvokeOnMainThread(() =>
{
var inputMethodManager = Context.GetSystemService(Context.InputMethodService) as InputMethodManager;
inputMethodManager?.HideSoftInputFromWindow(Control.WindowToken, HideSoftInputFlags.None);
e?.Focus();
});
}
}
Based on your code, I think you're right to try to dismiss the keyboard in UI thread, I'm not sure that happens with new Handler().Post() here, but you can use BeginInvokeOnMainThread to force the code run on UI thread:
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.FocusChange += (sender, eh) =>
{
if (eh.HasFocus)
{
Device.BeginInvokeOnMainThread(() =>
{
var imm = (InputMethodManager)Control.Context.GetSystemService(Context.InputMethodService);
imm.HideSoftInputFromWindow(Control.WindowToken, HideSoftInputFlags.None);
});
}
};
}
}
This code works by my side and the FocusChange event can be fired normally.
I have a fully functional custom android keyboard in which i have to add speech recognition. Here are the relevant parts of the implementation i have
public class CustomInputMethodService
extends InputMethodService
implements <random stuff> {
private SpeechRecognizer mSpeechRecognizer;
private RecognitionListener mSpeechlistener;
public void onCreate() {
super.onCreate();
mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
mSpeechlistener = new CustomRecognitionListener();
mSpeechRecognizer.setRecognitionListener(mSpeechlistener);
}
#Override
public void onPress(int primaryCode) {
if (primaryCode == KeyCodes.VOICE_INPUT) {
mSpeechRecognizer.startListening(getSpeechIntent());
}else if(..){
...
}
}
private Intent getSpeechIntent() {
Intent speechIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
speechIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
speechIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, this.getPackageName());
speechIntent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, false);
return speechIntent;
}
}
The relevant method of the CustomRecognitionListener is simply:
#Override
public void onResults(Bundle results) {
ArrayList<String> matches = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
Log.d(TAG, "onResults: ----> " + matches.get(0));
if(matches != null && matches.size() > 0) {
writeText(matches.get(0));
}
}
This code is working just fine. The twist here is that i want a similar behaviour to what happens on google keyboard when the uset taps the microphone key:
This would ideally by achieved by something like:
Intent voiceIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
try {
startActivityForResult(voiceIntent, Constants.RESULT_SPEECH);
} catch (ActivityNotFoundException ex) {
DebugLog.e(TAG, "Not found excpetion onKeyDown: " + ex);
}
However, since the key listener is on and InputMethodService im not able to call startActivityForResult.
What is the ideal way to accomplish this? Should i simply start a new activity without a layout and have a callback to the inputMethodService? seems messy
Your screenshot shows "Google voice typing", which is an independent IME that is called by the Google Keyboard when its microphone button is pressed. So, your IME should do the same: replace itself with an IME that provides voice typing, and hope that there is a backlink to your IME once the voice typing is done.
The simplest implementation would be Switching among IME Subtypes, but you might want to have more control, e.g. start a specific IME with specific input parameters, etc. I'm not sure what is the best/standard way to achieve this extra control.
For an example of a voice typing IME you could look into (my app) Kõnele.
Simple implementation of the solution:
// on mic tap we call
public void startVoiceListening() {
InputMethodManager imeManager = (InputMethodManager) getApplicationContext().getSystemService(INPUT_METHOD_SERVICE);
String voiceExists = voiceExists(imeManager);
if (voiceExists != null) {
final IBinder token = getWindow().getWindow().getAttributes().token;
imeManager.setInputMethod(token,voiceExists);
}
}
private String voiceExists(InputMethodManager imeManager) {
List<InputMethodInfo> list = imeManager.getInputMethodList();
for (InputMethodInfo el : list) {
// do something to check whatever IME we want.
// in this case "com.google.android.googlequicksearchbox"
}
return null;
}
Once we no longer want to use the current IME just close it and it will fall back to the previous one
I had tried this out. And it works fine with Samsung tablet.
On Page 1_4.html i have to hide keypad and on 2.html I Have to show
keypad.
Both on textbox click inside webview
NOTE: Android Activity is Same.
I'm calling this code on webView.setOnTouchListener
if (value.equals("1") || value.equals("4")) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
} else if(value.equals("2")) {
getWindow().clearFlags( WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
}
But its not working in any mobile phones. It gives me Warning
W/InputMethodManager(25060): startInputInner : InputBindResult == null
I have google it. But didn't find anything useful.
What should I do now? Any help will be Appreciated.
To open keypad try this
webview.postDelayed(new Runnable() {
#Override
public void run() {
InputMethodManager keyboard = (InputMethodManager)
MainActivity.this.getSystemService(Context.INPUT_METHOD_SERVICE);
keyboard.showSoftInput(webview, 0);
}
},100);
To close keypad try this
InputMethodManager inputMethodManager = (InputMethodManager)MainActivity.this.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), 0);
try this code : This is working on all devices.
try
{
if(isopen)
{
// to hide keyboard
InputMethodManager inputMethodManager = (InputMethodManager)context.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}else{
// to open keyboard
InputMethodManager inputMethodManager=(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.toggleSoftInputFromWindow(linearLayout.getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0);
}
}
catch (NullPointerException e)
{
}
catch (Exception e)
{
}
I try to select text in webview, after I select text,I need to decide what to do next.not just copy the selected text.I have more choice for user to choose from.I mean, after user selected text in webview,could I prompt out a some button for further? I tried use emulateshiftheld to solve my problem.but google's docs said " This method is deprecated".
also,I can't prompt out some choice button.
you can clck the link to see what I mean. link: https://public.blu.livefilestore.com/y1pHhMR2iyIbQN7uJ2C-9CLLJBosWAZw2r4MvD0qyyTG-QWUM-06i6HFu4Fn4oaWnHMbDyTBOa-CPwN6PwoZNifSQ/select.jpg?download&psid=1
Pasting relevant code from WebView emulateShiftHeld() on Android Newer SDK's
/**
* Select Text in the webview and automatically sends the selected text to the clipboard
*/
public void selectAndCopyText() {
try {
KeyEvent shiftPressEvent = new KeyEvent(0,0,KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_SHIFT_LEFT,0,0);
shiftPressEvent.dispatch(mWebView);
} catch (Exception e) {
throw new AssertionError(e);
}
}
The question is very old, but for other people here is a solution with javascript for API 19+. Just add this to your WebView:
public void getSelectedText(final SelectedTextInterface selectedTextInterface) {
evaluateJavascript("(function(){return window.getSelection().toString()})()", new ValueCallback<String>() {
#Override
public void onReceiveValue(final String selectedText) {
if (selectedText != null && !selectedText.equals("")) {
//If you don't have a context, just call
//selectedTextInterface.onTextSelected(selectedText);
if (context instanceof Activity) {
((Activity) context).runOnUiThread(new Runnable() {
#Override
public void run() {
selectedTextInterface.onTextSelected(selectedText);
}
});
} else selectedTextInterface.onTextSelected(selectedText);
}
}
});
}
public interface SelectedTextInterface {
void onTextSelected(String selectedText);
}
When you are done with selecting text, just call it with:
webView.getSelectedText(new YourWebView.SelectedTextInterface() {
#Override
public void onTextSelected(String selectedText) {
//Your code here
}
});
I hope this may be useful for some people :-)