How to let EditText take as much space it needs, to be scrollable together with content above it? How to let EditText take as much space it needs, to be scrollable together with content above it? android android

How to let EditText take as much space it needs, to be scrollable together with content above it?


I got some workaround for this, by wrapping the bottom EditText with a layout that will grant it focus.

Doesn't require much code at all

activity_main.xml

<android.support.v4.widget.NestedScrollView    android:id="@+id/nestedScrollView" xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true">    <LinearLayout        android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical">        <EditText            android:id="@+id/titleEditText" android:layout_width="match_parent" android:layout_height="wrap_content"            android:ellipsize="end" android:hint="title" android:imeOptions="actionNext|flagNoExtractUi"            android:inputType="text|textAutoCorrect|textCapSentences" android:maxLines="1"            android:nextFocusDown="@id/contentEditText" android:nextFocusForward="@id/contentEditText"            android:scrollHorizontally="true" android:textColor="#2a2f3b" android:textColorHint="#a3a3a3"            android:textSize="21sp"/>        <android.support.constraint.ConstraintLayout            android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent"            android:background="@android:drawable/alert_light_frame" android:clickable="true" android:focusable="false">            <EditText                android:id="@+id/contentEditText" android:layout_width="match_parent"                android:layout_height="wrap_content" android:background="@null" android:gravity="top"                android:hint="content" android:imeOptions="actionDone|flagNoEnterAction|flagNoExtractUi"                android:inputType="textMultiLine|textAutoCorrect|textCapSentences" android:textSize="18sp"/>        </android.support.constraint.ConstraintLayout>    </LinearLayout></android.support.v4.widget.NestedScrollView>

MainActivity.kt

class MainActivity : AppCompatActivity() {    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)        container.setOnClickListener {            contentEditText.requestFocus()            contentEditText.setSelection(contentEditText.length())        }        contentEditText.setOnFocusChangeListener { view, hasFocus ->            if (hasFocus) {                nestedScrollView.scrollTo(0, 0)            }        }    }}

manifest

<manifest package="com.example.user.myapplication" xmlns:android="http://schemas.android.com/apk/res/android">    <application        android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name"        android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme">        <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>    </application></manifest>


You should be able to achieve what you want by calculating the minLines based on the height of the screen. See the example activity and layout below.

You'll need to type quite a bit of text to use up the minimum lines and grow beyond the height of the screen to start the scrolling behavior, but you can circumvent this by adding a few constant lines to the minLines calculation

public class ScrollingActivity extends AppCompatActivity{    EditText editText2;    @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_scrolling);        editText2 = findViewById(R.id.editText2);        int minHeight = getResources().getDisplayMetrics().heightPixels - editText2.getTop();        float lineHeight = editText2.getPaint().getFontMetrics().bottom - editText2.getPaint().getFontMetrics().top;        int minLines = (int)(minHeight/lineHeight);        editText2.setMinLines(minLines);    }}

Here is the layout

<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout    android:id="@+id/parentLayout"    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"    tools:context="com.my.package.ScrollingActivity">    <ScrollView        android:layout_width="match_parent"        android:layout_height="match_parent"        android:background="#000000">        <android.support.constraint.ConstraintLayout            android:id="@+id/scrollingLayout"            android:layout_width="match_parent"            android:layout_height="wrap_content">            <EditText                android:id="@+id/editText1"                android:layout_margin="15dp"                android:layout_width="match_parent"                android:layout_height="wrap_content"                app:layout_constraintTop_toTopOf="parent"                android:background="#FFFFFF"/>            <EditText                android:id="@+id/editText2"                android:layout_width="match_parent"                android:layout_height="wrap_content"                app:layout_constraintTop_toBottomOf="@id/editText1"                app:layout_constraintBottom_toBottomOf="parent"                android:layout_margin="15dp"                android:background="#FFFFFF"/>        </android.support.constraint.ConstraintLayout>    </ScrollView></android.support.constraint.ConstraintLayout>

EDIT

I recreated your solution and you can correct the focus issue by setting this listener to your EditText. It works by overriding the scroll action when the Edit Text gets the focus, to only scroll enough to make the cursor visible.

contentEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {    @Override    public void onFocusChange(View view, boolean hasFocus) {        if(hasFocus){            nestedScrollView.scrollTo(0, 0);        }    }});

EDIT 2

I've updated my answer to reflect the changes with the new bounty, this should be pretty close to what you need, if I've understood the question properly.

public class ScrollingActivity extends AppCompatActivity{    ConstraintLayout parentLayout;    EditText contentEditText;    NestedScrollView nestedScrollView;    LinearLayout autoHideLayout;    boolean preventScroll = true;    @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_scrolling);        contentEditText = findViewById(R.id.contentEditText);        nestedScrollView = findViewById(R.id.nestedScrollView);        autoHideLayout = findViewById(R.id.autoHideLayout);        parentLayout = findViewById(R.id.parentLayout);        nestedScrollView.setOverScrollMode(View.OVER_SCROLL_NEVER);        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);        parentLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {            @Override            public void onGlobalLayout() {                int minHeight = autoHideLayout.getTop() - contentEditText.getTop();                float lineHeight = contentEditText.getPaint().getFontMetrics().bottom - contentEditText.getPaint().getFontMetrics().top;                int minLines = (int)(minHeight/lineHeight);                if(minLines != contentEditText.getMinLines()){                    contentEditText.setMinLines(minLines);                }            }        });        contentEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {            @Override            public void onFocusChange(View view, boolean hasFocus) {                ViewGroup.LayoutParams layoutParams = autoHideLayout.getLayoutParams();                if(hasFocus){                    nestedScrollView.scrollTo(0,0);                    layoutParams.height = ConstraintLayout.LayoutParams.WRAP_CONTENT;                } else{                    layoutParams.height = 0;                }                autoHideLayout.setLayoutParams(layoutParams);            }        });    }}

Here is the new layout

    <android.support.constraint.ConstraintLayout    android:id="@+id/parentLayout"    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:orientation="vertical"    android:animateLayoutChanges="true">    <android.support.v4.widget.NestedScrollView        android:id="@+id/nestedScrollView"        android:layout_width="0dp"        android:layout_height="0dp"        android:focusable="false"        android:focusableInTouchMode="false"        app:layout_constraintLeft_toLeftOf="parent"        app:layout_constraintRight_toRightOf="parent"        app:layout_constraintTop_toTopOf="parent"        app:layout_constraintBottom_toTopOf="@id/autoHideLayout"        >        <LinearLayout            android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">            <EditText                android:id="@+id/titleEditText" android:layout_width="match_parent" android:layout_height="wrap_content"                android:ellipsize="end" android:hint="title" android:imeOptions="actionNext|flagNoExtractUi"                android:inputType="text|textAutoCorrect|textCapSentences" android:maxLines="1"                android:nextFocusDown="@id/contentEditText" android:nextFocusForward="@id/contentEditText"                android:scrollHorizontally="true" android:textColor="#2a2f3b" android:textColorHint="#a3a3a3"                android:background="@android:drawable/alert_light_frame"                android:textSize="21sp"/>            <EditText                android:id="@+id/contentEditText" android:layout_width="match_parent"                android:layout_height="wrap_content" android:background="@android:drawable/alert_light_frame" android:gravity="top"                android:hint="content" android:imeOptions="actionDone|flagNoEnterAction|flagNoExtractUi"                android:inputType="textMultiLine|textAutoCorrect|textCapSentences" android:textSize="18sp"/>        </LinearLayout>    </android.support.v4.widget.NestedScrollView>    <LinearLayout        android:id="@+id/autoHideLayout" android:layout_width="0dp" android:layout_height="0dp"        app:layout_constraintLeft_toLeftOf="parent"        app:layout_constraintRight_toRightOf="parent"        android:orientation="horizontal" android:visibility="visible" tools:visibility="visible"        app:layout_constraintBottom_toBottomOf="parent">        <Button            android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="button"/>        <Button            android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="button2"/>    </LinearLayout></android.support.constraint.ConstraintLayout>


Your expected result can be achieved by changing the layout.xml and MainActivity.Change layout_height and adding layout_weight for ConstraintLayout as follows:

    <?xml version="1.0" encoding="utf-8"?><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:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <View        android:layout_width="0dp"        android:layout_height="0dp"        android:focusable="true"        android:focusableInTouchMode="true" />    <android.support.v4.widget.NestedScrollView        android:id="@+id/nestedScrollView"        android:layout_width="match_parent"        android:layout_height="0px"        android:layout_weight="1"        android:fillViewport="true">        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="vertical">            <EditText                android:id="@+id/titleEditText"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:ellipsize="end"                android:hint="title"                android:imeOptions="actionNext|flagNoExtractUi"                android:inputType="text|textAutoCorrect|textCapSentences"                android:maxLines="1"                android:nextFocusDown="@id/contentEditText"                android:nextFocusForward="@id/contentEditText"                android:scrollHorizontally="true"                android:textColor="#2a2f3b"                android:textColorHint="#a3a3a3"                android:textSize="21sp" />            <android.support.constraint.ConstraintLayout                android:id="@+id/container"                android:layout_width="match_parent"                android:layout_height="0dp"                android:layout_weight="1"                android:background="@android:drawable/alert_light_frame"                android:clickable="true"                android:focusable="false"                android:nestedScrollingEnabled="false"><!-- -->                <EditText                    android:id="@+id/contentEditText"                    android:layout_width="match_parent"                    android:layout_height="wrap_content"                    android:background="@null"                    android:gravity="top"                    android:hint="content"                    android:imeOptions="actionDone|flagNoEnterAction|flagNoExtractUi"                    android:inputType="textMultiLine|textAutoCorrect|textCapSentences"                    android:textSize="18sp" />            </android.support.constraint.ConstraintLayout>        </LinearLayout>    </android.support.v4.widget.NestedScrollView>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:animateLayoutChanges="true"        android:orientation="vertical">        <LinearLayout            android:id="@+id/autoHideLayout"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="horizontal"            android:visibility="visible"            tools:visibility="visible">            <Button                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="button" />            <Button                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="button2" />        </LinearLayout>    </LinearLayout></LinearLayout>

Manifest.xml is:

<application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:roundIcon="@mipmap/ic_launcher_round"        android:supportsRtl="true"        android:theme="@style/AppTheme">        <activity android:name=".MainActivity"            android:windowSoftInputMode="adjustResize">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.DEFAULT" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity></application>

Record the current value of scrollX & scroll Y for NestedScrollView and adjust NestedScrollView as follows:

MainActivity.java

public class MainActivity extends AppCompatActivity {   private int scrollX;   private int scrollY;   @Override   protected void onCreate(Bundle savedInstanceState) {       super.onCreate(savedInstanceState);       setContentView(R.layout.activity_main);       final EditText editText = findViewById(R.id.contentEditText);       final LinearLayout autoHideLayout = findViewById(R.id.autoHideLayout);       ConstraintLayout container = findViewById(R.id.container);       container.setOnClickListener(new View.OnClickListener() {           @Override           public void onClick(View view) {               autoHideLayout.setVisibility(View.VISIBLE);               editText.requestFocus();               editText.setSelection(editText.length());           }       });       final NestedScrollView nestedScrollView = findViewById(R.id.nestedScrollView);       editText.setOnTouchListener(new View.OnTouchListener() {           @Override           public boolean onTouch(View v, MotionEvent event) {               scrollX = nestedScrollView.getScrollX();               scrollY = nestedScrollView.getScrollY();               autoHideLayout.setVisibility(View.VISIBLE);               return false;           }       });       editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {           @Override           public void onFocusChange(View v, boolean hasFocus) {               if (hasFocus)                   nestedScrollView.scrollTo(scrollX, scrollY);               if (!hasFocus) {                   autoHideLayout.setVisibility(View.GONE);               }           }       });   }}

It didn't scroll when it was not necessary. See the screenshot:screen shot