Ben
Ben

Reputation: 1839

Adding Margin between EditText and keyboard

So this question has been asked few times already in here in the past years and non of the solutions worked for me.

The problem is that when I use AdjustPan to move the softkeyboard it hides part of the EditText as follows:

enter image description here

The solutions I tried are:

Solution 1 (2011)

Solution 2 (2014)

Solution 3 (2013)

Most of the answers include using AdjustPan/AdjustResize so I will just say that none of them give the desired solution (Showing the whole EditText when keyboard is opened).

I was thinking maybe in 2019 there is a working solution for this problem.

The xml for this layout is:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorWhite"
    tools:context=".ChatActivity">


    <androidx.appcompat.widget.ActionMenuView
        android:id="@+id/actionbar"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="@color/colorGrayBox"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent="0.1"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">
    </androidx.appcompat.widget.ActionMenuView>

    <TextView
        android:id="@+id/tv_This"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="24dp"
        android:layout_marginTop="16dp"
        android:fontFamily="@font/open_sans"
        android:text="@string/ActivityChat_This"
        android:textSize="12sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/actionbar" />

    <View
        android:id="@+id/v_Line"
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:layout_marginLeft="24dp"
        android:layout_marginTop="16dp"
        android:layout_marginRight="24dp"
        android:background="@color/colorLightGray"
        app:layout_constraintTop_toBottomOf="@+id/tv_This" />

    <androidx.cardview.widget.CardView
        android:id="@+id/imagecard"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_marginStart="16dp"
        app:cardCornerRadius="20dp"
        app:layout_constraintBottom_toBottomOf="@+id/actionbar"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageButton
            android:id="@+id/ivPersonPic"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:background="@null" />

    </androidx.cardview.widget.CardView>

    <TextView
        android:id="@+id/username"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:fontFamily="@font/assistant_bold"
        android:textColor="@color/colorLightPurple"
        android:textSize="18sp"
        app:layout_constraintBottom_toBottomOf="@+id/actionbar"
        app:layout_constraintStart_toEndOf="@+id/imagecard"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_Messages"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginTop="8dp"
        app:layout_constraintBottom_toTopOf="@+id/constraint2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/v_Line"/>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/constraint2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
        app:layout_constraintHeight_percent="0.1">

        <EditText
            android:id="@+id/et_Message"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginStart="12dp"
            android:layout_marginTop="8dp"
            android:layout_marginBottom="8dp"
            android:background="@drawable/et_rounded"
            android:fontFamily="@font/assistant"
            android:gravity="center_vertical"
            android:hint="@string/ActivityChat_Type"
            android:inputType="textMultiLine|textPersonName"
            android:paddingEnd="32dp"
            android:paddingStart="32dp"
            android:textSize="16sp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintWidth_percent="0.85" />

        <ImageButton
            android:id="@+id/ib_Send"
            style="?android:borderlessButtonStyle"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginBottom="8dp"
            android:adjustViewBounds="true"
            android:src="@drawable/ic_chats_send"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintWidth_percent="0.1" />

    </androidx.constraintlayout.widget.ConstraintLayout>

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:itemBackground="@color/colorWhite"
        app:itemIconTint="@drawable/btm_nav"
        app:itemTextColor="@drawable/btm_nav"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent="0.08"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/menu_btm_nav" />

</androidx.constraintlayout.widget.ConstraintLayout>

Upvotes: 10

Views: 5382

Answers (10)

Jimmy Hendrix
Jimmy Hendrix

Reputation: 21

Add padding bottom to TextInputLayout

Upvotes: 0

nibbana
nibbana

Reputation: 729

Replace the EditText view with a TextInputEditText view and simply add padding to its bottom, like:

<com.google.android.material.textfield.TextInputLayout
    ...
    <com.google.android.material.textfield.TextInputEditText
        android:paddingBottom="30dp"
        ...
        android:textSize="15sp"
        android:hint="@string/txt_hint_add_comment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
    />
</com.google.android.material.textfield.TextInputLayout>

Upvotes: 0

Osama Remlawi
Osama Remlawi

Reputation: 2990

There is one trick to do it:

1- put the EditText inside a CardView

2- style the CardView to looks like a TextEdit

3- add these properties to the EditText

android:paddingBottom="15dp"
android:paddingTop="15dp"
android:background="@android:color/transparent"

Upvotes: -1

Kevin van Mierlo
Kevin van Mierlo

Reputation: 9814

I had a lot of problems with the keyboard myself, but I prefer using android:windowSoftInputMode="adjustResize" so you can handle the changes yourself. You should add a windowInsetsListener to your root view and if you don't have a transparent navigation bar the systemWindowInsetBottom should only be the keyboard. So you can just add padding to the container you're interested in. This is an example I use:

rootContainer.setOnApplyWindowInsetsListener { view, windowInsets ->
    var containerPadding = 0
    if (windowInsets.systemWindowInsetBottom > 0) {
        val bottomBarHeight = bottomBar.bottom - bottomBar.top
        containerPadding = windowInsets.systemWindowInsetBottom - bottomBarHeight
    }

    if (containerPadding < 0) {
        containerPadding = 0
    }

    contentView.bottomPadding = containerPadding

    return@setOnApplyWindowInsetsListener windowInsets.replaceSystemWindowInsets(windowInsets.systemWindowInsetLeft, windowInsets.systemWindowInsetTop, windowInsets.systemWindowInsetRight, 0)
}

This way you can move the container above the bottomBar up (which has your EditText in it).

For me this was the best option I've found so far. Most options rely on GlobalLayoutListeners and see how much it changes, but this is far more reliable.

Upvotes: 0

Salar Arabpour
Salar Arabpour

Reputation: 520

i had exact same issue and solved this problem forever with a 'easy implementation' and 'tested' method..the idea is that when the edit text gains focus scroll view auto scrolls to bottom.let me show you how...

first you should use nested scroll view as parent of main layout

second add a library to find out when keyboard opens

implementation 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:2.0.1'

third add this class to your project

public class KeyboardUtil {
private View decorView;
private View contentView;
//a small helper to allow showing the editText focus
ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        Rect r = new Rect();
        //r will be populated with the coordinates of your view that area still visible.
        decorView.getWindowVisibleDisplayFrame(r);

        //get screen height and calculate the difference with the useable area from the r
        int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
        int diff = height - r.bottom;

        //if it could be a keyboard add the padding to the view
        if (diff != 0) {
            // if the use-able screen height differs from the total screen height we assume that it shows a keyboard now
            //check if the padding is 0 (if yes set the padding for the keyboard)
            if (contentView.getPaddingBottom() != diff) {
                //set the padding of the contentView for the keyboard
                contentView.setPadding(0, 0, 0, diff);
            }
        } else {
            //check if the padding is != 0 (if yes reset the padding)
            if (contentView.getPaddingBottom() != 0) {
                //reset the padding of the contentView
                contentView.setPadding(0, 0, 0, 0);
            }
        }
    }
};

public KeyboardUtil(Activity act, View contentView) {
    this.decorView = act.getWindow().getDecorView();
    this.contentView = contentView;

    //only required on newer android versions. it was working on API level 19
    if (Build.VERSION.SDK_INT >= 19) {
        decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
    }
}

/**
 * Helper to hide the keyboard
 *
 * @param act
 */
public static void hideKeyboard(Activity act) {
    if (act != null && act.getCurrentFocus() != null) {
        InputMethodManager inputMethodManager = (InputMethodManager) act.getSystemService(Activity.INPUT_METHOD_SERVICE);
        inputMethodManager.hideSoftInputFromWindow(act.getCurrentFocus().getWindowToken(), 0);
    }
}

public void enable() {
    if (Build.VERSION.SDK_INT >= 19) {
        decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
    }
}

public void disable() {
    if (Build.VERSION.SDK_INT >= 19) {
        decorView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
    }
}

public static void adjustResize(Activity activity, final NestedScrollView scrollView) {
    KeyboardVisibilityEvent.setEventListener(
            activity,
            new KeyboardVisibilityEventListener() {
                @Override
                public void onVisibilityChanged(boolean isOpen) {
                    // some code depending on keyboard visiblity status
                    if (isOpen) {

                        //Scroll view scrolls bottom without changing focus
                        View lastChild = scrollView.getChildAt(scrollView.getChildCount() - 1);
                        int bottom = lastChild.getBottom() + scrollView.getPaddingBottom();
                        int sy = scrollView.getScrollY();
                        int sh = scrollView.getHeight();
                        int delta = bottom - (sy + sh);

                        scrollView.smoothScrollBy(0, delta);


                    } else {
                        //Toast.makeText(context, "keyboard is close", Toast.LENGTH_SHORT).show();

                    }
                }
            });} }

then use it in your activity like

new KeyboardUtil(activity,nestedScrollView);
KeyboardUtil.adjustResize(activity,nestedScrollView);

and if you are in fragment you can pass below code as activity:

(AppCompatActivity)context

Upvotes: -1

niceumang
niceumang

Reputation: 1432

First add ScrollView into your XML and add below lines into AndroidManiFest.xml in your activity tag where you use this search EditText.

android:windowSoftInputMode="stateAlwaysHidden|adjustResize|adjustPan|adjustResize

Upvotes: 2

ankitsinh corepix
ankitsinh corepix

Reputation: 89

In your Layout file add the following line in the Constraint tag.

android:isScrollContainer="true"

Upvotes: 0

Jamil Hasnine Tamim
Jamil Hasnine Tamim

Reputation: 4448

Try this, add this code in your AndroidManifest.xml activity

android:windowSoftInputMode="adjustPan" 

Add the following into your root Layout at the xml file

android:fitsSystemWindows="true"

Upvotes: 5

hardartcore
hardartcore

Reputation: 17037

First of all I think your layout should be improved, there is no need to use two ConstraintLayout in a single xml file and the second one is a child of the first / main one. The idea behind this view is to flatten your whole layout, so as first step I think you should get rid off the second ConstraintLayout.

I've create a simple layout which looks a little like yours in order to test if my implementation will work, so here is the layout file:

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <View
        android:layout_width="0dip"
        android:layout_height="0dip"
        app:layout_constraintBottom_toTopOf="@+id/edit_text"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/edit_text"
        android:layout_width="0dip"
        android:layout_height="wrap_content"
        android:layout_marginStart="12dp"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        android:background="@drawable/rounded"
        android:gravity="center_vertical"
        android:hint="Text"
        android:importantForAutofill="no"
        android:inputType="textMultiLine|textPersonName"
        android:paddingStart="32dip"
        android:paddingEnd="32dip"
        android:textSize="16sp"
        app:layout_constraintBottom_toTopOf="@id/bottom_navigation_view"
        app:layout_constraintEnd_toStartOf="@+id/btn_send"
        app:layout_constraintStart_toStartOf="parent"
        tools:ignore="HardcodedText" />

    <Button
        android:id="@+id/btn_send"
        android:layout_width="0dip"
        android:layout_height="wrap_content"
        android:layout_marginStart="12dp"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        android:text="SEND"
        app:layout_constraintBottom_toTopOf="@id/bottom_navigation_view"
        app:layout_constraintEnd_toEndOf="parent"
        tools:ignore="HardcodedText" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="#c5c6c7"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />


</androidx.constraintlayout.widget.ConstraintLayout>

The structure looks similar to yours, at least the part with the BottomNavigatioView, EditText and the Button. Adding android:windowSoftInputMode="adjustPan" to the Activity which holds this layout will give this result (tested on a few devices) :

screenshot 01 screenshot 02

Upvotes: 0

Sagar
Sagar

Reputation: 554

 <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/constraint2"

Add padding bottom in ConstraintLayout like android:paddingBottom="8dp"

Remove android:layout_marginBottom="8dp" from Edittext and Imageview i.e. android:id="@+id/et_Message" and android:id="@+id/ib_Send"

Then rerun again

Upvotes: -1

Related Questions