TransitionManager不会为颜色更改设置动画

时间:2017-09-30 13:33:55

标签: android android-layout android-recyclerview material-design android-animation

我跟着Nick Butcher's Material Improvements I/O 2016 talk,大约6点,他开始谈论动画列表项目。我完全按照他的方式实现了这个功能,并且绑定更改了正确的动画效果,但颜色变化没有动画,尽管他明确表示他们会这样做:

animation

这就是代码的样子:

这是RecyclerView.Adapter类的相关部分:

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val item: Pair<String, String> = items[position]

    holder.title.text = item.first
    holder.subtitle.text = item.second

    val isExpanded = position == expandedPosition
    holder.subtitle.visibility = if (isExpanded) View.VISIBLE else View.GONE
    holder.itemView.isActivated = isExpanded
    holder.itemView.setOnClickListener {
        expandedPosition = if (isExpanded) -1 else position
        TransitionManager.beginDelayedTransition(recyclerView)
        notifyDataSetChanged()
    }
}

这是我用于项目的布局。 ConstraintLayout对于当前的布局设置来说有点过分,但我减少了布局以创建一个最小的示例。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".MainActivity"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/item_background"
    android:stateListAnimator="@animator/item_elevation"
    android:padding="8dp">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="24sp"
        tools:text="Title 1"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"/>

    <TextView
        android:id="@+id/subtitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:text="Subtitle 1"
        app:layout_constraintTop_toBottomOf="@id/title"
        app:layout_constraintStart_toStartOf="parent"
        />

</android.support.constraint.ConstraintLayout>

这是我用于项目布局的背景:

<selector xmlns:android="http://schemas.android.com/apk/res/android"
    android:enterFadeDuration="@android:integer/config_mediumAnimTime"
    android:exitFadeDuration="@android:integer/config_mediumAnimTime">

    <item android:state_activated="true"
        android:drawable="@color/colorAccent" />

    <item android:drawable="@color/colorPrimaryDark" />

</selector>

1 个答案:

答案 0 :(得分:4)

确保您的数据集具有稳定的ID并调用Recycler.Adapter#setHasStableIds(true)。看到 setHasStableIds()

您还需要覆盖适配器中的getItemId()以返回稳定的ID。另请参阅notifyDataSetChanged以获得有关稳定ID的简短讨论。

  

当使用此方法时,RecyclerView将尝试为报告它们具有稳定ID的适配器合成可见的结构更改事件。这有助于动画和视觉对象持久性的目的,但单个项目视图仍然需要反弹并重新传输。

以下是稳定ID设置为false的演示:

enter image description here

并将稳定的ID设置为true。我对颜色变化的过渡时间很长,所以很明显。

enter image description here

<强> RecyclerViewAdapter.java

这是演示中使用的适配器。已移除TransitionManager.beginDelayedTransition(mRecyclerView)以让RecyclerView更好地处理动画。

class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    RecyclerViewAdapter() {
    }

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

    private int mExpandedPosition = RecyclerView.NO_POSITION;

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        final ItemViewHolder vh = (ItemViewHolder) holder;
        final TextView subTitle = vh.mSubTitle;

        vh.mTitle.setText(titleForPosition(position));
        subTitle.setText(subTitleForPosition(position));

        final boolean isExpanded = position == mExpandedPosition;

        subTitle.setVisibility((isExpanded) ? View.VISIBLE : View.GONE);
        holder.itemView.setActivated(isExpanded);
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mExpandedPosition = isExpanded ? RecyclerView.NO_POSITION : vh.getAdapterPosition();
                notifyDataSetChanged();
            }
        });
    }

    private String titleForPosition(int position) {
        return "Title " + position;
    }

    private String subTitleForPosition(int position) {
        return "Subtitle " + position;
    }

    @Override
    public int getItemCount() {
        return 5;
    }

    @Override
    public long getItemId(int position) {
        return titleForPosition(position).hashCode();
    }

    static class ItemViewHolder extends RecyclerView.ViewHolder {
        private final TextView mTitle;
        private final TextView mSubTitle;

        ItemViewHolder(View itemView) {
            super(itemView);
            mTitle = itemView.findViewById(R.id.title);
            mSubTitle = itemView.findViewById(R.id.subtitle);
        }
    }

    @SuppressWarnings("unused")
    private final static String TAG = "RecyclerViewAdapter";
}