I am developing a native Android app that is a wrapper for a webpage. It works pretty well, but there is an issue where the soft keyboard (Android keyboard) appears over the bottom of the webview, which makes it impossible to see what you are writing if you are trying to fill out something near the bottom of the webview.
Please see image below. Here I've clicked a textarea that is impossible to reach while the keyboard is open:
The code for this view is:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="0dp"
android:paddingRight="0dp"
android:paddingTop="0dp"
android:paddingBottom="0dp" tools:context=".PetpulseMainActivity">
<WebView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/petpulseWebView" />
</RelativeLayout>
I've tried switching the RelativeLayout with ScrollView and other approaches I've found, but for some reason the keyboard is always rendered on top of the view.
AndroidManifest.xml:
<activity
android:name=".PetpulseMainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait">
[...]
</activity>
It's a known bug as refered in :
https://code.google.com/p/android/issues/detail?id=5497
To avoid it, remove the FullScreen theme of your activity
Update:
From FLAG_FULLSCREEN
Window flag: hide all screen decorations (such as the status bar)
while this window is displayed. This allows the window to use the
entire display space for itself -- the status bar will be hidden when
an app window with this flag set is on the top layer. A fullscreen
window will ignore a value of SOFT_INPUT_ADJUST_RESIZE for the
window's softInputMode field; the window will stay fullscreen and will
not resize.
Related
TL;DR: soft keyboard should overlap a bottom-anchored view instead of pushing it up. Gitlab link for an mcve.
Summary:
I have an AppCompatDialogFragment (androidx) which appears fullscreen on phones and has fixed dimensions on tablets (using dialog?.window?.setLayout(width, height) in case this matters). The dialog's layout has some content placed in a ScrollView and a button-like layout anchored at the bottom (complete XML structure see below).
Side note: the superclass of the AppCompatDialogFragment in question calls setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)on its Window.
The problem:
When the soft keyboard appears as a result of some text input receiving focus, it pushes the complete layout up, including the bottom-anchored view that I want overlapped by the soft keyboard. For some reason, the issue only affects phones, on tablets the soft keyboard correctly overlaps everything including the bottom-anchored view without any additional adjustments or flags.
What I have tried (without any success):
setting android:windowSoftInputMode="adjustNothing" (tried other flags "just in case" as well) for the Activity in question, also tried to apply them in code
setting android:isScrollContainer="false" on the ScrollView and its parent
combinations of the above
looking for similar questions like this one and confirming the proposed solutions didn't work
Here's the layout in question (note: I omitted many unrelated attributes to keep the snippet reasonably sized; everything is positioned vertically matching the elements' order. The <include> elements contain the text inputs):
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:id="#+id/toolbar"
android:layout_height="?attr/actionBarSize"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#id/bottom_layout"
app:layout_constraintTop_toBottomOf="#id/toolbar"
android:isScrollContainer="false"
android:scrollbarStyle="outsideOverlay">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include
layout="#layout/some_layout_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<include
layout="#layout/some_layout_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
<!-- I want this one to be overlapped by the soft input, but it's just pushed up -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/bottom_layout"
app:layout_constraintBottom_toBottomOf="parent">
<View
android:layout_width="match_parent"
android:layout_height="#dimen/divider"
android:background="#color/dark_grey" />
<TextView
android:layout_width="match_parent"
android:layout_height="#dimen/some_dimen"
android:foreground="?attr/selectableItemBackground"
android:text="#string/text" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
The question: how do I force the soft keyboard to overlap the layout anchored at the bottom on all devices?
Please comment if you need any additional details.
EDIT: here's a minimal demo app that reproduces the issue: https://gitlab.com/Droidman/soft-keyboard-issue-demo
Try adding the following line to onCreateView() of DemoDialog:
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
It is important to apply this change to the window of the dialog and not to the window of the activity.
With this in place, this is what I see on an Nexus 6 emulator running API 29 using your MCVE:
You may need to work with the placement a little, but this should help.
Let's look under the hood a little. For a phone and a tablet, the soft input mode is zero in onCreateView(). This value corresponds to SOFT_INPUT_ADJUST_UNSPECIFIED. The documentation for SOFT_INPUT_ADJUST_PAN explains what happens when the soft input mode is unspecified (emphasis is mine.)
Adjustment option for softInputMode : set to have a window pan when an input method is shown, so it doesn't need to deal with resizing but just panned by the framework to ensure the current input focus is visible. This can not be combined with SOFT_INPUT_ADJUST_RESIZE ; if neither of these are set, then the system will try to pick one or the other depending on the contents of the window.
Looking at the value of the soft input mode in onStart() (dialog?.window?.attributes?.softInputMode) shows the value selected by the system for the phone is SOFT_INPUT_ADJUST_RESIZE) and the value selected for the tablet is SOFT_INPUT_ADJUST_PAN. This explains the difference that is seen between phones and tablets.
So, always setting the soft input mode to SOFT_INPUT_ADJUST_PAN looks like the best solution although SOFT_INPUT_ADJUST_NOTHING also works and may be preferable for certain layouts.
Add this to your class inside the tags in the AndroidManifest in your Class:
android:windowSoftInputMode="stateHidden|adjustResize"
I don't have any sample code for this case, because I don't know how this work.
A screenshot will explain this much clearer.
I'm trying to create an input like a Telegram.
Once the sticker button is clicked, hide the keyboard and show a panel with the same height.
The current way that I'm doing will cause the window jumping around.
Because when the panel is open, the input will be pushed up
When the keyboard is hidden, the input will go to the bottom then pushed up after the sticker panel shows up.
This is what I have right now
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/inputLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:showIn="#layout/activity_main">
<LinearLayout
android:id="#+id/inputContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/inputBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<RelativeLayout
android:id="#+id/galleryContainer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#color/send_panel_color"
>
</RelativeLayout>
adjustResize
The activity's main window is always resized to make room for the soft keyboard on screen.
adjustPan
The activity's main window is not resized to make room for the soft keyboard. Rather, the contents of the window are automatically panned so that the current focus is never obscured by the keyboard and users can always see what they are typing. This is generally less desirable than resizing, because the user may need to close the soft keyboard to get at and interact with obscured parts of the window.
This might help you one of them !
<activity android:windowSoftInputMode="adjustResize"> </activity>
<activity android:windowSoftInputMode="adjustPan"> </activity>
Taken the help from
Other member of Stackoverflow
I appreciate there's a number of questions around this but none of them seem to resolve the situation I find myself in. I've written a small test case to see if the community can support.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="75dp"
android:background="#ff0000">
</RelativeLayout>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="12dp"
android:text="Hello World!" />
</RelativeLayout>
This snippet above, produces the following: -
when given a theme in the android manifest for this activity of: -
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
</style>
So.. this is exactly what I would like, however when I open the keyboard, the following happens: -
(given that I have the following set in the manifest)
android:windowSoftInputMode="adjustResize"
As you can see, the keyboard hides the edit text.
This is where there's a number of other posts and confusion
The recommendations seemed to be to set things like (and see the result for each): -
android:fitsSystemWindows in the root relativelayout
Great, this fixes the keyboard hiding the edit text but now the red bar at the top is moved downwards, which is not what I would like (see original image if needed)
Change windowSoftInputMode to adjustPan
As expected, the view pans and the top bar is lost.
At this point, I'm a bit lost without coming up with a hacky solution to resize and calculate on the fly, which feels very dirty.
So given what I've posted above, does anyone have any solution to achieve the following: -
Translucent status bar (so the red panel sits behind it)
red panel doesn't disappear when the soft keyboard is shown
soft keyboard doesn't cover the text control
Let's also assume for arguments sake that colouring the status panel is not an option as I actually want to view the content behind the status panel, i.e. a map. I've used a red panel as an example.
I'm trying to create a pretty basic chat screen with a ListView displaying the text and an EditText at the bottom and a "Send" button to the right of the EditText. Everything is functional, but when I click the EditText, the virtual keyboard covers it. The screen pans up a little but not enough to become visible above the keyboard. I've got the "adjustPan" tag in my manifest and have also tried the "adjustResize" tag to no avail. I'm guessing it has something to do with the way my layout is set up, but I honestly have no clue. Please help!
Current Layout...
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView android:id="#+id/android:list"
android:layout_height="0dip"
android:layout_width="fill_parent"
android:layout_weight="1"
android:stackFromBottom="true">
</ListView>
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<EditText android:id="#+id/sendMessageBox"
android:focusable="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:scrollbars="vertical"
android:maxLines="4"
android:text=""
android:inputType="textShortMessage|textAutoCorrect|textCapSentences|textMultiLine"
android:maxLength="1000"
android:hint="Type your message..."
android:imeOptions="actionSend"/>
<Button android:id="#+id/sendMessageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:text="Send"/>
</LinearLayout>
After doing a lot of searching apparently it's what I'm calling a bug. If you use the fullscreen tag (to remove the status bar from the activity) you can't use "adjustResize" without wrapping the activity in a ScrollView. Unfortunately for me I'm using a ListView which would create yet another problem. I'm sick of messing with it and will probably just abandon the fullscreen on that activity.
In your manifest file, you need to set the appropriate android:windowSoftInputMode property. This attribute is valid since API 3.
<activity
...
android:windowSoftInputMode="adjustPan" >
</activity>
Options are: http://developer.android.com/guide/topics/manifest/activity-element.html#wsoft
stateUnspecified The state of the soft keyboard (whether it is hidden or visible) is not specified. The system will choose an
appropriate state or rely on the setting in the theme. This is the
default setting for the behavior of the soft keyboard.
stateUnchanged The soft keyboard is kept in whatever state it was last in, whether visible or hidden, when the activity comes to the
fore.
"stateHidden" The soft keyboard is hidden when the user chooses the activity — that is, when the user affirmatively navigates forward
to the activity, rather than backs into it because of leaving another
activity.
stateAlwaysHidden The soft keyboard is always hidden when the activity's main window has input focus.
stateVisible The soft keyboard is visible when that's normally appropriate (when the user is navigating forward to the activity's
main window).
stateAlwaysVisible The soft keyboard is made visible when the user chooses the activity — that is, when the user affirmatively
navigates forward to the activity, rather than backs into it because
of leaving another activity.
adjustUnspecified It is unspecified whether the activity's main window resizes to make room for the soft keyboard, or whether the
contents of the window pan to make the current focus visible
on-screen. The system will automatically select one of these modes
depending on whether the content of the window has any layout views
that can scroll their contents. If there is such a view, the window
will be resized, on the assumption that scrolling can make all of the
window's contents visible within a smaller area. This is the default
setting for the behavior of the main window.
adjustResize The activity's main window is always resized to make room for the soft keyboard on screen.
adjustPan The activity's main window is not resized to make room for the soft keyboard. Rather, the contents of the window are
automatically panned so that the current focus is never obscured by
the keyboard and users can always see what they are typing. This is
generally less desirable than resizing, because the user may need to
close the soft keyboard to get at and interact with obscured parts of
the window.
if you set android:windowSoftInputMode="adjustResize" for an activity in the manifest, then a ScrollView (or other collapsable ViewGroups) will shrink to accommodate the soft keyboard. But, if you set android:windowFullscreen="true" in the activity’s theme, then the ScrollView won’t shrink because it’s forced to fill the whole screen. However, setting android:fitsSystemWindows="false" in your theme also causes adjustResize not to work
I had this in my AndroidManifest. It caused the adjustPan to stop working correctly. I removed the block below and everything works fine again.
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="false"
android:anyDensity="false" />
Here is one workaround I have found. Open the problematic editText and hit the RETURN key. Notice it shifts the editText closer to the position you're shooting for.
So although hacky, you can essentially please a newline at the top of the edittext.
This also seems to work using a newline at the bottom but you'd have to use a delay to not add the newline until AFTER the soft keyboard has animated into position.
Note I only have this problem on certain phones (DroidX).
if (android.os.Build.MODEL.equals("DROIDX")) {
inputEt.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
String text = inputEt.getText().toString();
text = "\n\n" + text.trim();
inputEt.setText(text);
inputEt.setSelection(text.length());
}
});
}
Try adding android:windowSoftInputMode="adjustResize|stateVisible|stateAlwaysHidden" in your manifest.
You can try the following settings:
<supports-screens
android:anyDensity="true"/>
I have added a LinearLayOut having some buttons My screen is RelativeLayOut it self
Here is the code for that linear layout manager
<LinearLayout
android:orientation="horizontal"
android:gravity="bottom"
android:layout_alignParentBottom="true"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:id="#+id/Footer"
android:layout_marginBottom="5dp">
Here is the problem:
There is an EditText component on the top and it pops a soft keyboard on the screen , and brings my Footer manager on top of the keyboard and eventually SHATTERS my whole UI.
What is the exact solution?
P.S. I have removed android:gravity="bottom" and android:layout_alignParentBottom="true" one by one but with hard luck i did not get desired result.
Thanks
Add android:windowSoftInputMode="adjustPan" to manifest - to the corresponding activity:
<activity android:name="MyActivity"
...
android:windowSoftInputMode="adjustPan"
...
</activity>
You probably want
<activity
...
android:windowSoftInputMode="adjustNothing">
</activity>
That will prevent any layout changes when the soft keyboard is shown.
There is probably some confusion over this since it's currently missing from the documentation at http://developer.android.com/guide/topics/manifest/activity-element.html#wsoft