CardView в RecyclerView: анимация при заполнении
У меня есть переработанное представление, которое заполняется макетами CardView. Я заметил, что во многих приложениях эти элементы имеют приятный анимированный вход, а не внезапно появляются, как они это делают в моем приложении. Пример того, что я пытаюсь достичь, показан ниже:
![введите описание изображения здесь]()
Как я могу использовать свой swipeRefreshListener/adapter для запуска этой анимации? Как реализовать это через адаптер?
Примечание. Мне нужна эта анимация, которая также срабатывает, когда RecyclerView сначала заполняется элементами CardView и данными, которые они содержат.
Мой адаптер RecyclerView показан ниже:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private String[] mDataset;
private String[] mClassDataset;
private int lastPosition = -1;
private Context context;
View view;
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public TextView mClassDataView;
CardView container;
public ViewHolder(View itemView) {
super(itemView);
mTextView = (TextView)itemView.findViewById(R.id.grade);
mClassDataView = (TextView)itemView.findViewById(R.id.class_name);
container = (CardView)itemView.findViewById(R.id.card_view);
}
}
public RecyclerAdapter(String[] myDataset, String[] classData, Context context) {
mDataset = myDataset;
mClassDataset = classData;
this.context = context;
}
@Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_item, parent, false);
ViewHolder vh = new ViewHolder(v);
view = v;
return vh;
}
@Override
public int getItemCount() {
return mClassDataset.length;
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
if (mDataset.length < mClassDataset.length) {
holder.mTextView.setText("N/A");
holder.mClassDataView.setText(mClassDataset[position]);
if (mClassDataset[position].equals("N/A")) {
}
} else {
holder.mTextView.setText(mDataset[position]);
holder.mClassDataView.setText(mClassDataset[position]);
}
for (int i = 0; i < getItemCount(); i++) {
animate(view, i);
}
}
private void animate(final View view, final int position){
Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left);
view.startAnimation(animation);
lastPosition = position;
}
}
Анимация в настоящее время работает, однако вещь состоит в том, что элементы анимируются все сразу. Я попытался выполнить итерацию элементов, создав собственный метод getChild()
, но это не сработало. Как-то мне нужно получить доступ/оживить каждого ребенка по отдельности и, возможно, установить задержку между каждой анимацией. Однако я не уверен, как именно я могу это сделать. Я знаю, что я могу использовать Handler для установки задержки, но доступ к каждому ребенку является проблемой.
Ответы
Ответ 1
Используйте этот настраиваемый класс RecyclerView
, он ведет себя как приложение, которое вы разместили на снимке экрана (Reddit Relay), оно предотвращает прокрутку во время анимации первых элементов.
Вы можете настроить анимацию по своему усмотрению.
package net.leolink.android.testrecyclerviewentranceanimation;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* @author Leo on 2015/09/03
*/
public class MyRecyclerView extends RecyclerView {
private boolean mScrollable;
public MyRecyclerView(Context context) {
this(context, null);
}
public MyRecyclerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mScrollable = false;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return !mScrollable || super.dispatchTouchEvent(ev);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
for (int i = 0; i < getChildCount(); i++) {
animate(getChildAt(i), i);
if (i == getChildCount() - 1) {
getHandler().postDelayed(new Runnable() {
@Override
public void run() {
mScrollable = true;
}
}, i * 100);
}
}
}
private void animate(View view, final int pos) {
view.animate().cancel();
view.setTranslationY(100);
view.setAlpha(0);
view.animate().alpha(1.0f).translationY(0).setDuration(300).setStartDelay(pos * 100);
}
}
DEMO
![Demo]()
Ответ 2
Для RecyclerView вы можете использовать ItemAnimators, установив их с помощью этого метода:
RecyclerView.setItemAnimator(RecyclerView.ItemAnimator animator)
Существует несколько библиотек, которые реализуют этот ItemAnimator, например, этот: https://github.com/wasabeef/recyclerview-animators
Ответ 3
Сначала определите анимацию:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="100%p" android:toXDelta="0"
android:duration="300"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="300" />
</set>
Затем установите его в свой адаптер:
@Override
public void onBindViewHolder(ViewHolder holder, int position)
{
holder.text.setText(items.get(position));
// Here you apply the animation when the view is bound
setAnimation(holder.container, position);
}
/**
* Here is the key method to apply the animation
*/
private void setAnimation(View viewToAnimate, int position)
{
// If the bound view wasn't previously displayed on screen, it animated
if (position > lastPosition)
{
Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.push_left_in);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
Ссылка на: RecyclerView: как создать эффект анимации вставки?