我怎么能动画回收视图项目时出现?
默认的项目动画器只在设置完回收器数据后添加或删除数据时才会动画。
如何实现这一目标?
我怎么能动画回收视图项目时出现?
默认的项目动画器只在设置完回收器数据后添加或删除数据时才会动画。
如何实现这一目标?
当前回答
在2019年, 我建议把所有的项目动画放到ItemAnimator中。
让我们从在循环视图中声明动画器开始:
with(view.recycler_view) {
adapter = Adapter()
itemAnimator = CustomAnimator()
}
然后声明自定义动画器,
class CustomAnimator() : DefaultItemAnimator() {
override fun animateAppearance(
holder: RecyclerView.ViewHolder,
preInfo: ItemHolderInfo?,
postInfo: ItemHolderInfo): Boolean{} // declare what happens when a item appears on the recycler view
override fun animatePersistence(
holder: RecyclerView.ViewHolder,
preInfo: ItemHolderInfo,
postInfo: ItemHolderInfo): Boolean {} // declare animation for items that persist in a recycler view even when the items change
}
与上面的类似,还有一个用于消失的animatedisappear,用于添加的animateAdd,用于更改的animateChange和移动的animateMove。
重要的一点是在它们内部调用正确的动画调度器。
其他回答
你可以添加一个android:layoutAnimation="@anim/rv_item_animation"属性到RecyclerView,就像这样:
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/layout_animation_fall_down"
/>
感谢这篇精彩的文章: https://proandroiddev.com/enter-animation-using-recyclerview-and-layoutanimation-part-1-list-75a874a5d213
我从pbm的答案创建动画,只做了一点修改,使动画只运行一次
换句话说,动画只在你向下滚动时出现
private int lastPosition = -1;
private void setAnimation(View viewToAnimate, int position) {
// If the bound view wasn't previously displayed on screen, it's animated
if (position > lastPosition) {
ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
anim.setDuration(new Random().nextInt(501));//to make duration random number between [0,501)
viewToAnimate.startAnimation(anim);
lastPosition = position;
}
}
并在onBindViewHolder中调用该函数
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.getTextView().setText("some text");
// call Animation function
setAnimation(holder.itemView, position);
}
当项目被绑定到适配器中时,在recyclerview中进行动画可能不是最好的想法,因为这会导致recyclerview中的项目以不同的速度进行动画。在我的例子中,在recyclerview的末尾的项目动画到他们的位置比顶部的更快,因为顶部的那些有进一步的旅行,所以它看起来不整洁。
我用来动画每个项目到recyclerview的原始代码可以在这里找到:
http://frogermcs.github.io/Instagram-with-Material-Design-concept-is-getting-real/
但是我会复制粘贴代码以防链接中断。
步骤1:在你的onCreate方法中设置这个,这样你就可以确保动画只运行一次:
if (savedInstanceState == null) {
pendingIntroAnimation = true;
}
步骤2:你需要把这段代码放入你想要开始动画的方法中:
if (pendingIntroAnimation) {
pendingIntroAnimation = false;
startIntroAnimation();
}
在链接中,作者是动画工具栏图标,所以他把它放在这个方法中:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
inboxMenuItem = menu.findItem(R.id.action_inbox);
inboxMenuItem.setActionView(R.layout.menu_item_view);
if (pendingIntroAnimation) {
pendingIntroAnimation = false;
startIntroAnimation();
}
return true;
}
步骤3:现在编写startIntroAnimation()的逻辑:
private static final int ANIM_DURATION_TOOLBAR = 300;
private void startIntroAnimation() {
btnCreate.setTranslationY(2 * getResources().getDimensionPixelOffset(R.dimen.btn_fab_size));
int actionbarSize = Utils.dpToPx(56);
toolbar.setTranslationY(-actionbarSize);
ivLogo.setTranslationY(-actionbarSize);
inboxMenuItem.getActionView().setTranslationY(-actionbarSize);
toolbar.animate()
.translationY(0)
.setDuration(ANIM_DURATION_TOOLBAR)
.setStartDelay(300);
ivLogo.animate()
.translationY(0)
.setDuration(ANIM_DURATION_TOOLBAR)
.setStartDelay(400);
inboxMenuItem.getActionView().animate()
.translationY(0)
.setDuration(ANIM_DURATION_TOOLBAR)
.setStartDelay(500)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
startContentAnimation();
}
})
.start();
}
我更倾向于:
我宁愿动画整个recyclerview,而不是在recyclerview内的项目。
步骤1和2保持不变。
在第3步,只要你的API调用返回你的数据,我将开始动画。
private void startIntroAnimation() {
recyclerview.setTranslationY(latestPostRecyclerview.getHeight());
recyclerview.setAlpha(0f);
recyclerview.animate()
.translationY(0)
.setDuration(400)
.alpha(1f)
.setInterpolator(new AccelerateDecelerateInterpolator())
.start();
}
这将使您的整个recyclerview动画,以便它从屏幕底部飞进来。
只用XML简化
浏览Gist连结
res/anim/layout_animation.xml
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/item_animation_fall_down"
android:animationOrder="normal"
android:delay="15%" />
res/anim/item_animation_fall_down.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500">
<translate
android:fromYDelta="-20%"
android:toYDelta="0"
android:interpolator="@android:anim/decelerate_interpolator"
/>
<alpha
android:fromAlpha="0"
android:toAlpha="1"
android:interpolator="@android:anim/decelerate_interpolator"
/>
<scale
android:fromXScale="105%"
android:fromYScale="105%"
android:toXScale="100%"
android:toYScale="100%"
android:pivotX="50%"
android:pivotY="50%"
android:interpolator="@android:anim/decelerate_interpolator"
/>
</set>
在布局和循环视图中使用:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layoutAnimation="@anim/layout_animation"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
就像下面那样扩展你的适配器
public class RankingAdapter extends AnimatedRecyclerView<RankingAdapter.ViewHolder>
并添加super方法到onBindViewHolder
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
super.onBindViewHolder(holder, position);
这是一种自动创建动画适配器的方法比如Basheer AL-MOMANI
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;
import java.util.Random;
/**
* Created by eliaszkubala on 24.02.2017.
*/
public class AnimatedRecyclerView<T extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<T> {
@Override
public T onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(T holder, int position) {
setAnimation(holder.itemView, position);
}
@Override
public int getItemCount() {
return 0;
}
protected int mLastPosition = -1;
protected void setAnimation(View viewToAnimate, int position) {
if (position > mLastPosition) {
ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
anim.setDuration(new Random().nextInt(501));//to make duration random number between [0,501)
viewToAnimate.startAnimation(anim);
mLastPosition = position;
}
}
}