Вложенная анимация LinearLayouts LayoutTransition перемещается при удалении дочернего элемента - PullRequest
0 голосов
/ 02 января 2019

Я создал вложенные LinearLayouts, которые содержат дочерние кнопки и другие LinearLayouts с wrap_content и animateLayoutChanges, установленными в true.

код ниже

Когда я удаляюButton из вложенного LinearLayout, анимация воспроизводит удаление Button, но затем повторяется снова, создавая эффект прыжка в общем вложенном Layout.

Кажется, что это ошибка, которая возникает в API 19 и API 25 - и, возможно, другихте (еще не проверенные), но он прекрасно работает на API> = 27, поэтому они должны были это исправить или что-то изменить для этих версий Android, и я не знаю, что это такое.

Проблема в том, что я хотел бы, чтобы он работал для всех API> = 19.

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

ПРИМЕР КОДА

Нажмите кнопку GR1, чтобы создать новое дочернее представление (Button) в синем LinearLayout (id = linearLayoutB) инажмите ее еще раз, чтобы удалить эту же кнопку, чтобы увидеть проблему с анимацией в любой из упомянутых более низких версий API Android

Нажмите кнопку R3, чтобы создать новую дочернюю кнопку в сером LinearLayout (id = linearLayoutGR),не вложены ни в какие другие LinearLayouts, но могут добавить и удалить эту дочернюю кнопку без проблем с анимацией для любой версии Android, конечно, поддерживающей LayoutTransition!

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:animateLayoutChanges="true"
tools:context=".MainActivity">

<LinearLayout
    android:id="@+id/linearLayoutGR"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:background="#ddd"
    android:animateLayoutChanges="true"
    android:orientation="horizontal"
    android:padding="5dp">

    <Button
        android:id="@+id/btnGR1"
        android:layout_width="50dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="GR1"/>

    <LinearLayout
        android:id="@+id/linearLayoutR"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="#fdd"
        android:animateLayoutChanges="true"
        android:orientation="vertical"
        android:padding="5dp">

        <Button
            android:id="@+id/btnR1"
            android:layout_width="50dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="R1"/>

        <Button
            android:id="@+id/btnR2"
            android:layout_width="50dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="R2"/>

        <Button
            android:id="@+id/btnR3"
            android:layout_width="50dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="R3"/>

        <LinearLayout
            android:id="@+id/linearLayoutG"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:background="#dfd"
            android:animateLayoutChanges="true"
            android:orientation="vertical"
            android:padding="5dp">

            <Button
                android:id="@+id/btnG1"
                android:layout_width="50dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="G1"/>

            <Button
                android:id="@+id/btnG2"
                android:layout_width="50dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="G2"/>

            <LinearLayout
                android:id="@+id/linearLayoutB"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:background="#ddf"
                android:animateLayoutChanges="true"
                android:orientation="horizontal"
                android:padding="5dp">

                <Button
                    android:id="@+id/btnB1"
                    android:layout_width="50dp"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:text="B1"/>

                <Button
                    android:id="@+id/btnB2"
                    android:layout_width="50dp"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:text="B2"/>

            </LinearLayout>
    </LinearLayout>

        <Button
            android:id="@+id/btnR5"
            android:layout_width="50dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="R5" />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/linearLayoutP"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="#fdf"
        android:animateLayoutChanges="true"
        android:orientation="vertical"
        android:padding="5dp">

        <Button
            android:id="@+id/btnP1"
            android:layout_width="50dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="P1"/>

        <Button
            android:id="@+id/btnP2"
            android:layout_width="50dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="P2"/>
    </LinearLayout>

    <Button
        android:id="@+id/btnGR4"
        android:layout_width="50dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="GR4"/>
</LinearLayout>

MainActivity.java

import android.animation.LayoutTransition;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {

private LinearLayout linearLayoutGR;
private LinearLayout linearLayoutR;
private LinearLayout linearLayoutG;
private LinearLayout linearLayoutB;
private LinearLayout linearLayoutP;

private Button btnGR1, btnR3;

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

    linearLayoutGR = findViewById(R.id.linearLayoutGR);
    linearLayoutR = findViewById(R.id.linearLayoutR);
    linearLayoutG = findViewById(R.id.linearLayoutG);
    linearLayoutB = findViewById(R.id.linearLayoutB);
    linearLayoutP = findViewById(R.id.linearLayoutP);

    linearLayoutGR.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
    linearLayoutR.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
    linearLayoutG.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
    linearLayoutB.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
    linearLayoutP.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);

    btnGR1 = findViewById(R.id.btnGR1);
    btnR3 = findViewById(R.id.btnR3);

    final Button aBtn = new Button(this);

    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(131, LinearLayout.LayoutParams.WRAP_CONTENT);
    params.gravity = Gravity.CENTER;

    aBtn.setLayoutParams(params);
    aBtn.setGravity(Gravity.CENTER);
    aBtn.setText("A");


    final Button bBtn = new Button(this);

    bBtn.setLayoutParams(params);
    bBtn.setGravity(Gravity.CENTER);
    bBtn.setText("B");


    btnGR1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (linearLayoutB.getChildCount() < 3) {
                linearLayoutB.addView(aBtn);
            } else {
                linearLayoutB.removeView(aBtn);
            }
        }
    });

    btnR3.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (linearLayoutGR.getChildCount() < 5) {
                linearLayoutGR.addView(bBtn);
            } else {
                linearLayoutGR.removeView(bBtn);
            }
        }
    });
}
}

Если есть какой-то обходной путь, я все же хотел бы сохранить тот же эффект / поведение, что и сейчас, без этой ошибки, где любые дочерние представления (Buttons и другие LinearLayouts), которые добавляются или удаляются в любом из других вложенных макетов, приводят к тому, что все макеты соответствующим образом изменяют размер с помощью плавной анимации, сохраняя при этом все дочерние представления по центру и компактные вместе

1 Ответ

0 голосов
/ 02 января 2019

Проблема с удалением потомков, по-видимому, заключается в том, что его анимация задерживается - в LayoutTrasition для mChangingDisappearingDelay установлено значение DEFAULT_DURATION, равное 300 мс

При установке для объекта LayoutTransition задержки 0 с кодом

layoutTransition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);

кажется, что LinearLayouts снова правильно анимируется.

Каждый LinearLayout должен иметь свой собственный уникальный объект LayoutTransition - вы не можете дать им один и тот же объект LayoutTransition, поэтому я создал метод для этого ниже

private LayoutTransition createLayoutTransition(){
    LayoutTransition layoutTransition = new LayoutTransition();
    layoutTransition.enableTransitionType(LayoutTransition.CHANGING);

    // the delay fix
    layoutTransition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
    return layoutTransition;
}

и затем установите для каждого из LinearLayouts LayoutTransition указанный выше метод

linearLayoutGR.setLayoutTransition(createLayoutTransition());
linearLayoutR.setLayoutTransition(createLayoutTransition());
linearLayoutG.setLayoutTransition(createLayoutTransition());
linearLayoutB.setLayoutTransition(createLayoutTransition());
linearLayoutP.setLayoutTransition(createLayoutTransition());

, заменив старый код ниже на приведенный выше код

linearLayoutGR.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
linearLayoutR.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
linearLayoutG.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
linearLayoutB.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
linearLayoutP.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);

Теперь кажется, чтоработать со всеми API, которые поддерживают LayoutTransition

...