TransitionManager 不动画颜色变化
TransitionManager doesn't animate color change
我关注了 Nick Butcher's Material Improvements I/O 2016 talk,大约在 6:00,他开始谈论动画列表项。我已经完全按照他的方式实现了该功能,并且绑定更改动画正确,但颜色更改没有动画,尽管他明确表示他们会:
代码如下所示:
这是RecyclerView.Adapter
class的相关部分:
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>
确保您的数据集具有稳定的 ID,然后调用 Recycler.Adapter#setHasStableIds(true)
。看
setHasStableIds().
您还需要覆盖 getItemId()
in the adapter to return a stable id. Also see notifyDataSetChanged 以简短讨论稳定 ID。
RecyclerView will attempt to synthesize visible structural change events for adapters that report that they have stable IDs when this method is used. This can help for the purposes of animation and visual object persistence but individual item views will still need to be rebound and relaid out.
这里是稳定 ID 设置为 false 的演示:
并将稳定 ID 设置为 true。我在颜色变化上设置了很长的过渡时间,所以它会很明显。
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";
}
我关注了 Nick Butcher's Material Improvements I/O 2016 talk,大约在 6:00,他开始谈论动画列表项。我已经完全按照他的方式实现了该功能,并且绑定更改动画正确,但颜色更改没有动画,尽管他明确表示他们会:
代码如下所示:
这是RecyclerView.Adapter
class的相关部分:
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>
确保您的数据集具有稳定的 ID,然后调用 Recycler.Adapter#setHasStableIds(true)
。看
setHasStableIds().
您还需要覆盖 getItemId()
in the adapter to return a stable id. Also see notifyDataSetChanged 以简短讨论稳定 ID。
RecyclerView will attempt to synthesize visible structural change events for adapters that report that they have stable IDs when this method is used. This can help for the purposes of animation and visual object persistence but individual item views will still need to be rebound and relaid out.
这里是稳定 ID 设置为 false 的演示:
并将稳定 ID 设置为 true。我在颜色变化上设置了很长的过渡时间,所以它会很明显。
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";
}