Подтвердить что ты не робот

Переход активности элементарного элемента на андроид 5

Я хотел настроить переход с общим элементом при переходе от одного действия к другому.

Первая операция имеет RecyclerView с элементами. Когда элемент щелкнут, этот элемент должен анимироваться для нового действия.

Итак, я установил       android: transitionName = "item" как в представлении конечной активности, так и в представлениях вида ресайклеров.

Я также использую этот код при переходе к следующему действию:

this.startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this, itemView, "boomrang_item").toBundle());

При нажатии элемента он переходит правильно и отображается новое представление. Это действительно приятно. Однако, когда я нажимаю кнопку "Назад". Иногда это работает нормально, но большую часть времени моя активность падает со следующей командой:

   java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.ViewGroup.transformMatrixToGlobal(android.graphics.Matrix)' on a null object reference
            at android.view.GhostView.calculateMatrix(GhostView.java:95)
            at android.app.ActivityTransitionCoordinator$GhostViewListeners.onPreDraw(ActivityTransitionCoordinator.java:845)
            at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:847)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1956)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1054)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5779)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
            at android.view.Choreographer.doCallbacks(Choreographer.java:580)
            at android.view.Choreographer.doFrame(Choreographer.java:550)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

Что я делаю неправильно? Это похоже на ошибку в android 5

4b9b3361

Ответ 1

Я сталкиваюсь с той же проблемой и замечаю, что произошел сбой, если исходный общий элемент больше не отображается на предыдущем экране, когда вы возвращаетесь назад (вероятно, это последний элемент на экране в портрете, но после переключения на пейзаж он не более длинный вид), и, таким образом, переход не имеет возможности вернуть общий элемент.

Мое обходное решение состоит в том, чтобы удалить обратный переход (во втором действии), если экран был повернут перед возвратом, но я уверен, что должен быть лучший способ справиться с этим:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    mOrientationChanged = !mOrientationChanged;
}

@Override
public void supportFinishAfterTransition() {
    if (mOrientationChanged) {
        /**
         * if orientation changed, finishing activity with shared element
         * transition may cause NPE if the original element is not visible in the returned
         * activity due to new orientation, we just finish without transition here
         */
        finish();
    } else {
        super.supportFinishAfterTransition();
    }
}

Ответ 2

Попробуйте удалить любые теги слияния xml, которые могут иметься в последнем представлении активности. Я заметил, что переход к представлению, содержащему тег merge, в котором переходный элемент является прямым дочерним элементом тега merge, вызовет эту ошибку, но следует заменить тег merge другим контейнером, например CardView, анимацией работает просто отлично. Также убедитесь, что между представлениями перехода в представлениях существует соотношение 1:1.

UPDATE: Я снова столкнулся с этой проблемой при выполнении перехода активности, нажав кнопку "Назад", чтобы вернуться к первоначальной активности, а затем повторю попытку перехода. Я обращался к прямому родительскому "компоненту перехода" (A RelativeLayout) по id, с вызовом findViewById(), а затем вызывал removeAllViews(). Я закончил тем, что менял код, чтобы вызвать 'removeAllViews()' на более высоком предке, чем родительский, также удалил тег из элемента, который должен был заменить "переходный компонент" после загрузки страницы. Это облегчило мою проблему.

Ответ 3

Если вы используете Proguard, попробуйте добавить это в свой файл правил. У меня была такая же проблема, и она работает?

-keep public class android.app.ActivityTransitionCoordinator

Ответ 4

Удостоверьтесь, что просмотр, в который вы переходите во вторую активность, не является корневым макетом. Вы можете просто обернуть его в FrameLayout с прозрачным windowBackground.

Ответ 5

Убедитесь, что элемент "itemView", который вы передаете при переходе, - это щелчок (полученный при обратном вызове onClick())

Ответ 6

У меня была эта же проблема, для меня это вызвано повторным выполнением обновлений после/во время первого перехода на выход. Я думаю, что представление об общем элементе затем иногда перерабатывалось, что означает, что он больше не будет доступен для анимации перехода, следовательно, сбой (как правило, при обратном преобразовании, но иногда на выходе). Я решил это, заблокировав обновления, если действие приостановлено (используется флаг isRunning) - обратите внимание, что он приостанавливается, но не останавливается, поскольку он все еще отображается в фоновом режиме. Кроме того, я заблокировал процесс обновления, если переход был запущен. Я нашел достаточно для прослушивания этого обратного вызова:

Transition sharedElementExitTransition = getWindow().getSharedElementExitTransition();
        if (sharedElementExitTransition != null) {
            sharedElementExitTransition.addListener(.....);
        }

В качестве окончательной меры, хотя я не уверен, что это имело значение, я также сделал recyclerView.setLayoutFrozen(true)/recyclerView.setLayoutFrozen(false) в onTransitionStart/onTransitionEnd.

Ответ 7

То, что я придумал, заключается в том, чтобы не переходить к Activity с RecyclerView или изменять переход с чем-то другим.

Отключить все обратные переходы:

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void finishAfterTransition() {
    finish();
}

Или, если вы хотите отключить возврат только общих элементов, и сможете установить свой собственный возврат:

// Track if finishAfterTransition() was called
private boolean mFinishingAfterTransition;

@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mFinishingAfterTransition = false;
}

public boolean isFinishingAfterTransition() {
    return mFinishingAfterTransition;
}

@Override
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void finishAfterTransition() {
    mFinishingAfterTransition = true;
    super.finishAfterTransition();
}

public void clearSharedElementsOnReturn() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        TransitionUtilsLollipop.clearSharedElementsOnReturn(this);
    }
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static final class TransitionUtilsLollipop {

    private TransitionUtilsLollipop() {
        throw new UnsupportedOperationException();
    }

    static void clearSharedElementsOnReturn(@NonNull final BaseActivity activity) {
        activity.setEnterSharedElementCallback(new SharedElementCallback() {

            @Override
            public void onMapSharedElements(final List<String> names,
                    final Map<String, View> sharedElements) {
                super.onMapSharedElements(names, sharedElements);
                if (activity.isFinishingAfterTransition()) {
                    names.clear();
                    sharedElements.clear();
                }
            }
        });
    }

Благодаря тому, что реализовано в базовой деятельности, вы можете легко использовать его в onCreate()

@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    clearSharedElementsOnReturn(this);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        // set your own transition
        getWindow().setReturnTransition(new VerticalGateTransition());
    }
}

Ответ 8

У меня была такая же ошибка, моя была вызвана теми же соображениями позади ответа на гидру, но была вызвана клавиатурой, скрывающей общий элемент, к которому переход возвращался.

Мое обходное решение заключалось в том, чтобы программно закрыть клавиатуру до завершения операции, чтобы общий элемент предыдущей активности не был закрыт.

View view = this.getCurrentFocus();
if (view != null) {  
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
supportFinishAfterTransition();

Ответ 9

Как @Fabio Rocha, убедитесь, что itemView извлекается из ViewHolder.

Вы можете получить ViewHolder по позиции через

mRecyclerView.findViewHolderForAdapterPosition(position);

Ответ 10

Причина этого на самом деле довольно проста: Когда вы переходите к родительскому действию или фрагменту, Вид еще не существует (может быть по многим причинам).
Итак, что вы хотите сделать, это отложить переход Enter, пока не появится представление.

Моя работа заключается в вызове следующей функции в onCreate() в моем фрагменте (но также работает в Activity):

private void checkBeforeTransition() {
    // Postpone the transition until the window decor view has
    // finished its layout.
    getActivity().supportPostponeEnterTransition();

    final View decor = getActivity().getWindow().getDecorView();
    decor.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            decor.getViewTreeObserver().removeOnPreDrawListener(this);
            getActivity().supportStartPostponedEnterTransition();
            return true;
        }
    });
}

Ответ 11

Я столкнулся с той же проблемой, на самом деле я использовал firebase, и у меня есть список информации, и когда пользователь нажимает на нее, он вызывает функцию detailActivity с sharedAnimation в этом действии, я обновлял ее, как видно, используя firebase, чтобы событие firebase обновляло элемент списка, как показано, в этом случае эта проблема вызывается, поскольку просмотрщик-ресайлер просматривает экран макет.

и он вызывает исключение, потому что этот идентификатор перехода, который мы передали ему, больше не был, поэтому я решу эту проблему с помощью этого метода.

onPause() Я заморозил макет и onResume() установил его как false,

 @Override
public void onPause() {
    super.onPause();
    mRecycler.setLayoutFrozen(true);
}

@Override
public void onResume() {
    super.onResume();
    mRecycler.setLayoutFrozen(false);
}

И он работает.