Непостоянное движение при использовании animateLayoutChanges в ConstraintLayout

Я хочу реализовать расширяющийся CardView, я сделал это, включив представление, которое я хочу показать / скрыть, и установив видимость на View.GONE. Но почему-то CardView заикается при раскрытии и сворачивании. Это делает это.
Я попытался исправить это, добавив настраиваемый переход, который масштабируется вверх и вниз, но он дает мне тот же результат, только немного медленнее. Я действительно не могу найти какую-либо документацию по этому типу вещей, а вещи, которые я считаю, не имеют отношения, например, переход активности и т. д.
Я взглянул на LayoutTransition, но опять же не очень помог. Понятия не имею, почему это происходит, толчок в правильном направлении был бы признателен!

Ваше здоровье

Вот мой макет:

<?xml version = "1.0" encoding = "utf-8"?>
<android.support.v7.widget.CardView xmlns:android = "http://schemas.android.com/apk/res/android"
    xmlns:app = "http://schemas.android.com/apk/res-auto"
    android:id = "@+id/shoppinglist_card"
    android:layout_width = "match_parent"
    android:layout_height = "wrap_content"
    android:layout_marginEnd = "4dp"
    android:layout_marginStart = "4dp"
    app:cardCornerRadius = "4dp"
    app:cardUseCompatPadding = "true"
    app:layout_constraintEnd_toEndOf = "parent"
    app:layout_constraintStart_toStartOf = "parent">

    <android.support.constraint.ConstraintLayout
        android:id = "@+id/shoppinglist_content_container"
        android:layout_width = "match_parent"
        android:layout_height = "wrap_content"
        android:animateLayoutChanges = "true">

        <TextView
            android:id = "@+id/shoppinglist_name"
            android:layout_width = "wrap_content"
            android:layout_height = "wrap_content"
            android:layout_marginStart = "16dp"
            android:layout_marginTop = "16dp"
            android:text = "Shoppinglist Name"
            android:textColor = "@color/primary"
            android:textSize = "16sp"
            app:layout_constraintStart_toStartOf = "parent"
            app:layout_constraintTop_toTopOf = "parent" />

        <TextView
            android:id = "@+id/shoppinglist_group"
            android:layout_width = "wrap_content"
            android:layout_height = "wrap_content"
            android:layout_marginTop = "2dp"
            android:text = "Group Name"
            app:layout_constraintEnd_toEndOf = "@+id/shoppinglist_name"
            app:layout_constraintHorizontal_bias = "0.0"
            app:layout_constraintStart_toStartOf = "@+id/shoppinglist_name"
            app:layout_constraintTop_toBottomOf = "@+id/shoppinglist_name" />

        <View
            android:id = "@+id/shoppinglist_category_container"
            android:layout_width = "50dp"
            android:layout_height = "0dp"
            android:animateLayoutChanges = "true"
            android:background = "@color/primary"
            app:layout_constraintBottom_toBottomOf = "parent"
            app:layout_constraintEnd_toEndOf = "parent"
            app:layout_constraintTop_toTopOf = "parent" />

        <ImageView
            android:id = "@+id/shoppinglist_category_image"
            android:layout_width = "0dp"
            android:layout_height = "0dp"
            android:layout_marginBottom = "8dp"
            android:layout_marginEnd = "8dp"
            android:layout_marginStart = "8dp"
            android:layout_marginTop = "8dp"
            android:src = "@drawable/ic_email"
            android:tint = "@android:color/white"
            app:layout_constraintBottom_toBottomOf = "@+id/shoppinglist_dropdown"
            app:layout_constraintEnd_toEndOf = "@+id/shoppinglist_category_container"
            app:layout_constraintStart_toStartOf = "@+id/shoppinglist_category_container"
            app:layout_constraintTop_toTopOf = "@+id/shoppinglist_category_container" />

        <ImageView
            android:id = "@+id/shoppinglist_unchecked_image"
            android:layout_width = "15dp"
            android:layout_height = "15dp"
            android:layout_marginBottom = "8dp"
            android:layout_marginStart = "16dp"
            android:tint = "@color/shoppinglist_unchecked"
            app:layout_constraintBottom_toBottomOf = "@+id/shoppinglist_dropdown"
            app:layout_constraintStart_toStartOf = "parent"
            app:srcCompat = "@drawable/ic_close" />

        <ImageView
            android:id = "@+id/shoppinglist_checked_image"
            android:layout_width = "15dp"
            android:layout_height = "15dp"
            android:layout_marginBottom = "2dp"
            android:layout_marginStart = "16dp"
            android:tint = "@color/shoppinglist_checked"
            app:layout_constraintBottom_toTopOf = "@+id/shoppinglist_unchecked_image"
            app:layout_constraintStart_toStartOf = "parent"
            app:srcCompat = "@drawable/ic_check" />

        <TextView
            android:id = "@+id/shoppinglist_unchecked_amount"
            android:layout_width = "wrap_content"
            android:layout_height = "wrap_content"
            android:layout_marginStart = "2dp"
            android:text = "12"
            android:textSize = "11sp"
            app:layout_constraintBottom_toBottomOf = "@+id/shoppinglist_unchecked_image"
            app:layout_constraintStart_toEndOf = "@+id/shoppinglist_unchecked_image"
            app:layout_constraintTop_toTopOf = "@+id/shoppinglist_unchecked_image" />

        <TextView
            android:id = "@+id/shoppinglist_checked_amount"
            android:layout_width = "wrap_content"
            android:layout_height = "wrap_content"
            android:layout_marginStart = "2dp"
            android:text = "12"
            android:textSize = "11sp"
            app:layout_constraintBottom_toBottomOf = "@+id/shoppinglist_checked_image"
            app:layout_constraintStart_toEndOf = "@+id/shoppinglist_checked_image"
            app:layout_constraintTop_toTopOf = "@+id/shoppinglist_checked_image" />

        <TextView
            android:id = "@+id/shoppinglist_date"
            android:layout_width = "wrap_content"
            android:layout_height = "wrap_content"
            android:layout_marginEnd = "16dp"
            android:layout_marginTop = "16dp"
            android:text = "31/12/2018"
            android:textColor = "@color/accent"
            app:layout_constraintEnd_toStartOf = "@+id/shoppinglist_category_container"
            app:layout_constraintTop_toTopOf = "parent" />

        <ImageView
            android:id = "@+id/shoppinglist_dropdown"
            android:layout_width = "25dp"
            android:layout_height = "25dp"
            android:layout_marginBottom = "2dp"
            android:layout_marginEnd = "8dp"
            android:layout_marginStart = "8dp"
            android:layout_marginTop = "115dp"
            android:tint = "@color/secondary_text"
            app:layout_constraintBottom_toBottomOf = "parent"
            app:layout_constraintEnd_toEndOf = "parent"
            app:layout_constraintStart_toStartOf = "parent"
            app:layout_constraintTop_toTopOf = "parent"
            app:layout_constraintVertical_bias = "0.0"
            app:srcCompat = "@drawable/ic_dropdown" />

        <TextView
            android:id = "@+id/shoppinglist_item_list"
            android:layout_width = "0dp"
            android:layout_height = "150dp"
            android:layout_marginBottom = "8dp"
            android:layout_marginEnd = "16dp"
            android:layout_marginStart = "16dp"
            android:layout_marginTop = "8dp"
            android:visibility = "gone"
            app:layout_constraintBottom_toBottomOf = "parent"
            app:layout_constraintEnd_toStartOf = "@+id/shoppinglist_category_container"
            app:layout_constraintStart_toStartOf = "parent"
            app:layout_constraintTop_toBottomOf = "@+id/shoppinglist_dropdown" />


    </android.support.constraint.ConstraintLayout>

</android.support.v7.widget.CardView>

И мой адаптер:

package nl.knapper_development.basketbuddy.ui.main.shoppinglist;

import android.support.annotation.NonNull;
import android.support.constraint.ConstraintLayout;
import android.support.transition.TransitionManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;

import nl.knapper_development.basketbuddy.R;

public class ShoppinglistAdapter extends RecyclerView.Adapter<ShoppinglistAdapter.ViewHolder> {

    private ArrayList<Shoppinglist> data;
    private ExpansionStateList expansionStateList;

    public ShoppinglistAdapter(ArrayList<Shoppinglist> data) {
        this.data = data;
        this.expansionStateList = new ExpansionStateList(data.size());
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.shoppinglist, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Shoppinglist s = data.get(position);
        holder.name.setText(s.getName());
        holder.group.setText(s.getGroup());
        holder.date.setText(s.getDate());
        holder.checked.setText(s.getCheckedAmount().toString());
        holder.unchecked.setText(s.getUncheckedAmount().toString());
        holder.categoryImage.setImageResource(s.getDrawable());
        holder.categoryContainer.setBackgroundColor(holder.itemView.getResources().getColor(s.getColor()));
        holder.dropDown.setOnClickListener(v -> {
            TransitionManager.beginDelayedTransition(holder.contentContainer);
            holder.list.setVisibility(expansionStateList.get(position) ? View.VISIBLE : View.GONE);
            expansionStateList.flip(position);
        });
    }

    @Override
    public int getItemCount() {
        return data.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        private TextView name;
        private TextView group;
        private TextView date;
        private TextView checked;
        private TextView unchecked;
        private ImageView categoryImage;
        private View categoryContainer;
        private ImageView dropDown;
        private TextView list;
        private ConstraintLayout contentContainer;

        public ViewHolder(View itemView) {
            super(itemView);
            name = itemView.findViewById(R.id.shoppinglist_name);
            group = itemView.findViewById(R.id.shoppinglist_group);
            date = itemView.findViewById(R.id.shoppinglist_date);
            checked = itemView.findViewById(R.id.shoppinglist_checked_amount);
            unchecked = itemView.findViewById(R.id.shoppinglist_unchecked_amount);
            categoryImage = itemView.findViewById(R.id.shoppinglist_category_image);
            categoryContainer = itemView.findViewById(R.id.shoppinglist_category_container);
            dropDown = itemView.findViewById(R.id.shoppinglist_dropdown);
            list = itemView.findViewById(R.id.shoppinglist_item_list);
            contentContainer = itemView.findViewById(R.id.shoppinglist_content_container);
        }

    }

}

ExpansionStateList: для отслеживания состояний расширения представления, true = extended.

public class ExpansionStateList extends ArrayList<Boolean> {

    public ExpansionStateList(int size) {
        for (int c = 0; c < size; c++) {
            this.add(false);
        }
    }

    public void flip(int index) {
        Boolean v = this.get(index);
        this.set(index, !v);
    }

}

Вы программно меняете ширину shoppinglist_item_list внутри flip ()? Это может быть проблемой.

Andro 15.04.2018 23:29

@Andro Нет, flip устанавливает логическое значение в '! Value', это помогает мне отслеживать развернутые состояния. Это то, для чего я использую ExpansionStateList. Я добавил этот код в свой вопрос.

Harjan 15.04.2018 23:35

Попробуйте установить ширину shoppinglist_item_list на match_parent вместо 0dp. Я думаю, это, вероятно, из-за того, что макет обтекает контент. Этого опять же не должно быть, поскольку оболочка имеет атрибут match_parent. Другой способ - использовать Animator.

Andro 15.04.2018 23:50

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

Harjan 16.04.2018 00:21

Самый короткий способ - удалить android:animateLayoutChanges = "true" и TransitionManager.beginDelayedTransition(holder.contentConta‌​iner);. Это расширит вид без анимации. Для анимации используйте этот stackoverflow.com/questions/32835397/…

Andro 16.04.2018 01:06
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
5
1 739
1

Ответы 1

Я испытал ту же самую проблему. Я добился лучших результатов, установив ширину скрытого / видимого макета на «match_parent» вместо «0dp» с ограничениями с обеих сторон. Это исправило анимацию для расширения, но не для уменьшения. Из-за нехватки времени я в конечном итоге использовал RelativeLayoutt, но я уверен, что если немного поэкспериментировать с шириной просмотров, проблема может быть решена. Надеюсь, это кому-то поможет, других решений в сети я не нашел.

Другие вопросы по теме