private void prepareAnimation() {
    yMap.clear();
    positionMap.clear();
    beforeVisible.clear();
    afterVisible.clear();

    adapter.setMayNotify(false);

    final int childCount = getChildCount();

    final int firstVisiblePosition = getFirstVisiblePosition();

    for (int i = 0; i < childCount; i++) {
      final View child = getChildAt(i);
      final long id = adapter.getItemId(firstVisiblePosition + i);

      yMap.put(id, ViewHelper.getY(child));
      positionMap.put(id, firstVisiblePosition + i);
    }

    for (int i = 0; i < firstVisiblePosition; i++) {
      final long id = adapter.getItemId(i);
      beforeVisible.add(id);
    }

    final int count = adapter.getCount();

    for (int i = firstVisiblePosition + childCount; i < count; i++) {
      final long id = adapter.getItemId(i);
      afterVisible.add(id);
    }
  }
  /** Animate items that just appeared and items that move within the screen. */
  private void animatePostLayout(final float durationUnit) {

    final AnimatorSet animatorSet = new AnimatorSet();

    for (int i = 0; i < getChildCount(); i++) {
      final View child = getChildAt(i);
      final long id = getItemIdAtPosition(getFirstVisiblePosition() + i);

      ObjectAnimator anim = null;

      ViewHelper.setAlpha(child, 1f);

      if (yMap.containsKey(id)) {
        // moved within visible area

        // log("Moved within visible area id: " + id);
        final float oldY = yMap.remove(id);
        final float newY = ViewHelper.getY(child);

        if (oldY != newY) {
          anim = animateY(child, oldY, newY, durationUnit);
        }

      } else {
        // moved into visible area or new

        if (beforeVisible.contains(id)) {
          // moved from top
          final float newY = ViewHelper.getY(child);
          final float oldY = -child.getHeight();

          anim = animateY(child, oldY, newY, durationUnit);
        } else if (afterVisible.contains(id)) {
          // moved from bottom
          final float newY = ViewHelper.getY(child);
          final float oldY = getHeight();

          anim = animateY(child, oldY, newY, durationUnit);
        } else {
          // entirely new
          ViewHelper.setAlpha(child, 0f);

          anim = animateAlpha(child, true);
          anim.setStartDelay(MIN_ANIM_DURATION);
        }
      }

      if (anim != null) {
        animatorSet.play(anim);
      }
    }

    animatorSet.addListener(
        new AnimatorListenerAdapter() {
          @Override
          public void onAnimationEnd(final Animator animation) {
            finishAnimation();
          };
        });

    animatorSet.start();
  }