Анимация свойств в представлениях за RecyclerView с использованием ItemTouchHelper.SimpleCallback

#java #android #android-recyclerview #viewpropertyanimator #itemtouchhelper

#java #Android #android-recyclerview #viewpropertyanimator #itemtouchhelper

Вопрос:

Я пытаюсь реализовать анимацию для представлений, которая в основном находится за моим RecyclerView. Я использую класс ItemTouchHelper.SimpleCallback для получения событий движения в RecyclerView и переопределяю метод обратного вызова onChildDraw() для распространения анимации.

Эта анимация в основном управляется пользовательскими жестами салфетки. Итак, вот моя проблема.

У меня есть RecyclerView с содержимым электронной почты в виде карточки. В левой и правой частях экрана под этим видом карты есть два изображения. Что-то подобное показано на изображении внутри этой ссылки:

CardView внутри RecyclerView с левым и правым изображениями за представлением карты

Изначально красные и розовые изображения невидимы и будут анимироваться при пролистывании белой карты просмотра. Теперь, когда я провожу пальцем по белой карточке слева и справа, изображения в красном и розовом цветах будут отображаться в масштабе, альфа-анимация. Масштабная анимация начинается с 0.8, а альфа-анимация начинается с 0 до 255. Когда эти две анимации завершатся, красные и розовые изображения будут переведены в направлении прокрутки.

Вот мой код:

 public class ViewItemTouchHelperCallback extends ItemTouchHelper.SimpleCallback {

  private Context mContext;
  private OnViewSwipedListener mOnSwipeListener;

  public interface OnViewSwipedListener {
    void onViewSwiped(float dX);
  }

  public FocusViewItemTouchHelperCallback(int dragDirs, int swipeDirs, Context context, OnViewSwipedListener listener) {
    super(dragDirs, swipeDirs);
    this.mContext = context;
    this.mOnSwipeListener = listener;
  }

  @Override
  public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    return false;
  }

  @Override
  public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
    if(mContext instanceof ViewActivity) {
      if(viewHolder != null) {
        WebView webView = ((ViewAdapter.MailObjectHolder) viewHolder).webViewBody;
        if(webView != null) {
          webView.clearView();
          webView.loadUrl(Constants.ABOUT_BLANK);

          if(swipeDir == ItemTouchHelper.LEFT) {
            ((ViewActivity) mContext).onSwipedLeft();
          } else if(swipeDir == ItemTouchHelper.RIGHT) {
            ((ViewActivity) mContext).onSwipedRight();
          }
        }
      }
    }
  }

  @Override
  public void onChildDraw(Canvas canvas, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
    if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
      if(mOnSwipeListener != null) {
        mOnSwipeListener.onViewSwiped(dX);
      }

      super.onChildDraw(canvas, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    }
  }
}
  

Ниже приведен мой код действия, в котором я получаю обратные вызовы из вышеупомянутого класса:

     @Override
  public void onViewSwiped(float dX) {
    if(dX == 0) {
      mFlagEmailIcon.setVisibility(View.INVISIBLE);
      mNextEmailIcon.setVisibility(View.INVISIBLE);
    } else if(dX > 0) {
      //Left to right - flag email

      float swipedWidth = Math.abs(dX) / mFlagEmailIcon.getMeasuredWidth();
      if(swipedWidth >= 1) {
        LogUtils.log(TAG, "Left to right dX = "   dX   "and Swiped width = "   swipedWidth);
        mFlagEmailIcon.setVisibility(View.VISIBLE);
        float scaleChange = Math.scalb(Math.abs(dX) / mFlagEmailIcon.getMeasuredWidth(), 1);
        if(scaleChange >= 0.8 amp;amp; scaleChange <= 1) {
          mFlagEmailIcon.animate().scaleX(scaleChange).scaleY(scaleChange);
        }

        mFlagEmailIcon.animate().alpha(scaleChange);
      } else {

      }
    } else {
      //Right to left - next email

      float swipedWidth = Math.abs(dX) / mNextEmailIcon.getMeasuredWidth();
      if(swipedWidth >= 1) {
        LogUtils.log(TAG, "Right to left dX = "   dX   "and Swiped width = "   swipedWidth);
        mNextEmailIcon.setVisibility(View.VISIBLE);
        float scaleChange = Math.scalb(Math.abs(dX) / mNextEmailIcon.getMeasuredWidth(), 1);
        if(scaleChange >= 0.8 amp;amp; scaleChange <= 1) {
          mNextEmailIcon.animate().scaleX(scaleChange).scaleY(scaleChange);
        }

        mNextEmailIcon.animate().alpha(scaleChange);
      } else {

      }
    }
  }
  

В приведенном выше коде я пытаюсь анимировать красно-розовое изображение на основе количества нажатий пользователя на белой карточке. Но я действительно застрял в вычислении на основе «dX» и не могу понять, как вычислить значения для анимации.

Примечание: — Когда пользователь проводит пальцем слева направо по карточке, должно быть анимировано красное изображение, а когда пользователь проводит пальцем справа налево по карточке, должно быть анимировано розовое изображение. Анимация изначально будет содержать масштабную и альфа-анимацию, и когда обе анимации завершатся, красное или розовое изображение начнет перемещаться в направлении смахивания.

Кто-нибудь может помочь мне рассчитать значения анимации на основе пользовательского свайпа. Если у вас есть какой-либо запрос, связанный с этим вопросом, пожалуйста, задавайте. Я действительно застрял в этой проблеме, и нигде в Интернете для этого нет решения.

Любая помощь будет оценена. Заранее спасибо.

Комментарии:

1. где / когда вызывается onFocusViewSwiped метод?

2. Извините, это была моя ошибка. Я обновил вопрос. Она вызывается внутри метода ‘onChildDraw()’ расширенного класса ItemTouchHelper.SimpleCallback. Пожалуйста, смотрите выше для изменений.