24

I have a layout that contains 5 EditText and a Button and a TextView at bottom. Now when I press an EditText then the keyboard will shown and all my View is push up.

Now I don't want to push my TextView and Button to above keyboard, just only want to push up all EditText inside ScrollView to above keyboard.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#ff0"
        >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            >

            <EditText
                android:layout_marginTop="30dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="EditText 1"

                />

            <EditText
                android:layout_marginTop="30dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="EditText 2"
                />

            <EditText
                android:layout_marginTop="30dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="EditText 3"
                />

            <EditText
                android:layout_marginTop="30dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="EditText 4"
                />

            <EditText
                android:layout_marginTop="30dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="EditText 5"
                android:inputType="textNoSuggestions"
                />

        </LinearLayout>

    </ScrollView>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="Button"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#000"
        android:text="I don't want to push this TextView and Button to above keyboard when keyboard is shown. Just obly want to push the ScrollView that contain all EditText"
        />
</LinearLayout>

enter image description here

I have an idea is. When I will listener when keyboard show and hide. When keyboard show I will set the bottom margin of ScrollView = keyboard height, when keyboard hide I will set this margin = 0.
Is there any way easier to handle my case? Any help or suggestion would be great appreciated.

UPDATE
If I use windowSoftInputMode=adjustPan => not all EditText is push up to above keyboard
If I use windowSoftInputMode=adjustResize => Button, TextView and all EditText is push up to above keyboard

Linh
  • 57,942
  • 23
  • 262
  • 279

9 Answers9

8

Won't work- there is no reliable API to detect when the keyboard is shown. You'll see "solutions" on this site, but they have false positives and negatives. But it seems like the best thing for you is to set the softInputMode to adjustPan. This will make the OS scroll the entire screen by the minimum amount needed to make the cursor visible above the keyboard. (the entire app going above the keyboard is due to the mode adjustResize).

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
7
  1. Tested on all Nexus mobile and Tablet devices. It works fine. I am using your layout xml code and have added only id's to views.

  2. I am using the below library in my production application and it is very promising. To achieve the same and add the below line in app gradle: 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:2.0.1' Here is the link for the same.

  3. Refer to the below gist for the rest of the code:Manifest code, Activity code, Activity layout code.

The above solution migh not work 20% of time as per my experience. For a few samsung devices, above code is not working as expected. If I have time will try to resolve it using Constraintlayout and adjustPan.

Anurag Singh
  • 6,140
  • 2
  • 31
  • 47
  • can u help how to pass context instead of activity it seems context not works other than passing direct activity name – Mithu Aug 06 '20 at 12:16
5

You must add android:windowSoftInputMode="adjustPan" in your Manifest and It will work like a Pro:

<activity android:name=".your_activity_name"
        android:windowSoftInputMode="adjustPan">
    ..............

</activity>
W4R10CK
  • 5,502
  • 2
  • 19
  • 30
3

Use a Relavtive Layout as parent with two Linear Layout as child and put the scrollview in first LinearLayout while the button with the textview in other one.

Use this code. Have tested it, will work as you expect.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <LinearLayout
        android:id="@+id/linear"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#ff0"
        >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            >

            <EditText
                android:layout_marginTop="30dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="EditText 1"

                />

            <EditText
                android:layout_marginTop="30dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="EditText 2"
                />

            <EditText
                android:layout_marginTop="30dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="EditText 3"
                />

            <EditText
                android:layout_marginTop="30dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="EditText 4"
                />

            <EditText
                android:layout_marginTop="30dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="EditText 5"
                android:inputType="textNoSuggestions"
                />

        </LinearLayout>

    </ScrollView>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_below="@id/linear">
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:text="Button"
            />
        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#000"
            android:text="I don't want to push this TextView and Button above keyboard"
            />
    </LinearLayout>
</RelativeLayout>
Darshan Miskin
  • 844
  • 14
  • 25
  • thank you for your answer, I have used your code but when keyboard show. I can not scroll all EditText – Linh Jan 19 '17 at 07:22
  • have tested it on two separate devices, works properly on both. check if there is any misplaced `android:windowSoftInputMode` in the manifest. – Darshan Miskin Jan 19 '17 at 10:47
  • With 5 EditText, maybe you can not find the problem. You can add 5 more EditText then test I have test on both mode adjustPan and adjustResize, both of the mode won't work – Linh Jan 20 '17 at 01:01
  • no, don't keep any `android:windowSoftInputMode` at all for the said activity in manifest. – Darshan Miskin Jan 20 '17 at 05:47
2

Please try to add this layout,

 <LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/activity_main"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical">
<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:background="#ff0"
    >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >

        <EditText
            android:layout_marginTop="30dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="EditText 1"

            />

        <EditText
            android:layout_marginTop="30dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="EditText 2"
            />

        <EditText
            android:layout_marginTop="30dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="EditText 3"
            />

        <EditText
            android:layout_marginTop="30dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="EditText 4"
            />

        <EditText
            android:layout_marginTop="30dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="EditText 5"
            android:inputType="textNoSuggestions"
            />

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:text="Button"
            />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#000"
            android:text="any text"
        />
    </LinearLayout>
  </ScrollView>


</LinearLayout>
rak
  • 108
  • 1
  • 12
  • thank you for your answer but when keyboard show, I don't want to push up the Button and TextView. with your solution. Button and TextView also push up – Linh Jan 11 '17 at 07:44
  • with code given in this answer, use `android:windowSoftInputMode="adjustPan"`. I think this will help. – Akhilesh Kumar Jan 18 '17 at 16:53
2

Give id to all editText,button and textview:-

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#ff0">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            >

            <EditText
                android:layout_marginTop="30dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="EditText 1"
                android:id="@+id/et1"
                />

            <EditText
                android:layout_marginTop="30dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="EditText 2"
                android:id="@+id/et2"/>

            <EditText
                android:layout_marginTop="30dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="EditText 3"
                android:id="@+id/et3"/>

            <EditText
                android:layout_marginTop="30dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="EditText 4"
                android:id="@+id/et4"/>

            <EditText
                android:layout_marginTop="30dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="EditText 5"
                android:inputType="textNoSuggestions"
                android:id="@+id/et5"/>

        </LinearLayout>

    </ScrollView>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="Button"
        android:id="@+id/btn"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#000"
        android:text="I don't want to push this TextView and Button to above keyboard when keyboard is shown. Just obly want to push the ScrollView that contain all EditText"
        android:id="@+id/tv"/>
</LinearLayout>

In your Manifest:-

android:windowSoftInputMode="adjustResize|stateHidden"

In your Activity:-

public class Main2Activity extends AppCompatActivity {
    EditText e1,e2,e3,e4,e5;
    Button button;
    TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        e1=(EditText)findViewById(R.id.et1);
        e2=(EditText)findViewById(R.id.et2);
        e3=(EditText)findViewById(R.id.et3);
        e4=(EditText)findViewById(R.id.et4);
        e5=(EditText)findViewById(R.id.et5);
        textView=(TextView)findViewById(R.id.tv);
        button=(Button)findViewById(R.id.btn);
        e1.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View view, boolean b) {
                hideKeyBoard();
            }
        });
        e2.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View view, boolean b) {
                hideKeyBoard();
            }
        });
        e3.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View view, boolean b) {
                hideKeyBoard();
            }
        });
        e4.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View view, boolean b) {
                hideKeyBoard();
            }
        });
        e5.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View view, boolean b) {
                hideKeyBoard();
            }
        });

    }
    private void hideKeyBoard(){
        final View activityRootView = findViewById(R.id.activity_main);
        activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
                if (heightDiff > dpToPx(Main2Activity.this, 200)) { // if more than 200 dp, it's probably a keyboard...
                    // ... do something here
                    button.setVisibility(View.GONE);
                    textView.setVisibility(View.GONE);
                }
                else {
                    button.setVisibility(View.VISIBLE);
                    textView.setVisibility(View.VISIBLE);
                }
            }
        });
    }
    public static float dpToPx(Context context, float valueInDp) {
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);
    }

}

Here i am checking whether keyboard is visible or not. And if it is visible then hiding the button and textview.

Nainal
  • 1,728
  • 14
  • 27
2

first change layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#ff0">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp"
                android:hint="EditText 1"

                />

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp"
                android:hint="EditText 2" />

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp"
                android:hint="EditText 3" />

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp"
                android:hint="EditText 4" />

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp"
                android:hint="EditText 5"
                android:inputType="textNoSuggestions" />

        </LinearLayout>

    </ScrollView>


    <RelativeLayout
        android:id="@+id/rlBtm"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <Button
            android:id="@+id/btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Button" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/btn"
            android:text="I don't want to push this TextView and Button to above keyboard when keyboard is shown. Just obly want to push the ScrollView that contain all EditText"
            android:textColor="#000" />

    </RelativeLayout>

</LinearLayout>

then add class

public class KeyboardUtil {

    public static void setKeyboardVisibilityListener(Activity activity, final KeyboardVisibilityListener keyboardVisibilityListener) {
        final View contentView = activity.findViewById(android.R.id.content);
        contentView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            private int mPreviousHeight;

            @Override
            public void onGlobalLayout() {
                int newHeight = contentView.getHeight();
                if (mPreviousHeight != 0) {
                    if (mPreviousHeight > newHeight) {
                        // Height decreased: keyboard was shown
                        keyboardVisibilityListener.onKeyboardVisibilityChanged(true);
                    } else if (mPreviousHeight < newHeight) {
                        // Height increased: keyboard was hidden
                        keyboardVisibilityListener.onKeyboardVisibilityChanged(false);
                    } else {
                        // No change
                    }
                }
                mPreviousHeight = newHeight;
            }
        });
    }
}

And from activities onCreate

KeyboardUtil.setKeyboardVisibilityListener(this, new KeyboardVisibilityListener() {
            @Override
            public void onKeyboardVisibilityChanged(boolean keyboardVisible) {
                rlBtm.setVisibility(keyboardVisible ? View.GONE : View.VISIBLE);
            }
        });

find id for rlBtm.

Pavya
  • 6,015
  • 4
  • 29
  • 42
1

you may use below code ( But in this case your button and your textview was end of the screen. else your may manage it with Linear layout too. if you want button and textview must be show then pls ask.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
    android:id="@+id/sw1"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:id="@+id/ll1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <EditText
            android:layout_width="match_parent"
            android:layout_height="70dp"
            android:layout_marginBottom="10dp"
            android:layout_marginTop="100dp"
            android:background="#ff009988"
            android:padding="10dp"
            android:textColor="#ffffff" />
        <EditText
            android:layout_width="match_parent"
            android:layout_height="70dp"
            android:layout_marginBottom="10dp"
            android:background="#ff009988"
            android:padding="10dp"
            android:textColor="#ffffff" />
 <RelativeLayout
    android:id="@+id/btmbar"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true">

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button2"
        android:text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, " />
</RelativeLayout>
    </LinearLayout>
</ScrollView>

Arpan24x7
  • 648
  • 5
  • 24
0

With the new feature of WindowInsetsCompat which help detecting keyboard visibility easily (I follow answer here https://stackoverflow.com/a/63517673/5381331).
Instead of using windowSoftInputMode=adjustPan for less complex like before, now I can solve this problem by combine windowSoftInputMode=adjustResize with WindowInsetsCompat

ViewCompat.setOnApplyWindowInsetsListener(root) { v, insets ->
    val isKeyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
    
    if (isKeyboardVisible) {
        // Hide some view when keyboard visible
    } else {
        // Show it again here
    }
}

AndroidManifest

<activity android:name=".activity_name"
        android:windowSoftInputMode="adjustResize"> // all content will push to above keyboard then we able to scroll to see whole content
   
</activity>
Linh
  • 57,942
  • 23
  • 262
  • 279