Как наложить представление в режиме ограничения?

У меня есть этот макет моей активности входа. Я хочу наложить progressBar, как это можно сделать, используя FrameLayout. Как это сделать, используя ConstraintLayout?

<layout>

    <data>

        <variable
            name="vm"
            type="com.app.android.login.vm" />
    </data>

    <ScrollView 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:fillViewport="true"
        tools:context="com.app.android.login.LoginActivity"
        tools:ignore="missingPrefix">

        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="@dimen/default_view_margin_bottom_8dp">

            <android.support.design.widget.TextInputLayout
                android:id="@+id/til_login_email"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginEnd="@dimen/default_view_margin_right_8dp"
                android:layout_marginStart="@dimen/default_view_margin_left_8dp"
                android:textColorHint="@color/colorSecondaryText"
                app:hintTextAppearance="@style/AppTheme.InputLayoutStyle"
                app:layout_constraintBottom_toTopOf="@+id/til_login_password"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintVertical_chainStyle="packed">

                <android.support.design.widget.TextInputEditText
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="@string/login_email"
                    android:imeOptions="actionNext"
                    android:singleLine="true"
                    android:text="@={vm.emailField}"
                    android:textColor="@color/colorPrimaryText" />
            </android.support.design.widget.TextInputLayout>

            <android.support.design.widget.TextInputLayout
                android:id="@+id/til_login_password"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginEnd="@dimen/default_view_margin_right_8dp"
                android:layout_marginStart="@dimen/default_view_margin_left_8dp"
                android:textColorHint="@color/colorSecondaryText"
                app:hintTextAppearance="@style/AppTheme.InputLayoutStyle"
                app:layout_constraintBottom_toTopOf="@+id/btn_login_login"
                app:layout_constraintTop_toBottomOf="@+id/til_login_email"
                app:layout_constraintVertical_chainStyle="packed">

                <android.support.design.widget.TextInputEditText
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="@string/login_password"
                    android:imeOptions="actionDone"
                    android:inputType="textPassword"
                    android:singleLine="true"
                    android:text="@={vm.passwordField}"
                    android:textColor="@color/colorPrimaryText" />
            </android.support.design.widget.TextInputLayout>

            <Button
                android:id="@+id/btn_login_login"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginEnd="@dimen/default_view_margin_right_8dp"
                android:layout_marginStart="@dimen/default_view_margin_left_8dp"
                android:layout_marginTop="48dp"
                android:onClick="@{vm::login}"
                android:text="@string/login_btn_text"
                android:textColor="@color/colorWhite"
                app:layout_constraintBottom_toTopOf="@+id/textview_login_forgot_password"
                app:layout_constraintTop_toBottomOf="@+id/til_login_password"
                app:layout_constraintVertical_chainStyle="packed" />

            <TextView
                android:id="@+id/textview_login_forgot_password"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginEnd="@dimen/default_view_margin_right_8dp"
                android:layout_marginStart="@dimen/default_view_margin_left_8dp"
                android:layout_marginTop="36dp"
                android:gravity="center"
                android:text="@string/login_forgot_password"
                app:layout_constraintBottom_toTopOf="@+id/btn_login_register"
                app:layout_constraintTop_toBottomOf="@+id/btn_login_login"
                app:layout_constraintVertical_chainStyle="packed" />

            <Button
                android:id="@+id/btn_login_register"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginEnd="@dimen/default_view_margin_right_8dp"
                android:layout_marginStart="@dimen/default_view_margin_left_8dp"
                android:text="@string/login_sign_up"
                android:textColor="@color/colorWhite"
                app:layout_constraintBottom_toBottomOf="parent" />

            <ProgressBar
                android:id="@+id/progressBar"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:visibility="@{vm.progressVisibility}"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

        </android.support.constraint.ConstraintLayout>
    </ScrollView>
</layout>

Он выглядит следующим образом:

введите описание изображения здесь

Я ищу решение, которое должно работать для уровня API 19+. Я не хочу добавлять больше иерархии в свой макет, обертывая Button или progressBar внутри ViewGroup или так.

Ответ 1

Есть два варианта: в каждом случае вы добавляете один атрибут к тегу <ProgressBar/>. Это либо

android:translationZ="2dp"

или

android:elevation="2dp"

Уровень API должен быть >= 21.

Ответ 2

Если вы хотите на 100% наложить целевой вид, ограничьте все стороны наложения на соответствующие стороны целевого представления и установите высоту и ширину накладываемого вида на 0dp следующим образом:

    <View
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="@id/animation_view"
        app:layout_constraintLeft_toLeftOf="@id/animation_view"
        app:layout_constraintRight_toRightOf="@id/animation_view"
        app:layout_constraintTop_toTopOf="@id/animation_view"/>

Вот рабочий пример. На следующем изображении красный рисунок помещается поверх изображения. XML следует за изображением.

введите описание изображения здесь

<android.support.constraint.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/animation_view"
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:src="@mipmap/ic_launcher"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#AAFF0000"
        app:layout_constraintBottom_toBottomOf="@id/animation_view"
        app:layout_constraintLeft_toLeftOf="@id/animation_view"
        app:layout_constraintRight_toRightOf="@id/animation_view"
        app:layout_constraintTop_toTopOf="@id/animation_view" />
</android.support.constraint.ConstraintLayout>

Подробнее см. для ConstraintLayout.

Ответ 3

Установить высоту над ProgressBar 2dp, похоже, будет работать.

android:elevation="2dp"

Вы также можете попробовать установить translationZ, как предложено в , на аналогичный вопрос. Для меня это работает на эмуляторе, работающем с API 17, и индикатор выполнения отображается сверху, как и ожидалось. Если вы получите предупреждение, проверьте версию сборки

Ответ 4

Я хочу предоставить вам альтернативу XML-решению.
Вы также можете добавить представление в свое корневое представление. (ConstraintLayout)

ViewGroupOverlay - дополнительный слой, который находится поверх ViewGroup ( "представление хоста" ), который вычерчивается после всего остального содержимого в этом представлении (включая дочерние группы представлений). Взаимодействие с слоем наложения выполняется путем добавления и удаления представлений и чертежей.

<android.support.constraint.ConstraintLayout
            android:id="@+id/root_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="@dimen/default_view_margin_bottom_8dp">

Если вы ссылаетесь на корень в коде, вы можете добавить свой ProgressBar.
Что-то вроде этого:

rootLayout.overlay.add(ProgressBar(context).apply {
    measure(View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY))
    layout(0, 0, 100, 100)
})

Вы также можете узнать об этом ссылка для получения дополнительной информации.
И этот fooobar.com/questions/459125/... вопрос также может помочь.

Ответ 5

Вы можете попробовать один из следующих вариантов: 1. Добавьте относительный макет вне вашего макета как здесь

 <RelativeLayout
   android:id="@+id/relativelayout_progress"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:visibility="gone"
   android:background="#aa000022" >

   <ProgressBar 
       android:layout_centerInParent="true"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:indeterminateOnly="true" />

</RelativeLayout>
  1. Добавить оверлей в вашу деятельность onCreate, как описано здесь Android 4.3 Просмотр пользовательских интерфейсов наложения

Ответ 6

Еще один простой способ решить это - изменить Button на View, изменить фон и размер. Наложите его на TextView для замены старого текста Button и другого View для кликабельного позже

Ответ 7

Вот ваше решение API 19. Он помещает CircularProgressDrawable в наложение поверх вашего ConstraintLayout.

Это выглядит так:

введите описание изображения здесь

Что вам нужно сделать:

  • Избавьтесь от XML ProgressBar.

  • Дайте XML ConstraintLayout идентификатор, например:

    android:id="@+id/cl"
    
  • Добавьте этот код в свою MainActivity:

    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
        boolean toggle;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            final ConstraintLayout cl = findViewById(R.id.cl);
            cl.setOnClickListener(this);
        }
    
        @Override
        public void onClick(final View view) {
            toggle ^= true;
            if (toggle) {
                startProgress();
            } else {
                stopProgress();
            }
        }
    
        void startProgress() {
            final ConstraintLayout cl = findViewById(R.id.cl);
            final CircularProgressDrawable progressDrawable = new CircularProgressDrawable(this);
            progressDrawable.setColorSchemeColors(Color.MAGENTA);
            progressDrawable.setCenterRadius(50f);
            progressDrawable.setStrokeWidth(12f);
            progressDrawable.setStrokeCap(Paint.Cap.BUTT);
            cl.post(new Runnable() {
                @Override
                public void run() {
                    progressDrawable.setBounds(0, 0, cl.getWidth(), cl.getHeight());
                    cl.getOverlay().add(progressDrawable);
                }
            });
            progressDrawable.start();
        }
    
        void stopProgress() {
            final ConstraintLayout cl = findViewById(R.id.cl);
            final CircularProgressDrawable progressDrawable = new CircularProgressDrawable(this);
            progressDrawable.setColorSchemeColors(Color.MAGENTA);
            progressDrawable.setCenterRadius(50f);
            progressDrawable.setStrokeWidth(12f);
            progressDrawable.setStrokeCap(Paint.Cap.BUTT);
            cl.post(new Runnable() {
                @Override
                public void run() {
                    cl.getOverlay().clear();
                }
            });
            progressDrawable.stop();
        }
    }
    

Ответ 8

В моих наблюдениях Android "складывает" представления вдоль оси z в том порядке, в котором они отображаются в файле xml, так что представление в конце файла будет в верхней части оси z, а представление в начале файл будет внизу. Конечно, как только вы начнете устанавливать высоту, zTranslation и т.д., Порядок стеков оси z будет изменен...

поэтому перемещение объявления progressBar в конец ConstraintLayout должно привести к тому, что оно появится над другими представлениями, это сработало для меня.

Ответ 9

Вы можете достичь своей цели, установив перевод Z для вида.

Поместите этот метод в вспомогательный класс (например: UIUtils) и используйте его для вашего представления:

/**
 * Set the 'Z' translation for a view
 *
 * @param view         {@link View} to set 'Z' translation for
 * @param translationZ 'Z' translation as float
 */
public static void setTranslationZ(View view, float translationZ) {
    ViewCompat.setTranslationZ(view, translationZ);
}

ИСПОЛЬЗОВАНИЕ:

UIUTils.setTranslationZ(YOUR_VIEW, 5);