Переход с вложенным фрагментом создает заметный лаг вместо плавного перехода, как сгладить этот переход? - PullRequest
0 голосов
/ 03 января 2019

У меня проблема с переходом между фрагментами. Переход между фрагментами A и B очень прерывистый, как видно из этого GIF: https://imgur.com/a/PDogrxV. Если вы заметите, когда я нажимаю потрясающую кнопку, переход останавливается в середине экрана. Я попытался отладить его, замедляя анимацию, и вот результат (с боковым переходом): https://imgur.com/a/1ipQvfW

У меня есть фрагмент NavigationBar, в котором есть FrameLayout, в который я добавляю свой recyclerViewFragment (который наследуется от BaseFragment). Моя цель на самом деле - сгладить переход, чтобы не было «прерывистости» между фрагментом A (без сопряженного устройства) и B, который содержит представление рециркулятора, как показано в первой ссылке GIF,

Для справки:

Пример NavigationController (который наследует от моего фрагмента NavBar):

 public class ExampleController extends NavBarFragment {

  public static ExampleController newInstance() {
    ExampleController fragment = new ExampleController();
    fragment.setArguments(fragment.createInitBundle());
    return fragment;
   }

   @Override
   protected BaseFragment rootFragment() {
       return RecyclerViewFragment.newInstance();
   }

   @Override
   public Bundle createInitBundle() {
      return new Bundle();
   }

}

Метод rootFrament () вызывается в методе initializeLayout, найденном в NavBarFragment (который вызывается в OnCreateView ()) - это просто для придания некоторого контекста:

     @Override
     protected void initializeLayout(View view) {
        super.initializeLayout(view);
        this.toolbar.setNavigationOnClickListener(this::navigationButtonClick);
               this.toolbar.setOnMenuItemClickListener(this::navigationMenuClick);

        progressBar.getLayoutParams().height = 0;
        progressBar.requestLayout();

        this.setContentFragment(view, this.rootFragment());
     }

и setContentFragment вызывает диспетчер транзакций:

private void setContentFragment(View view, BaseFragment frag) {
  Context context = getActivity() != null ?    getActivity().getApplicationContext() : null;
  if (frag == null || view == null || context == null) {
    return;
  }

  this.currentFragment = frag;

   configureUIComponents(context, frag, 0);
   getChildFragmentManager().beginTransaction()
         .replace(view.findViewById(R.id.main_container).getId(),    frag, createFragmentTag(0))
         .commit();
 }

Пример RecyclerViewFragment:

public class RecyclerViewFragment extends BaseRecyclerViewFragment {

  public static RecyclerViewFragment newInstance(){

       //navbar implement
       Bundle args = new Bundle();
       args.putString(NavigationBarConfig.KEY_NAV_BAR_TITLE, "Paired Devices");
       args.putBoolean(NavigationBarConfig.KEY_SHOW_NAV_BAR, true);
      args.putBoolean(FloatingActionButtonConfig.KEY_SHOW_FAB_BUTTON, true);
       RecyclerViewFragment fragment = new RecyclerViewFragment();
       fragment.setArguments(args);
       return fragment;
   }. 

Я пробовал несколько вещей: 1) Я пытался использовать слушатели для «конца» перехода, чтобы дождаться загрузки данных. Это было основано на вопросе переполнения стека: Неправильный переход вложенных фрагментов . Я реализовал это следующим образом (я не буду делиться всем кодом по причинам). Метод didDisappear / didAppear () затем используется при загрузке моей модели:

@Override
public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
Animator animator = null;

// Check for "Show" Transition ids
if (showTransitionAnimationIds.contains(nextAnim)) {
  animator = AnimatorInflater.loadAnimator(getActivity(), nextAnim);
  if (animator != null && enter) {
    animator.addListener(new TransitionAnimatorListener() {
      @Override
      public void onAnimationStart(Animator animation) {
        if (previousFragment != null) {
          previousFragment.willDisappear();
        }
        willAppear();
      }

      @Override
      public void onAnimationEnd(Animator animation) {
        transitionDone.set(true);
        if (previousFragment != null) {
          previousFragment.didDisappear();
        }
        didAppear();
      }
    });
  }
} else if (hideTransitionAnimationIds.contains(nextAnim)) {
  animator = AnimatorInflater.loadAnimator(getActivity(), nextAnim);
  if (animator != null && !enter) {
    animator.addListener(new TransitionAnimatorListener() {
      @Override
      public void onAnimationStart(Animator animation) {
        if (previousFragment != null) {
          previousFragment.willAppear();
        }
        willDisappear();
      }

      @Override
      public void onAnimationEnd(Animator animation) {
        if (previousFragment != null) {
          previousFragment.didAppear();
        }
        didDisappear();
      }
    });
  }
}

Я использую этот метод для загрузки модели:

protected void waitForTransition() {
  if (transitionDone != null) {
    try {
     transitionDone.get();
    }  catch (Exception e) {
     e.printStackTrace();
   }
  }
 }

Что обычно помогает мне "подождать", пока анимация не закончится, прежде чем я загружу свои модели. Я думал, что это проблема.

Моя цель - сгладить анимацию. Мне известен трюк «предоставить изображение» (перефразировать), показанный в этом вопросе: Вложенные фрагменты исчезают во время анимации перехода , но я искал что-то немного чище. Я думал, что может быть возможность создать два фрагмента на лету? Т.е.: у меня есть пустой макет с 2 frameLayout, в который я мог бы просто вставить два фрагмента во время выполнения. Хотя я этого не пробовал, он не выглядит очень модульным.

...