I have 4 lines of input fields in my Layout.
The problem is that when i click the uppermost EditText, soft keyboard appears and hides the lowermost EditText.
My Goal is to keep every EditText fields visible in screen when soft keyboard pops up.
I tried windowSoftInputMode in Manifest but that's not what I wanted, it just keeps the 'focused' input field visible.
Is there any flags for View type to prevent hiding from soft keyboard, so that the screen always scrolls to show the specified Views?
You can put 4 lines of input fields into a linearlayout view then put this linearlayout into a scrollview, when soft keyboard appears, you scroll the scrollview to the last EditText view position.
int[] loc = new int[2];
lastEditTextView.getLocationOnScreen(loc);
the method to detect keyboard appears:
private ViewTreeObserver.OnGlobalLayoutListener mOnGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect r = new Rect();
if (activityRootView == null) {
return;
}
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
if (heightDiff > 100) {
// keyboard show
scrollView.smoothScrollTo(loc[0],loc[1]);
} else {
// keyboard hidden
}
}
};
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener);
Related
I have a BottomSheetBehavior in my main activity to constantly show a bottom drawer.
When I open and then close the keyboard (when pressing an EditText and then pressing Back), the method "OnSlide" gets triggered:
mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset)
{
// my code
}
}
I have code in this function that runs when the user slides the drawer up and down with his finger. I don't want this code to be run when the keyboard comes up and back down. It doesn't make sense that it's being called. How can I prevent keyboard changes from running the code in this function ?
I tried:
Changing in my AndroidManifest android:windowSoftInputMode="adjustResize" to android:windowSoftInputMode="adjustNothing" which essentialy does what I want, but removes useful functionalities which I had added (enabling scroll while keyboard is up).
Listening to soft keyboard changes to only execute code when changes are not occuring which doesn't work since OnSlide is called after keyboard is fully hidden (see code below).
Keyboard change listener:
mContentView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
Rect r = new Rect();
mContentView.getWindowVisibleDisplayFrame(r);
int screenHeight = mContentView.getRootView().getHeight();
// r.bottom is the position above soft keypad or device button.
// if keypad is shown, the r.bottom is smaller than that before.
int keypadHeight = screenHeight - r.bottom;
// 0.15 ratio is perhaps enough to determine keypad height.
mKeyboardIsOpen = keypadHeight > screenHeight * 0.15;
}
});
just like the picture, when the keyboard is show ,it hide the logo.
the question is how to listen the keyboard show/hide even? have some sample?
add this attribute to your activity in manifest
android:windowSoftInputMode="adjustResize"
Get a reference to the layout which you want to hide when keyboard pops up. You can set the visibility of that to GONE when keyboard is shown and to VISIBLE otherwise. So your task now is to detect whether the keyboard is shown or hidden. For that you can use ViewTreeObserver.OnGlobalLayoutListener().
rootView = getWindow().getDecorView().getRootView();
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect rect = new Rect();
rootView.getWindowVisibleDisplayFrame(rect);
int screenHeight = rootView.getHeight();
int keyboardHeight = screenHeight - (rect.bottom - rect.top);
if(keyboardHeight > screenHeight / 3){
//hide the layout
}
else{
//show the layout
}
}
});
I have a activity that has the "adjustPan" option set and it pans my view up just fine when a EditText receives focus and the soft keyboard is shown, but my problem is that there are UI elements below my EditText that needs to be visible also when the keyboard is shown and it is not on smaller screens. Can I some how tell the view to always pan so that those UI elements are visible by linking them to the EditText or something, or do I have to take control of the panning manually and calculate height and all, or what is the good solution here?
What you can do is you can use ViewTreeObserver to pan your content l'il bit more.
I did this is my app.
int edtHeight = 0;
// llContent is the Viewgroup layout which is inside a ScrollView.
ViewTreeObserver viewTreeObserver1 = llContent.getViewTreeObserver();
viewTreeObserver1.addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
// Here edtHeight will get the height of edittext as i wanted my view to scroll that much bit more
edtHeight = edtTemprature.getHeight();
ViewTreeObserver obs = llContent.getViewTreeObserver();
obs.removeGlobalOnLayoutListener(this);
}
});
//llMain is the parent View Group of my XML layout
llMain.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
Rect r = new Rect();
// r will be populated with the coordinates of your view
// that area still visible.
llMain.getWindowVisibleDisplayFrame(r);
int heightDiff = llMain.getRootView().getHeight() - (r.bottom - r.top);
if (heightDiff > 100)
{ // if more than 100 pixels, its probably a keyboard...
if(edtTemprature.hasFocus()){
llContent.scrollTo(0, (int) (edtHeight * 1.5));
}else{
llContent.scrollTo(0, 0);
}
}
else
{
llContent.scrollTo(0, 0);
}
}
});
Use stateHidden in Android manifestfile which class you need ..
android:windowSoftInputMode="stateHidden"
or else,
In Activity,
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
I'm trying to force the EditText control to lose focus when the user presses the back button to hide the keyboard. There are many questions similar to this already, but after several hours, I haven't been able to make it work.
First, just a little bit of context. I have a ListView with custom items. Each item has several TextViews and one EditText. I have an AfterTextChanged() method saving edited values. I have a style set up to highlight the field if it has focus. Unfortunately, it is now much more obvious that the EditText doesn't actually lose focus when you hide the (soft) keyboard, and I think it's confusing. I would like the EditText to not be focused if there's no keyboard.
The solution that seemed the most reasonable is to override OnBackPressed() in the activity as described here. Unfortunately, it doesn't appear that my method is being called. I.e. the field is still focused, and a breakpoint in the function doesn't fire.
Similarly, an OnKeyUp() listener on the activity doesn't fire, and Xamarin doesn't appear to support the OnKeyUp handler for the EditText control.
I'm not trying to suppress the keyboard on creation, or anything, so using any of the invisible control tricks don't help either.
It's obvious that a lot of people have this problem. I'm sure one of you has solved it! Can you please share your solution?
Thank you so much!
-Karen
P.S. I do not need to know how to hide the keyboard. I need to take an action when the user hides the keyboard with the back button. Thanks :)
In my experience onBackPressed() (at least the default #Override one in an activity) will not normally fire when pushing the back button to close the keyboard. As far as I know it will only fire when a Back press would initiate a finish() on the current activity.
Below is a kind of "hacky" way to know when the keyboard is shown/hidden by monitoring the change in the view size. You must also set the Activity to android:windowSoftInputMode="adjustResize" in the AndroidManifest.xml.
final View activityRootView = findViewById("Your main View");
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
//Keyboard is shown
}
if(heightDiff <= 100) {
//Keybaord not shown
}
}
});
With sincere thanks to #Shadesblade (and Xamarin's sample code), my EditTexts now unfocus! Here's the Xamarin-ized solution:
To your activity, add this class:
class GlobalLayoutListener : Java.Lang.Object, ViewTreeObserver.IOnGlobalLayoutListener
{
Action on_global_layout;
public GlobalLayoutListener (Action onGlobalLayout)
{
on_global_layout = onGlobalLayout;
}
public void OnGlobalLayout ()
{
on_global_layout ();
}
}
Add a class variable to hold the View so that the delegate can access it:
View _rootview;
In your OnCreate() add:
GlobalLayoutListener gll = new GlobalLayoutListener(
delegate {
Android.Graphics.Rect r = new Android.Graphics.Rect();
_rootView.GetWindowVisibleDisplayFrame(r);
int heightDiff = _rootView.RootView.Height - (r.Bottom - r.Top);
if (heightDiff < 100)
{
if (Window.CurrentFocus != null)
Window.CurrentFocus.ClearFocus();
}
});
_rootView = FindViewById<View>(Resource.Id.relativeLayoutOrder);
_rootView.ViewTreeObserver.AddOnGlobalLayoutListener(gll);
I expect to need to dork around with the heightDiff level and/or have to add some rotation checking, but I haven't done any rotation support at this point, so I can punt that until later.
Thank you again! *happy dance*
adding on to Shadesblade's answer, if you are using a scrollview, his answer needs a change to work, because not all of the scrollview is showing on screen.
so instead of doing
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
you should do
int heightDiff = Utils.getScreenHeight(SearchActivity.this) - (r.bottom - r.top);
where Utils.getScreenHeight is this:
public static int getScreenHeight(Context c) {
if (screenHeight == 0) {
WindowManager wm = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
screenHeight = size.y;
screenWidth = size.x;
}
return screenHeight;
}
i just want to shift my whole activity screen upwards when the user clicks on the edit text...
i mean the screen will shift upwards and below it we can see the soft keypad...
I have tried using android:windowSoftInputMode="adjustPan|adjustResize" in my Manifest file but it doesn't make any sense..
thanks in advance ...
In your xml layout. Make the scrollview to be root parent, and it will work!
Try this to detect if keyboard is up, and then scroll down (you need your scroll to be root in xml):
final View activityRootView = findViewById(R.id.scroll);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
//keyboard is visible
if (heightDiff > 100) {
scroll.fullScroll(ScrollView.FOCUS_DOWN);
}
}
});