форматирование - html теги android




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

Ваш ожидаемый результат может быть достигнут путем изменения 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>

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

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

Задний план

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

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

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

<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. Все here , here , here , here . Может быть, больше, но у меня не хватало следа ...
  2. Я пробовал различные значения windowSoftInputMode в манифесте и пытался установить isNestedScrollingEnabled в NestedScrollView.
  3. Пробовал различные конфигурации в XML, чтобы позволить EditText занимать столько места, сколько необходимо, чтобы предотвратить его прокручивание внутри него.

Вопрос

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

EDIT: поскольку оригинальное приложение немного сложнее, имея некоторые представления внизу (внутри того, что похоже на панель инструментов), которые автоматически скрываются, когда вы не фокусируетесь на нижнем 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)
        }
    }
}

Вы должны быть в состоянии достичь того, чего хотите, вычисляя 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);
        }
    }
});

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

Я понимаю, что 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();
            }
        }
    }






android-nestedscrollview