docs: @Nullable
      public Animator onDisappear(@NonNull final ViewGroup sceneRoot,
                                  @Nullable TransitionValues startValues,
                                  int startVisibility,
                                  @Nullable TransitionValues endValues,
                                  int endVisibility) {
          if ((mMode & MODE_OUT) != MODE_OUT) {
              return null;
          }
  
          View startView = (startValues != null) ? startValues.view : null;
          View endView = (endValues != null) ? endValues.view : null;
          View overlayView = null;
          View viewToKeep = null;
          boolean reusingCreatedOverlayView = false;
          boolean createOverlayFromStartView = false;
          if (endView == null || endView.getParent() == null) {
              if (endView != null) {
                  // endView was removed from its parent - add it to the overlay
                  overlayView = endView;
              } else if (startView != null) {
                  createOverlayFromStartView = true;
              }
          } else {
              // visibility change
              if (endVisibility == View.INVISIBLE) {
                  viewToKeep = endView;
              } else {
                  // Becoming GONE
                  if (startView == endView || startView == null) {
                      viewToKeep = endView;
                  } else {
                      createOverlayFromStartView = true;
                  }
              }
          }
  
          if (createOverlayFromStartView) {
              // endView does not exist. Use startView only under certain
              // conditions, because placing a view in an overlay necessitates
              // it being removed from its current parent
              if (startView.getTag(R.id.overlay_view) != null) {
                  // we've already created overlay for the start view.
                  // it means that we are applying two visibility
                  // transitions for the same view
                  overlayView = (View) startView.getTag(R.id.overlay_view);
                  reusingCreatedOverlayView = true;
              } else if (startView.getParent() == null) {
                  // no parent - safe to use
                  overlayView = startView;
              } else if (startView.getParent() instanceof View) {
                  View startParent = (View) startView.getParent();
                  TransitionValues startParentValues = getTransitionValues(startParent, true);
                  TransitionValues endParentValues = getMatchedTransitionValues(startParent,
                      true);
                  VisibilityInfo parentVisibilityInfo =
                      getVisibilityChangeInfo(startParentValues, endParentValues);
                  if (!parentVisibilityInfo.visibilityChange) {
                      overlayView = TransitionUtils.copyViewImage(sceneRoot, startView, startParent);
                  } else if (startParent.getParent() == null) {
                      int id = startParent.getId();
                      if (id != View.NO_ID && sceneRoot.findViewById(id) != null
                          && mCanRemoveViews) {
                          // no parent, but its parent is unparented  but the parent
                          // hierarchy has been replaced by a new hierarchy with the same id
                          // and it is safe to un-parent startView
                          overlayView = startView;
                      }
                  }
              }
          }
  
          if (overlayView != null && startValues != null) {
              // TODO: Need to do this for general case of adding to overlay
              final int[] screenLoc = (int[]) startValues.values.get(PROPNAME_SCREEN_LOCATION);
              if (!reusingCreatedOverlayView) {
                  ViewGroupOverlayUtils.addOverlay(sceneRoot, overlayView, screenLoc[0], screenLoc[1]);
              }
              Animator animator = onDisappear(sceneRoot, overlayView, startValues, endValues);
              if (animator == null) {
                  ViewGroupOverlayUtils.removeOverlay(sceneRoot, overlayView);
              } else if (!reusingCreatedOverlayView) {
                  final View finalOverlayView = overlayView;
                  final View finalStartView = startView;
                  finalStartView.setTag(R.id.overlay_view, finalOverlayView);
                  addListener(new TransitionListenerAdapter() {
  
                      @Override
                      public void onTransitionPause(@NonNull Transition transition) {
                          ViewGroupOverlayUtils.removeOverlay(sceneRoot, finalOverlayView);
                      }
  
                      @Override
                      public void onTransitionResume(@NonNull Transition transition) {
                          if (finalOverlayView.getParent() == null) {
                              ViewGroupOverlayUtils.addOverlay(sceneRoot, finalOverlayView, screenLoc[0], screenLoc[1]);
                          }
                          else {
                              cancel();
                          }
                      }
  
                      @Override
                      public void onTransitionEnd(@NonNull Transition transition) {
                          finalStartView.setTag(R.id.overlay_view, null);
                          ViewGroupOverlayUtils.removeOverlay(sceneRoot, finalOverlayView);
                          transition.removeListener(this);
                      }
                  });
              }
              return animator;
          }
  
          if (viewToKeep != null) {
              int originalVisibility = -1;
              final boolean isForcedVisibility = mForcedStartVisibility != -1 ||
                      mForcedEndVisibility != -1;
              if (!isForcedVisibility) {
                  originalVisibility = viewToKeep.getVisibility();
                  ViewUtils.setTransitionVisibility(viewToKeep, View.VISIBLE);
              }
              Animator animator = onDisappear(sceneRoot, viewToKeep, startValues, endValues);
              if (animator != null) {
                  DisappearListener disappearListener = new DisappearListener(viewToKeep,
                          endVisibility, isForcedVisibility);
                  animator.addListener(disappearListener);
                  AnimatorUtils.addPauseListener(animator, disappearListener);
                  addListener(disappearListener);
              } else if (!isForcedVisibility) {
                  ViewUtils.setTransitionVisibility(viewToKeep, originalVisibility);
              }
              return animator;
          }
          return null;
      }