Problem hiding keyboard when scrolling to an EditText field - java

I have a ScrollView that contains several EditText and AutoCompleteTextView views. I'd like to hide the keyboard if the user scrolls or taps out of the text box.
So I added this to my Fragments onViewCreated()
myScrollView?.viewTreeObserver?.addOnScrollChangedListener {
hideKeyboard()
}
The problem is, when I start scrolling the keyboard hides, BUT when I click an EditText or AutoCompleteTextView, the view starts to scroll to that field to show the keyboard, but because, the scrollview has the addOnScrollChangedListener it hides the keyboard. And the view just jumps back and forth with hiding and showing the keyboard.
What is the correct way to handle this scenario?
The hideKeyboard() comes from an extension class
fun Activity.hideKeyboard() {
hideKeyboard(currentFocus ?: View(this))
}
fun Context.hideKeyboard(view: View) {
val inputMethodManager = getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0)
}
fun Fragment.hideKeyboard() {
view?.let {
activity?.hideKeyboard(it)
}
}

Related

Keyboard visibility listener when activity is not resizable

I have an Activity where there are 2 EditText. I have applied android:windowSoftInputMode="adjustNothing". When the user clicks on the EditText, the soft keyboard opens to enter some value in it. I want to set some other View's visibility to Gone when the soft keyboard opens and also when the soft keyboard closes from the EditText on the back button press. Then I want to set some other View's visibility to Visible.
I have tried serveral solution but they are not working due to adjustNothing applied on the Activity.
I have also used following keyboard visibilty watcher library but it's also not working due to adjustNothing.
implementation 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:3.0.0-RC2'
You can try to set a global layout listener to the root view of your Activity to detect changes in the height of the view. When the height of the view decreases, you can assume that the keyboard has opened. When the height of the view increases, you can assume that the keyboard has closed.
val rootView = findViewById<View>(android.R.id.content)
rootView.viewTreeObserver.addOnGlobalLayoutListener(object :
ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
val heightDiff = rootView.rootView.height - rootView.height
if (heightDiff > dpToPx(this#YourActivity, 200f)) { // if more than 200 dp, it's probably a keyboard...
// do something here
} else {
// do something here
}
}
})
fun dpToPx(context: Context, dp: Float): Int {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.resources.displayMetrics).toInt()
}

Disable underlyingFragment when Drawer is opened

Hey,
In my app I have a Drawer. When it's open the editText from the underlying fragment still works. Does anyone know how I can fix this?
At the red arrow is an editText that shouldn't respond right now, when the Drawer is opened.
x
A very simple way is to just hide the keyboard then the drawer opens. The only way to get the keyboard showing again is to click the edittext.
Here is one way to hide it:
fun hideKeyboard(activity: Activity) {
val imm = activity.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
//Find the currently focused view, so we can grab the correct window token from it.
var view: View? = activity.currentFocus
//If no view currently has focus, create a new one, just so we can grab a window token from it
if (view == null) {
view = View(activity)
}
imm.hideSoftInputFromWindow(view.windowToken, 0)
}

Force EditText to lose focus when: some keyboard keys are pressed and when user clicks on something else in the activity

I know this question has been asked in many different ways before, but even though I have looked at many other related questions about EditText focus, I have not found my solution.
Here is what I want to achieve:
When the user is done Editing an EditText I want it to loose focus.
When the user hits outside the EditText I want such EditText to lose
focus.
Whenever the soft-keyboard hides or is hidden I want EditText
to lose focus.
Whenever the User hits ENTER or BACK ARROW in the soft-keyboard, the EditText focus should be cleared
This is what I currently have:
I have two EditText in an activity, which I will call EditText_1 and EditText_2 for simplicity so that we know which EditText I am talking about.
When the user starts the activity, the EditText_1 would have no focus, a blinking cursor and the soft-keyboard would be hidden. I have already fixed that problem using;
android:focusableInTouchMode="true"
and
android:focusable="true"
After the previous fix in part1, when I start the activity and click on any EditText, it will gain focus, however, when I am done editing such clicked EditText and the soft-keyboard hides, the EditText will not lose focus and the cursor will still be blinking.
Another example happens when I am editing an EditText and click any other button outside the editText, it will not force EditText to lose focus or hide the keyboard.
The current solution I have is
public void onFocusChange(View v, boolean hasFocus){...}
so that, it will call some method such as force the EditText to lose focus:
EditText.clearFocus();
and do not show that annoying blinking cursor once I know EditText loses its focus:
EditText.setCursorVisible(false);
However, because hitting Done or outside EditText do not force it to lose focus, onFocusChange will not be called all the times(as in the examples provided).
Some of the solutions I cannot accept are:
Set the cursor visibility to false in the XML activity file and never and anywhere change it back to true.
setCursorVisible(false);
I want the cursor to be seen when needed and to be hidden when it is not needed.
Have a button that needs to be clicked by the user so that inside such button all methods needed will be called. I mean, it is not user-friendly at all. Users do not want to be forced to click a button just to hide all focus, blinking cursors...
Here comes the part many of you will tell me, every single of these issues have been solved in different questions. HOWEVER, I have not been able to implement multiple solutions which will do all points previously stated.
To make editText lose focus when you press outside of the keyboard you can try to setOnTouchListener to the view that is visible when the keyboard is shown. For example, it might be the parent layout, listView, recyclerView or any other significant in size view. In order to do that, just add code below inside of your onCreate method in activity:
findViewById(R.id.loginLayout).setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
usernameEditText.clearFocus();
passwordEditText.clearFocus();
return false;
}
});
To make editText lose focus and/or hide keyboard when pressing some button on keyboard you can use the following code. There is an example of listener for Enter key. You may find all the other keys on official documentation.
yourEditText.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_ENTER) {
if (event.getAction() == KeyEvent.ACTION_UP) {
yourEditText.clearFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
}
return false;
}
});
This Solution works For SOFTKEYS, some code is from here
The final solution to hide keyboard and clear focus from the EditText would be;
yourEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
name.clearFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
Log.d(TAG, "actionID: " + actionId +" KeyEvent: " + event);
}
return false;
}
});

Another page poping up instead of keyboard

I want to open calculator which I created. This is the code I wrote:
TextView.OnClickListener listener = new TextView.OnClickListener(){
public void onClick(View v) {
InputMethodManager imm =(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(textOut1.getWindowToken(), 0);
imm.hideSoftInputFromWindow(textOut2.getWindowToken(), 0);
imm.hideSoftInputFromWindow(textOut3.getWindowToken(), 0);
imm.hideSoftInputFromWindow(textOut5.getWindowToken(), 0);
startActivity (new Intent("com.easyPhys.start.calculator"));
}
};
textOut1.setOnClickListener(listener);
textOut2.setOnClickListener(listener);
textOut3.setOnClickListener(listener);
textOut5.setOnClickListener(listener);
But what happens is virtual keyboard opens and my calculator opens only than I press ENTER. What is wrong with my code?
Try the onClick event listener on the TextView, instead of the OnEditorActionListener.
For it to work you also need to add the following attribute to the TextView in the xml.
android:clickable="true"
Don't forget it, without it it won't work.
The OnEditorActionListener only fires when some action is performed on the editor, and that's why the activity only shows when you click the keyboard. On the other hand, the onClick listener should fire right after you click the TextView.

How to set focus on a view when a layout is created and displayed?

Currently, I have a layout which contains a Button, a TextView and an EditText. When the layout is displayed, the focus will be automatically put on the EditText, which will trigger the keyboard to show up on Android phone. It is not what I want. Is there any way that I can set the focus on TextView or on nothing when a layout is displayed?
Set focus: The framework will handled
moving focus in response to user
input. To force focus to a specific
view, call requestFocus()
This works:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
You should add this:
android:focusableInTouchMode="true"
To set focus, delay the requestFocus() using a Handler.
private Handler mHandler= new Handler();
public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout mainVw = (LinearLayout) findViewById(R.id.main_layout);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
EditText edit = new EditText(this);
edit.setLayoutParams(params);
mainVw.addView(edit);
TextView titleTv = new TextView(this);
titleTv.setText("test");
titleTv.setLayoutParams(params);
mainVw.addView(titleTv);
mHandler.post(
new Runnable()
{
public void run()
{
titleTv.requestFocus();
}
}
);
}
}
Set
android:focusable="true"
in your <EditText/>
You can try just hidding the keyboard. Something like this:
InputMethodManager inputManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
Set these lines to OnResume as well and make sure if focusableInTouch is set to true while you initialize your controls
<controlName>.requestFocus();
<controlName>.requestFocusFromTouch();
Try
comp.requestFocusInWindow();
to change the focus make the textView in xml focusable
<TextView
**android:focusable="true"**
android:id="#+id/tv_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
and in java in on create
textView.requestFocus();
or simply hide the keyboard
public void hideKeyBoard(Activity act) {
act.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
InputMethodManager imm = (InputMethodManager) act.getSystemService(Context.INPUT_METHOD_SERVICE);
}
None of the answers above works for me. The only (let's say) solution has been to change the first TextView in a disabled EditText that receives focus and then add
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
in the onCreate callback to prevent keyboard to be shown. Now my first EditText looks like a TextView but can get the initial focus, finally.
The last suggestion is the correct solution. Just to repeat, first set android:focusable="true" in the layout xml file, then requestFocus() on the view in your code.
i think a text view is not focusable. Try to set the focus on a button for example, or to set the property focusable to true.
you can add an edit text of size "0 dip" as the first control in ur xml, so, that will get the focus on render.(make sure its focusable and all...)
You can start by adding android:windowSoftInputMode to your activity in AndroidManifest.xml file.
<activity android:name="YourActivity"
android:windowSoftInputMode="stateHidden" />
This will make the keyboard to not show, but EditText is still got focus. To solve that, you can set android:focusableInTouchmode and android:focusable to true on your root view.
<LinearLayout android:orientation="vertical"
android:focusable="true"
android:focusableInTouchMode="true"
...
>
<EditText
...
/>
<TextView
...
/>
<Button
...
/>
</LinearLayout>
The code above will make sure that RelativeLayout is getting focus instead of EditText
Focus is for selecting UI components when you are using something besides touch (ie, a d-pad, a keyboard, etc.). Any view can receive focus, though some are not focusable by default. (You can make a view focusable with setFocusable(true) and force it to be focused with requestFocus().)
However, it is important to note that when you are in touch mode, focus is disabled. So if you are using your fingers, changing the focus programmatically doesn't do anything. The exception to this is for views that receive input from an input editor. An EditText is such an example. For this special situation setFocusableInTouchMode(true) is used to let the soft keyboard know where to send input. An EditText has this setting by default. The soft keyboard will automatically pop up.
If you don't want the soft keyboard popping up automatically then you can temporarily suppress it as #abeljus noted:
InputMethodManager inputManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
When a user clicks on the EditText, it should still show the keyboard, though.
Further reading:
Having Trouble Focusing? A Primer on Focus in Android
Android Developers Blog: Touch Mode
You can add
android:importantForAccessibility="yes"
android:focusable="true"
android:focusableInTouchMode="true"
to your Layout to force Talkback/accessibility to go there first.
You really only need the first line, however, the others reinforce to the OS what you want focused.
You can use the following Kotlin extension
fun View.focusAndShowKeyboard() {
/**
* This is to be called when the window already has focus.
*/
fun View.showTheKeyboardNow() {
if (isFocused) {
post {
// We still post the call, just in case we are being notified of the windows focus
// but InputMethodManager didn't get properly setup yet.
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT)
}
}
}
requestFocus()
if (hasWindowFocus()) {
// No need to wait for the window to get focus.
showTheKeyboardNow()
} else {
// We need to wait until the window gets focus.
viewTreeObserver.addOnWindowFocusChangeListener(
object : ViewTreeObserver.OnWindowFocusChangeListener {
override fun onWindowFocusChanged(hasFocus: Boolean) {
// This notification will arrive just before the InputMethodManager gets set up.
if (hasFocus) {
this#focusAndShowKeyboard.showTheKeyboardNow()
// It’s very important to remove this listener once we are done.
viewTreeObserver.removeOnWindowFocusChangeListener(this)
}
}
}
)
}
}
And just call your view.focusAndShowKeyboard() in override fun onViewCreated(..) or override fun OnCreate(..)
PS: For hiding Views use the following extension
fun View.hideKeyboard() {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(windowToken, 0)
}
Make sure the views are focusable before that using the following android XML attributes, u can also do it programmatically
android:focusableInTouchMode="true"
android:focusable="true"

Categories