Как позволить EditText занимать столько места, сколько ему нужно, чтобы его можно было прокручивать вместе с содержимым над ним?

Задний план

У меня есть макет, в котором есть несколько представлений вверху, которые должны прокручиваться вместе с EditText под ними.

EditText занимает остальную часть пространства, столько места, сколько ему нужно.

Вот пример макета POC, который демонстрирует это (здесь использовались только 2 EditText):

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

        <EditText
            android:id="@+id/contentEditText" android:layout_width="match_parent" android:layout_height="match_parent"
            android:gravity="top" android:hint="content" android:background="@android:drawable/alert_light_frame"
            android:imeOptions="actionDone|flagNoEnterAction|flagNoExtractUi" android:textSize="18sp"
            android:inputType="textMultiLine|textAutoCorrect|textCapSentences"/>

    </LinearLayout>

</android.support.v4.widget.NestedScrollView>

Я установил фоновую рамку, чтобы иметь визуальную индикацию размера EditText.

Проблема

Я нашел так много решений того, что я написал, но ни одно из них на самом деле не справляется с прокруткой.

То, что я всегда вижу, это как минимум одна из этих проблем:

  1. Невозможно прокрутить всю страницу (только EditText может прокручиваться, чего я пытаюсь избежать), поэтому больше не могу получить доступ к представлениям вверху.
  2. Когда я ввожу текст, курсор может выйти за пределы видимой области
  3. По мере того, как я набираю все больше и больше строк, он не прокручивает всю страницу. Только в самом EditText.

Что я пробовал

Я пробовал эти решения:

  1. Все из здесь, здесь, здесь, здесь. Может и больше, но я не следил...
  2. Я пробовал различные значения windowSoftInputMode в манифесте и пытался установить isNestedScrollingEnabled в NestedScrollView.
  3. Пробовал различные конфигурации в XML, чтобы позволить EditText занимать столько места, сколько ему нужно, чтобы предотвратить его прокрутку внутри него.

Вопрос

Как я могу сделать так, чтобы нижний EditText занимал столько места, сколько ему нужно, и при этом иметь возможность прокручивать весь NestedScrollView без проблем с редактированием?


РЕДАКТИРОВАТЬ: поскольку исходное приложение немного сложнее, имея некоторые представления внизу (внутри того, что похоже на панель инструментов), которые автоматически скрываются, когда вы не находитесь в фокусе нижнего EditText , это сделало ответ, который я нашел не работать.

Кроме того, я случайно назначил награду за неправильный ответ, так что вот новая награда за более сложный POC. Вопрос остается прежним. NestedScrollView должен оставаться на том же месте, без прокрутки при фокусировании на нижнем EditText.

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

    <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="gone" 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>


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 ->
            autoHideLayout.visibility = if (hasFocus) View.VISIBLE else View.GONE
            if (hasFocus)
                nestedScrollView.scrollTo(0, 0)
        }
    }
}

person android developer    schedule 21.03.2018    source источник
comment
Вы хотите прокручивать весь экран, а не просто редактировать прокрутку текста?   -  person Vivek Mishra    schedule 23.03.2018
comment
вы пытаетесь достичь этого youtu.be/jnO1KQHo3gU   -  person DimDim    schedule 23.03.2018
comment
@ВивекМишра Да. Точно   -  person android developer    schedule 23.03.2018
comment
@DimDim Кажется правильным. Предположим, у него нет странных проблем, это именно то, что мне нужно.   -  person android developer    schedule 23.03.2018
comment
Когда вы говорите The EditText takes the rest of the space, as much space as it needs, вы имеете в виду, что он должен заполнять экран, а затем увеличиваться, если это необходимо? Или вы просто имеете в виду, что ему нужно позволить расти по мере необходимости, даже если он начинается меньше, чем заполняет экран?   -  person Ben P.    schedule 27.03.2018
comment
Это должно быть похоже на приложение для редактирования электронной почты или заметок. Вверху есть несколько представлений, а EditText занимает остальную часть пространства и увеличивается по мере необходимости. Вы можете щелкнуть в любом месте его пустого места, чтобы придать ему фокус.   -  person android developer    schedule 27.03.2018
comment
Для меня это происходит только в том случае, если видна SoftKeyboard. В противном случае он работает нормально. У вас тот же случай? android:windowSoftInputMode="adjustResize" установка этого в манифесте решила проблему.   -  person Sagar    schedule 28.03.2018
comment
можешь выложить картинку с вопросом? чтобы было понятнее...   -  person RBK    schedule 13.04.2018
comment
@RBK Изображение чего? Это всего лишь один EditText под другим...   -  person android developer    schedule 13.04.2018
comment
@Sagar Все еще имеет эту проблему. Если я помещу несколько строк во второй EditText и сосредоточусь на нем с первого в его первой строке, он все равно будет прокручиваться.   -  person android developer    schedule 13.04.2018
comment
Немного непонятно. Вы хотите, чтобы он прокручивался или не прокручивался?   -  person Sagar    schedule 14.04.2018
comment
@Sagar В этом случае не следует прокручивать, потому что в этом нет необходимости, так как места достаточно. Смотрите видео: uploadfiles.io/vgbac   -  person android developer    schedule 14.04.2018
comment
@androiddeveloper Если я правильно понимаю, вы хотите, чтобы он прокручивался только в том случае, если есть необходимость в прокрутке. В противном случае следует максимально избегать прокрутки. Это правильно?   -  person Sagar    schedule 14.04.2018


Ответы (4)


Ожидаемого результата можно добиться, изменив layout.xml и MainActivity. Измените layout_height и добавьте layout_weight вместо ConstraintLayout следующим образом:

    <?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>

Манифест.xml:

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

Запишите текущее значение scrollX и прокрутите Y для NestedScrollView и отрегулируйте NestedScrollView следующим образом:

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);
               }
           }
       });
   }
}

Он не прокручивался, когда в этом не было необходимости. Смотрите скриншот: снимок экрана

person Sagar    schedule 14.04.2018
comment
Я все еще вижу ту же проблему. Наличие нескольких строк во втором EditText, а затем фокусировка на первой строке вызовет прокрутку. Если вы тоже не редактировали код, это, к сожалению, все еще не решение проблемы. Вот видео, показывающее проблему: ufile.io/tzz09 - person android developer; 14.04.2018
comment
Вы удалили важную часть моего кода для автоматического отображения и скрытия autoHideLayout. Также вы удалили часть возможности щелкнуть по всему пространству для EditText. Восстановив этот код, он все еще имеет ту же проблему. Кстати, я думаю, вы имеете в виду MainActivity.java . - person android developer; 15.04.2018
comment
Я обновил ответ. Вы можете проверить сейчас. извините за отсутствие подробностей - person Sagar; 16.04.2018
comment
Вы все же убрали часть кода нажатия на контейнер. И проблема все еще существует: ufile.io/ilxyq, просто прокрутите немного, и вы заметите, что он прыгает, когда сосредоточившись на втором EditText. - person android developer; 16.04.2018
comment
Вы можете добавить его. Я забыл вставить код. Для меня это довольно гладко на моем эмуляторе под управлением 8.0. Какую версию ОС вы используете? Я буду тестировать на нем и обновлять соответственно - person Sagar; 16.04.2018
comment
Встречается на Android P, Android 6.0.1 и Android 4.4. Пробовал и на эмуляторе. - person android developer; 16.04.2018
comment
Обновил код. Я протестировал вариант использования, который вы пытаетесь реализовать в видео на Samsung Galaxy A5. Это работает, как и ожидалось для меня. - person Sagar; 17.04.2018
comment
Думаю, на этот раз у тебя получилось. К сожалению, награда уже была автоматически предоставлена ​​(вам), поэтому я не могу ее предоставить. Единственное, чего я не заметил в вашем коде (и в моем тоже), это принудительное отображение клавиатуры при нажатии на контейнер. Но это легко добавить :((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(InputMethodManager.SHOW_FORCED, 0) . Все, что я могу сделать, это принять ответ и поставить за него +1, что я и делаю сейчас. - person android developer; 17.04.2018
comment
@androiddeveloper Полезно знать. Да, и, к сожалению, я не могу получить всю награду. Но рад, что это было полезно для вас. Спасибо за ответ на сообщение. - person Sagar; 17.04.2018

У меня есть обходной путь для этого, обернув нижний EditText макетом, который предоставит ему фокус.

вообще не требует много кода

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 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>
person android developer    schedule 25.03.2018
comment
@DaveS Ваш обходной путь для моего решения, похоже, не работает. Смотрите видео здесь: ufile.io/vgbac. Кроме того, я думаю, что даже то, что я написал, не всегда работает хорошо. Иногда он доходит до конца EditText, даже если я щелкнул в нем определенную точку. Я уберу свой ответ, потому что он недостаточно хорош, и обновлю, чтобы показать, что у него тоже есть эта проблема. - person android developer; 27.03.2018
comment
Что не так с поведением слушателя? Он не должен заметно прокручиваться, если вы не находитесь за нижней частью экрана, таким образом, текст заголовка не будет скрыт, если он не нужен, как вы просили. - person Dave S; 27.03.2018
comment
@DaveS Он вообще не должен прокручиваться, если я нахожусь в верхнем ряду. Текст заголовка скрывается, но не полностью. - person android developer; 27.03.2018
comment
@DaveS В большинстве случаев из-за этого клавиатура исчезает, когда я фокусируюсь на нижнем тексте редактирования. - person android developer; 29.03.2018
comment
@DaveS Однако удаление той части, которую я показываю на клавиатуре, исправляет это. Так что я дам вам награду и изменю свой ответ, чтобы не было проблем. - person android developer; 29.03.2018
comment
Озадаченный, вы используете MainActivity.kt в своем ответе, но не используете тег kotlin в своем вопросе. - person Jon Goodwin; 30.03.2018
comment
@DaveS Теперь у него есть 2 проблемы: когда много строк, он много прокручивается. Когда их мало, он ведет себя прыгающе (немного прокручивается в одном направлении, а затем в противоположном). - person android developer; 30.03.2018
comment
Хорошо, я исправил проблему с minLines, повторяющимися вычислениями, и это проясняет поведение прыжков. Не знаю, в чем еще проблема, но попробуйте. - person Dave S; 30.03.2018
comment
@DaveS Обе проблемы все еще существуют. Вот видео: ufile.io/83ubo. Прыжки в начале и прокрутка в остальных. - person android developer; 30.03.2018
comment
У меня нет проблемы с прыжками без строки заголовка, а прокрутка в фокусе выглядит так, как будто для отключения требуется настраиваемый вид прокрутки. Лично я считаю, что такое поведение соответствует пользовательскому опыту и не стоит исправлять, но у меня есть несколько вещей, которые я могу попробовать завтра. - person Dave S; 30.03.2018
comment
Я не смог исправить это со слушателями. Я думаю, что для этого потребуется специальный вид прокрутки, и он становится немного большим и сложным для этого вопроса. - person Dave S; 06.04.2018

Вы должны быть в состоянии достичь того, чего хотите, рассчитав minLines на основе высоты экрана. См. пример действия и макета ниже.

Вам нужно будет ввести довольно много текста, чтобы использовать минимальное количество строк и выйти за пределы высоты экрана, чтобы начать поведение прокрутки, но вы можете обойти это, добавив несколько постоянных строк в вычисление minLines

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);
    }
}

Вот макет

<?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>

ИЗМЕНИТЬ

Я воссоздал ваше решение, и вы можете исправить проблему с фокусом, установив этот прослушиватель в свой EditText. Он работает, переопределяя действие прокрутки, когда Edit Text получает фокус, чтобы прокручивать только достаточно, чтобы сделать курсор видимым.

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

ИЗМЕНИТЬ 2

Я обновил свой ответ, чтобы отразить изменения с новой наградой, это должно быть довольно близко к тому, что вам нужно, если я правильно понял вопрос.

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);
            }
        });
    }
}

Вот новый макет

    <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>
person Dave S    schedule 24.03.2018
comment
Всякий раз, когда я сосредотачиваюсь на нижнем EditText, он также прокручивается, скрывая верхний (и другие виды, если я их добавляю), хотя места достаточно. См. здесь: ufile.io/i02oe. Я также не хочу, чтобы нижний EditText занимал гораздо больше места, чем ему нужно. - person android developer; 25.03.2018
comment
Итак, чтобы уточнить, вы не хотите, чтобы текст редактирования заполнял оставшееся пространство? Вы хотите, чтобы он занимал столько места, сколько ему нужно? (Обернуть содержимое) - person Dave S; 25.03.2018
comment
Проблема с фокусом должна быть решена с помощью чего-то вроде этого. В понедельник попробую добавить. stackoverflow.com/a/6486348/2680506 - person Dave S; 25.03.2018
comment
Я не хочу, чтобы это занимало слишком много места. Оставшееся можно взять, но больше нужно, только если в нем действительно есть контент, требующий большего количества строк. Фон для него я поставил не просто так - чтобы были видны его края (в обычном приложении у меня его нет). Когда клавиатура не отображается, она не должна показывать, что я могу прокручивать, потому что еще не было введено ни одного символа. По поводу решения, которое было предложено для фокуса, оно не сработало (пробовал на обоих EditTexts). - person android developer; 25.03.2018
comment
Просто попробуйте макет, который я создал. Ты увидишь. Нижний EditText занимает оставшееся место. Не более того. - person android developer; 25.03.2018
comment
Match parent — это неправильный атрибут, если вы хотите, чтобы он имел динамический размер. Необходимо обернуть содержимое. Мой код oncreate должен занимать только оставшееся пространство, но когда появляется клавиатура, она будет прокручиваться, потому что тогда она будет больше, чем меньший экран. - person Dave S; 25.03.2018

Я понимаю, что NestedScrollView не будет прокручиваться, пока его содержимое не исчезнет с экрана. Я делаю хак и ставлю несколько пустых строк после введенного текста, чтобы содержимое вышло за пределы текущего экрана. После фокуса потерь EditText я удаляю пустые строки.

public class MainActivity extends AppCompatActivity {
        String EMPTY_SPACES = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
        EditText mEditText;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            mEditText = findViewById(R.id.contentEditText);

            mEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
                @Override
                public void onFocusChange(View view, boolean hasFocus) {
                    if (!hasFocus) {
                        // code to execute when EditText loses focus
                        mEditText.setText(mEditText.getText().toString().trim());
                    }
                }
            });

            mEditText.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

                }

                @Override
                public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                    int charsThatGuaranteesTextIsOutOfScreen = 400;
                    if (mEditText.hasFocus() && charSequence.length() < charsThatGuaranteesTextIsOutOfScreen) {
                        mEditText.setText(String.format(Locale.getDefault(), "%1$s%2$s", charSequence, EMPTY_SPACES));
                        mEditText.setSelection(i2);
                    }
                }

                @Override
                public void afterTextChanged(Editable editable) {

                }
            });
        }

        @Override
        public void onBackPressed() {
            if (mEditText.hasFocus()) {
                mEditText.clearFocus();
            } else {
                super.onBackPressed();
            }
        }
    }
person DimDim    schedule 23.03.2018
comment
Прокрутка, похоже, не работает. Смотрите видео: ufile.io/qb6zq. - person android developer; 23.03.2018
comment
Может быть, разместить полный проект на сайте, который я поставил? Я попробую то же самое, что и вы. - person android developer; 23.03.2018
comment
Хммм, я думаю, что NestedScrollView не будет прокручиваться, пока его содержимое не выйдет за пределы экрана ... мое видео было снято, когда NestedScrollView было больше одного экрана, и эффект прокрутки был таким, как ожидалось. - person DimDim; 24.03.2018
comment
Это вызывает странные проблемы с редактированием при фокусировке. Иногда, когда я печатаю сразу после фокусировки, текст не вводится, а иногда по какой-то причине курсор перемещается вверх. Кроме того, он помещает ненужные пробелы. См. здесь: ufile.io/d5v6s. - person android developer; 25.03.2018
comment
Определенно это не лучшее решение, я только демонстрирую проблему. Я собираюсь сделать лучший способ принудительной прокрутки NestedScrollView - person DimDim; 25.03.2018
comment
У меня есть альтернативное решение здесь: stackoverflow.com/a/49473337/878126 . Но это тоже не идеально. Сосредоточение внимания на многострочном содержимом приведет к его прокрутке, даже если вы сосредоточитесь на первой строке. - person android developer; 25.03.2018