Disable soft keyboard on NumberPicker - android
I'm trying to deactivate the soft keyboard when using a NumberPicker to enter numerical values (for aesthetic reasons). This is my layout-xml-code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/linearLayout2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="30dp"
android:layout_marginTop="30dp" >
<NumberPicker
android:id="#+id/repetitionPicker"
android:layout_width="40dp"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="#string/repetitions_short_divider"
android:textAppearance="?android:attr/textAppearanceMedium" />
<NumberPicker
android:id="#+id/weightPicker"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="#string/pounds"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
<Button
android:id="#+id/saveButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="#string/save" />
</LinearLayout>
And finally this is the code where I try to block the keyboard in the onCreate()-method:
// hide keyboard
View.OnClickListener disableKeyBoardListener = new View.OnClickListener() {
public void onClick(View v) {
((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE))
.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
};
((EditText) weightPicker.getChildAt(1)).setInputType(InputType.TYPE_NULL);
((EditText) repetitionPicker.getChildAt(1)).setInputType(InputType.TYPE_NULL);
((EditText) weightPicker.getChildAt(1)).setOnClickListener(disableKeyBoardListener);
//((EditText) repetitionPicker.getChildAt(1)).setOnClickListener(disableKeyBoardListener);
//weightPicker.setOnClickListener(disableKeyBoardListener);
//repetitionPicker.setOnClickListener(disableKeyBoardListener);
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Sadly, the soft keyboard still shows up when clicking on a NumberPicker. Any ideas?
Just found this and it works like a charm:
myNumberPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
You can also set this in XML:
android:descendantFocusability="blocksDescendants"
Xml version of Andrew Webber's answer
android:descendantFocusability="blocksDescendants"
Example
<NumberPicker
android:id="#+id/your_numberpicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"/>
After reading through the com/android/internal/widget/NumberPicker.java source code i got to the following solution:
// Hide soft keyboard on NumberPickers by overwriting the OnFocusChangeListener
OnFocusChangeListener fcl = new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
// Do nothing to suppress keyboard
}
};
((EditText) numberPicker.getChildAt(1)).setOnFocusChangeListener(fcl);
// Suppress soft keyboard from the beginning
((EditText) numberPicker.getChildAt(1)).setInputType(InputType.TYPE_NULL);
Just enhanced the #MaxVogler 's ans (so if wannt vote this vote #MaxVogler too) and make it a robust hack. Also we dont need to call setOnFocusChangeListener and setInputType. Only setFocusable to false will do.
Below is a helper api to enable/disable the feature
public static void enableNumberPickerManualEditing(NumberPicker numPicker,
boolean enable) {
int childCount = numPicker.getChildCount();
for (int i = 0; i < childCount; i++) {
View childView = numPicker.getChildAt(i);
if (childView instanceof EditText) {
EditText et = (EditText) childView;
et.setFocusable(enable);
return;
}
}
}
Here's another way to do it which enables the user still to edit a number if they want to - it just suppresses the soft keyboard initially. Use NumberPicker.setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS) to suppress the soft keyboard when the interface first shows as per answers above. Then get your dialog or activity to implement View.OnTouchListener, call setOnTouchListener(this) on your NumberPicker, and in your implementation of onTouch(View v,MotionEvent e) reset the numberpicker descendant focusability to its normal value, then return false.
Returning false means that the touch is still processed by the NumberPicker, which means that if the user taps the edit box the soft keyboard comes up. This happens to be exactly what I wanted faced with the same problem - having the soft keyboard come up with the dialog when it first shows is displeasing as it shifts the dialog up after it appears.
public class GetBufferDialog extends DialogFragment implements View.OnTouchListener {
after creating the Dialog in the onCreateDialog() method and finding the NumberPicker:
m_oldFocus = m_numberpicker.getDescendantFocusability();
m_numberpicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
m_numberpicker.setOnTouchListener(this);
and here's the OnTouch method:
public boolean onTouch(View v, MotionEvent event) {
m_numberpicker.setDescendantFocusability(m_oldFocus);
return false;
}
Working code
Programatically :
mp.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
XML:
android:descendantFocusability="blocksDescendants"
I don't know why it works, but setting OnClickListener which does nothing prevented keyboard from showing (Lollipop)
numberPicker.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
The simplest I found to work was :
numberPicker = (NumberPicker) myDialogView.findViewById(R.id.myViewId);
EditText numberPickerChild = (EditText) numberPicker.getChildAt(0);
numberPickerChild.setFocusable(false);
numberPickerChild.setInputType(InputType.TYPE_NULL);
If you only want to hide the software keyboard when loading the view with your number picker, but still want the users to be able to edit after the view loads, then you shouldn't block descendant focusability. Instead, just prevent the number picker from being the first focused item in your view.
See this answer for details.
Based on the above answer:
<!-- Dummy item to prevent Number Picker from receiving focus -->
<LinearLayout
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="0px"
android:layout_height="0px"/>
<!-- :nextFocusUp and :nextFocusLeft have been set to the id of this component
to prevent the dummy from receiving focus again -->
<NumberPicker
android:id="#+id/number_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusUp="#id/number_picker"
android:nextFocusLeft="#id/number_picker"/>
/**
* set focus to top level window
* disposes descendant focus
* disposes softInput
* #param context - activity context
* #param enable - state of focus
* */
public static void topLevelFocus(Context context, boolean enable){
if(Activity.class.isAssignableFrom(context.getClass())){
ViewGroup tlView = (ViewGroup) ((Activity) context).getWindow().getDecorView();
if(tlView!=null){
tlView.setFocusable(enable);
tlView.setFocusableInTouchMode(enable);
tlView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
tlView.requestFocus();
}
}
}
* calling this:
will not block descendant focusability (numberpicker will be editable)
will hide soft input on create
before (processing input) getValue() will allow to get proper walue
This extension is nice to not forget how to do it and have readable code. It is little bit hiding implementation details, but in this case I believe it's acceptable:
fun NumberPicker.disableTextEditing(disable: Boolean) {
descendantFocusability = if (disable) FOCUS_BLOCK_DESCENDANTS else FOCUS_BEFORE_DESCENDANTS
}
Related
Hide the keyboard after clicking on the EditText
I'm using Date and Time Picker to handle the meeting date field, so there is no need for the keyboard. How can I prevent the keyboard from showing after clicking on the field?enter image description here
There is a better way of programatically hiding the keyboard. Go in xml and add the following attribute android:focusable="false" E.g <EditText android:id="#+id/time_date_et" android:layout_width="wrap_content" android:layout_height="wrap_content" android:fontFamily="#font/prompt_light" android:focusable="false" android:textSize="17sp" /> The above attribute ensures that the keyboard won't appear!
You can use property android:focusableInTouchMode="false" in xml <com.google.android.material.textfield.TextInputEditText android:id="#+id/editText" android:layout_width="match_parent" android:layout_height="wrap_content" android:focusableInTouchMode="false" android:inputType="text|date"/> And add click listener to this view in code editText.setOnClickListener(new OnClickListener() { #Override public void onClick(View v) { //show date picker } });
val activity: Activity = this //if you are in the Activity val imm = activity.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager var view = activity.currentFocus if (view == null) { view = View(activity) } imm.hideSoftInputFromWindow(view.windowToken, 0) this piece of code should hide your virtual keyboard. Just put it in a method and call. :)
Best way to unfocus edittext when user interacts with another (non-texual) input element
I have an activity with some edittexts and some checkboxes, etc. I have validators set on text entries that get executed when a text entry loses focus. But the problem is when the user clicks/touches a checkbox, edittext doesn't lose focus and therefore the validator is not run. What is the best way for causing unfocus of text entries when the user touches another input field? I know I can e.g. set a handler on every checkbox to force unfocusing of text fields happen, but I think there is probably a more concise/general method for this purpose; Setting a handler on every checkbox seems too cumbersome and error prone. thank u.
You can try this way(it only is an example). your_activity.xml <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="#+id/sv_content" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:focusableInTouchMode="true" android:orientation="vertical"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:text="EditText 1" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:text="EditText 2" /> ..............other views................ </LinearLayout> </ScrollView> Using android:focusableInTouchMode="true" in the LinearLayout to make the EditText is focused when touching on it( or when starting this activity there is not auto focus to any EditText also). In your activity: #Override protected void onCreate(#Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test); ScrollView svContent = findViewById(R.id.sv_content); svContent.setOnTouchListener(new View.OnTouchListener() { #Override public boolean onTouch(View view, MotionEvent motionEvent) { int action = motionEvent.getAction(); if(action == MotionEvent.ACTION_MOVE || action == MotionEvent.ACTION_UP) { View focusView = getCurrentFocus(); if (focusView != null) { // The code for unfocus here return true; } } return false; } }); }
Soft Keyboard doesn't show on focus
I have a small function to open the soft keyboard when a EditText is programmatically focused as shown here... public void getUserName() { EditText tv = (EditText)findViewById(R.id.user_info_name); tv.setOnFocusChangeListener(new View.OnFocusChangeListener() { #Override public void onFocusChange(View view, boolean b) { if (b) { showDialog("Focused!"); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); } } }); tv.selectAll(); tv.requestFocus(); } However, the soft keyboard doesn't appear automatically but the dialog DOES show stating focused. In order to get the keyboard to appear I have to click inside the EditText. My XML is as follows... <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:id="#id/user_info_name" android:editable="true" android:hint="#string/user_info_name" android:inputType="textCapWords|textPersonName" android:textColor="#color/blue_gray" android:maxLength="50" android:layout_centerInParent="true" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:enabled="true" android:focusable="true" android:focusableInTouchMode="true" /> Can someone please advise why it's not working or what I am missing / failing to address. Thanks in advance as always. SOLVED: The following change to the function fixed the issue... public void getUserName() { EditText tv = (EditText)findViewById(R.id.user_info_name); tv.selectAll(); tv.requestFocus(); InputMethodManager imm = (InputMethodManager)this.getSystemService(this.INPUT_METHOD_SERVICE); imm.showSoftInput(tv,InputMethodManager.SHOW_IMPLICIT); }
android edittext remove focus after clicking a button
I have an Activity with an EditText and a Button. When the User clicks on the EditText, the keyboard is shown and he can type in some Text - fine. But when the user clicks on the Button I want the EditText to be no more in focus i.e. the keyboard hides til the user clicks again on the EditText. What can I do to 'hide the focus' of the EditText, after the Button is clicked. Some Code I can add in the OnClick Method of the Button to do that? EDIT: <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <EditText android:id="#+id/edt_SearchDest" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="0.8" android:textSize="18sp" android:hint="Enter your look-up here.." /> <Button android:id="#+id/btn_SearchDest" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="0.2" android:text="Search" /> </LinearLayout> Best Regards
Put this in your button listener: InputMethodManager inputManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),InputMethodManager.HIDE_NOT_ALWAYS); EDIT The solution above will break your app if no EditText is focused on. Modify your code like this: add this method to you class: public static void hideSoftKeyboard (Activity activity, View view) { InputMethodManager imm = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0); } Then, in your button listener, call the method like this: hideSoftKeyboard(MainActivity.this, v); // MainActivity is the name of the class and v is the View parameter used in the button listener method onClick.
One workaround is to create a fake view to transfer focus to when you clearFocus in your edittext: <EditText android:id="#+id/edt_thief" android:layout_width="0dp" android:layout_height="0dp" android:focusable="true" android:focusableInTouchMode="true" Note that this view is invisible so it doesn't require any space in the layout. In the control class, you can add a method like the following to trigger this focus transfer: public void clearFocus(){ yourEdittext.clearFocus(); edtThief.requestFocus(); } You can then minimize the keyboard once edtThief has focus: public static void hideKeyboard(final View view) { InputMethodManager imm = (InputMethodManager) view.getContext() .getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getWindowToken(), 0); }
I've successfully used the following in the onClick button code: editText.setEnabled(false); editText.setEnabled(true); Somewhat less complex than other methods...
The most elegant solution that I could find is this: You can save this method in your utility class: public static void hideSoftKeyboard(Activity activity) { if (activity == null) return; if (activity.getCurrentFocus() == null) return; InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0); } By simply calling hideSoftKeyboad() method it will hide the keyboard but as you can see, the focus will still be present. In order to remove the focus we will use a simple trick. Right above your input controls, add a dummy view like this: <View android:id="#+id/dummy" android:layout_width="1dp" android:layout_height="1dp" android:focusable="true" android:focusableInTouchMode="true" /> Then, write this line of code at the place where you call the focus-hiding method: theTextView.clearFocus(); Since the app needs to pass the focus to the next control it will be passed to our invisible view.
How i solved it. // xml file <LinearLayout ... android:id="#+id/linear_layout" android:focusableInTouchMode="true"> // 1. make this focusableInTouchMode... </LinearLayout> // Activity file private LinearLayout mLinearLayout; // 2. parent layout element private Button mButton; mLinearLayout = findViewById(R.id.linear_layout); mButton = findViewById(R.id.button); mButton.setOnClickListener(new View.OnClickListener() { #Override public void onClick(View v) { mLinearLayout.requestFocus(); // 3. request focus } }); I hope this helps you :)
The top answer definitely works but would add a lot of unnecessary codes in my use case, where there are many buttons and every one of them will need a setOnClickListener code block to remove focus from the EditText. Instead, my approach is to write a BindingAdapter to perform both focus change and the intended click action. BindingAdapter #BindingAdapter("onClickWithFocusChange") fun View.setOnClickWithFocusChangeListener(clickListener: View.OnClickListener?) { clickListener?.also { setOnClickListener(OnClickWithFocusChangeListener(it)) } ?: setOnClickListener(null) } class OnClickWithFocusChangeListener( private val clickListener: View.OnClickListener ) : View.OnClickListener { override fun onClick(v: View?) { v?.requestFocusFromTouch() clickListener.onClick(v) v?.clearFocus() } } In xml (databinding can now be used instead of programmatically setting every one of the clicklisteners): <!-- parentview of the EditText --> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:focusable="true" android:focusableInTouchMode="true"> <ImageButton ... onClickWithFocusChange="#{() -> viewModel.buttonClicked()}" ... /> In activity/fragment: editText.setOnFocusChangeListener { v, hasFocus -> if (!hasFocus) { requireContext().hideKeyboard(v) v.clearFocus() } } And lastly the extension function: fun Context.hideKeyboard(view: View) { val inputMethodManager = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0) } Hope this helps some one!
<LinearLayout android:id="#+id/parent" android:focusableInTouchMode="true" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <EditText android:id="#+id/edt" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="0.8" android:textSize="18sp" android:hint="Enter your look-up here.." /> <Button android:id="#+id/btn" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="0.2" android:text="Search" /> </LinearLayout> set android:focusableInTouchMode="true" to the parent layout. on button click transfer the focus to parent. binding.btn.setOnClickListener { binding.parent.requestFocus() // your stuff here }
private void hideDefaultKeyboard() { activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);//u have got lot of methods here } EDIT: LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
mTextView.setEnabled(!mTextView.isEnabled()); mTextView.setEnabled(!mTextView.isEnabled());
Sorry late to the answer, but I hope this will be the right answer, as I fixed it using try { InputMethodManager imm = (InputMethodManager) context .getSystemService(Context.INPUT_METHOD_SERVICE); if (v != null) { imm.hideSoftInputFromWindow(v.getWindowToken(),InputMethodManager.HIDE_NOT_ALWAYS); } } catch (Exception ignored) { } mEditText.setSelected(false); mEditText.setFocusable(false); mEditText.setFocusableInTouchMode(true); Write the following snippet on your button click.
Why not just disable the EditText in the Button code? That should get rid of the keyboard and the focus. edt_SearchDest.setEnabled(false);
If you are trying to create a button like in a notes app, just do the following: note.setEnabled(false); note.setEnabled(true); This will make a kind of checkmark like button (hides keyboard and removes cursor).
Editview press softkey Return, lose focus AND hide keyboard, how?
I'm working on an Android app and I've got 2 editviews and a label. The user can enter 2 values and the label shows some calculation using input from the editviews. What I want is the following; user enters either value with soft-keyboard user presses "Return" softkey editview should lose focus the soft-keyboard should disappear textview label should be recalculated Now, the v.clearFocus only seems to works when there is another widget that can can get focus(?), so I've also added a dummie zero-pixel layout that can 'steal' the focus from the first editview. The Return key works now, but when the user switches focus from edit1 to edit2 by simply tapping then HideKeyboard() crashes. I've tried checking if inputMethodManager==null but that didn't help. This all feels like I'm hacking to trick Android into doing some common UI behaviour, so I can't help but think that I'm overlooking something here. Any help would be greatly appreciated. Btw I know this is similar to this question: How to lose the focus of a edittext when "done" button in the soft keyboard is pressed? But I've tried that and it doesn't work. So my layout xml is this: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="vertical" > <!-- Dummy control item so that first textview can lose focus --> <LinearLayout android:focusable="true" android:focusableInTouchMode="true" android:layout_width="0px" android:layout_height="0px"/> <EditText android:id="#+id/editTest1" android:layout_width="250px" android:layout_height="wrap_content" android:inputType="numberDecimal" android:imeOptions="actionDone" > </EditText> <EditText android:id="#+id/editTest2" android:layout_width="250px" android:layout_height="wrap_content" android:inputType="numberDecimal" android:imeOptions="actionDone" > </EditText> <TextView android:id="#+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="test123" /> </LinearLayout> And the source is this: public class CalcActivity extends Activity implements OnFocusChangeListener { #Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.tab2_weight); EditText testedit = (EditText) findViewById(R.id.editTest1); testedit.setOnFocusChangeListener(this); testedit.setOnEditorActionListener(new OnEditorActionListener() { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if(actionId==EditorInfo.IME_ACTION_DONE){ //Clear focus here from edittext Log.d("test app", "v.clearFocus only works when there are other controls that can get focus(?)"); v.clearFocus(); } return false; } }); } public void hideSoftKeyboard() { InputMethodManager inputMethodManager = (InputMethodManager) this.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0); } public void onFocusChange(View v, boolean hasFocus) { if (hasFocus == false) { Log.d("unitconverter", "onFocusChange hasFocus == false"); // update textview label TextView bla = (TextView) findViewById(R.id.textView1); bla.setText(String.format("%s + %s", (((EditText) findViewById(R.id.editTest1)).getText()), (((EditText) findViewById(R.id.editTest2)).getText()))); // hide keyboard hideSoftKeyboard(); } } }