adjustPan not preventing keyboard from covering EditText - android

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"/>

Related

Android adjust view when keyboard appears

I want to create a dynamic login screen that includes a decorative branding image when the screen is sufficiently tall but excludes the image on short screens. When the keyboard appears, it's likely the image will need to be removed. When the keyboard is hidden, the image can come back.
With a web page, I'd just use CSS media queries for the device height, show or hide the image appropriately, and it would all work nicely. I don't think anything that simple and clean is possible for an Android view, is it? So I figure I need to know the height of the window when the activity is created and create the view appropriately.
In the manifest, I've set my main activity to adjustResize when the keyboard appears. When the keyboard appears, my view does resize but my activity is surprisingly not recreated. When the screen is rotated, the activity is recreated.
The documentation says the view will be recreated when the keyboard availability changes. The first paragraph from https://developer.android.com/guide/topics/resources/runtime-changes
Some device configurations can change during runtime (such as screen orientation, keyboard availability, and when the user enables multi-window mode). When such a change occurs, Android restarts the running Activity ( onDestroy() is called, followed by onCreate()). The restart behavior is designed to help your application adapt to new configurations by automatically reloading your application with alternative resources that match the new device configuration.
My questions are
What's the best way to handle my design goal?
Why is my activity not recreated when the keyboard appears?
Below are the relevant parts of my test app. There is no image in this as I didn't even get that far before running into what seems like behavior contradicting the documentation.
AndroidManifest.xml
<activity
android:name=".MainActivity"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
Log.d("MainActivity", "onCreate")
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/intro"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:text="Top"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="#color/colorAccent" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/intro"
android:singleLine="true" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:text="Bottom"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="#color/colorAccent" />
</android.support.constraint.ConstraintLayout>
The activity isn't recreated when the keyboard appears because that isn't how Android works. Its not supposed to be. (Although if you have an old fashioned device with a slide out physical keyboard it will be recreated when you slide it out, because its treated as a hardware configuration change). Keyboards being shown/hidden is done without recreation. Which is a good thing, that many recreate events would be expensive given how many people just shove a ton of logic into onCreate.
How to do what you want- you can't. There is no API to detect when the keyboard is opened. There are commonly used hacks that attempt to discover it, but they're all flawed (they can have problems with split screen mode, picture in picture mode, multiple screens, and keyboards which are too small, because they all work based on guessing based on height changes).
The method OnFocusChangeListener() will detect whenever a View gains or loses focus. EditText makes the keyboard show up whenever it gains focus. Therefore, you should attach a OnFocusChangeListener() to those EditText that you want:
EditText myET = (EditText)findViewById(R.id.myET);
myET.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus) {
//Hide image
} else {
//Reveal image
}
}
});
Moreover, to hide and reveal the image you should use the property called visibility.
The methods are:
myImageView.setVisibility(View.VISIBLE); //This will show the Image
myImageView.setVisibility(View.INVISIBLE); //This will make the Image invisible
myImageView.setVisibility(View.GONE); //This will make the Image invisible, and also it will collapse the layout, occupying no space at all.
Don't try using INVISIBLE and GONE simultaneously, since that could cause some trouble. In your case, from what I understand you might want to use GONE and VISIBLE.
The only problem with this approach is that if you have multiple EditText, you would have to set up many times the same code. To solve that, please refer to the following link:
EditText setOnFocusChangeListener on all EditTexts
I've been searching for an answer and I came across this:
https://developer.android.com/training/keyboard-input/visibility#java
It says android DOES do what you want.
I just tried it, add 1 line, ONE LINE!, to your manifest and it works.
Oh wait... you want the brand to disappear... hmmm well with this it wouldn't have to?
DOH! You already knew about that.....
"What you want to do you can't"...
I don't know how to do it, but I disagree that it can't be done. I have the PayPal app and when the keyboard appears the login button and the rest of the login screen resize so that the login button isn't covered by the keyboard. How they're doing it, I don't know, but obviously somehow the app knows the keyboard appears and adjusts accordingly.
I've been searching for an answer and I came across this:
https://developer.android.com/training/keyboard-input/visibility#java
It says android DOES resize the screen when then soft keyboard appears/disappears.
I just tried it, add 1 line, ONE LINE!, to your manifest and it works.

Stop EditText from bringing up the keyboard on Activity start?

I have an Edit Text in one of my App layouts, and I want this EditText to only open the keyboard (I believe this is called being focused on?) when it is actually touched.
As of now, the keyboard opens with the EditText whenever the app opens, which isn't what I want.
I have tried many different XML tags to fix this:
android:focusable="false" <--- Prevents keyboard from opening at all.
android:focusable="true"
android:focusableInTouchMode = "true" <--- These tags give me the same result as no tags (keybaord will open on activity start)
android:focusedByDefault = "true" <--- Only available in API >= 23
What I am asking is, why is it so hard to disable default focus on an EditText? Surely I am missing an easy way to do this.
EDIT: Adding this line to my AndroidManifest fixed the issue:
android:windowSoftInputMode="stateHidden"
However, I don't like this solution. It seems like since this is in the Manifest, it will affect more UI elements than the single EditText I need to change.
Alternatively you can set the focus to the root layout element:
android:focusable="true"
android:focusableInTouchMode="true"
Example:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
android:focusable="true"
android:focusableInTouchMode="true">
<EditText
android:inputType="text"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Use android:windowSoftInputMode="stateHidden"
If you dig deep into the Theme you are using for your Activity, you will find that the default value of windowSoftInputMode is stateUnspecified|adjustPan. And from the documentation:
stateUnspecified: Not specified, use what the system thinks is best. This is the default.
So depending on the the android device you run, your results will vary. I tried reproducing your case in API-26 emulator and the keyboard doesn't show up.You can use stateHidden to ensure that when an activity starts, the soft keyboard doesn't show up when the EditText gets focused on itself.
The other way to solve this is to requestFocus to some other element in the UI, making sure the EditText is not the first UI element to get focused. In my experience this is kind of a hack and it messes up the accessibility. The safest and clean way to accomplish is actually to use stateHidden.
stateHidden: Make the soft input area hidden when normally appropriate (when the user is navigating forward to your window).
Note that this will not affect any other UI elements. You can use adjustPan also to this, based on the screen background.

Isn't windowsoftinputmode = adjustResize supposed to move ALL the activity window to make room for the keyboard?

I'm working on a chat feature for an app an stumbled across the following issue.
I have an activity with android:windowsotinputmode = "stateHidden|adjustResize" (when the activity starts, the keyboard doesn't pop automatically up but waits until the user taps on the editText to type his message and after, the whole activity screen should slide up and make room for the soft keyboard).
However...
I noticed that the activity only slides up until the keyboard is right below the editText, covering the 'random view' at the bottom of the activity.
Is there a way to override this and make the screen move up completely and make visible the whole activity?
[EDIT] I should also mention that setting any paddingBottom/marginBottom to the editText gets ignored as well as the view.
You could go through this link and the code,could help you:
http://android-developers.blogspot.in/2009/04/updating-applications-for-on-screen.html
<EditText android:id="#+id/edtInput"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="textShortMessage|textAutoCorrect|textCapSentences|textMultiLine"
android:imeOptions="actionSend|flagNoEnterAction"
android:maxLines="4"
android:maxLength="2000"
android:hint="#string/compose_hint"/>

Soft keyboard hides parts of fullscreen webview

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.

How to remove auto focus/keyboard popup of a field when the screen shows up?

I have a screen where the first field is an EditText, and it gains the focus at startup, also popups the numeric input type, which is very annoying
How can I make sure that when the activity is started the focus is not gained, and/or the input panel is not raised?
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editTextField.getWindowToken(), 0);
or
set activity property in manifest file as below in the application tag
android:windowSoftInputMode="stateHidden"
go to your application manifest file, and write this line for that activity you want to disable auto keyboard pop-up.
android:windowSoftInputMode="stateHidden"
To programatically not have the keyboard displayed, but the default widget still recieve focus call:
getWindow().setSoftInputMode(WindowManager.
LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
in onResume()
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
call the above method inside onCreate().It prevent softKeyboard to show unless user select EditText by tapping or clicking.
or simply add android:windowSoftInputMode="stateHidden" in Activity tag in Manifest.xml
This is usually a mess. The first thing I try is try to steal the focus with another view via . You also have to have the focusable and focusableInTouchMode.
<TextView
...
android:focusable="true"
android:focusableInTouchMode="true">
<requestFocus/>
</TextView>
Have another view grab focus. By default, the first focusable View will get focus when a layout is inflated. You can request focus on a different View via XML:
<TextView
android:layout_width="wrap_parent"
android:layout_height="wrap_content"
android:text="Some other view">
<requestFocus />
</TextView>
This works for any View.
If you want to do it programmatically, you can use view.requestFocus().
Adding android:windowSoftInputMode="stateHidden" to your Activity in manifest only hides the keyboard when you are launching the activity, or as Google says
When the user affirmatively navigates forward to the activity, rather
than backs into it because of leaving another activity
To hide the keyboard also when user presses the back button and moves back to your activity from some other activity, use android:windowSoftInputMode="stateAlwaysHidden"
if(getWindow().getAttributes().softInputMode==WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED)
{
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
}
have not tried this nor am i near my programming computer, but I would suspect programmatically sending focus to the parent view or something of that nature could do the trick - thats more likely a workaround than a solution, but again not able to test it just a thought

Categories

Resources