programing tip

활동 장면 애니메이션 전환 중에 상태 표시 줄과 탐색 표시 줄에 애니메이션이 표시되지 않도록하려면 어떻게합니까?

itbloger 2020. 7. 10. 08:06
반응형

활동 장면 애니메이션 전환 중에 상태 표시 줄과 탐색 표시 줄에 애니메이션이 표시되지 않도록하려면 어떻게합니까?


먼저 내 상태 표시 줄 배경이 짙은 갈색으로 설정되어 있고 내비게이션 바 배경이 기본적으로 검은 색입니다. 머티리얼 라이트 테마를 사용하고 있습니다.

ActivityOptions.makeSceneTransitionAnimation기본 전환을 사용하여 새 활동을 시작하고 있는데 상태 표시 줄과 탐색 표시 줄이 잠시 흰색으로 바뀐 다음 올바른 색상으로 돌아옵니다.

설명서 에 따르면 :

전환 효과를 최대한 활용하려면 호출 및 호출 된 활동 모두에서 창 내용 전환을 활성화해야합니다. 그렇지 않으면 호출 활동이 종료 전환을 시작하지만 창 전환 (스케일 또는 페이드와 같은)이 표시됩니다.

나는 getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);부름과 부름 활동을 모두 사용 하고 있습니다.

마찬가지로 입력 전환을 슬라이드로 변경하면 상태 표시 줄과 탐색 표시 줄에 흰색 배경의 슬라이드 전환이 잠깐 있습니다.

활동 장면 애니메이션 전환 중에 상태 표시 줄과 탐색 표시 줄에 애니메이션이 표시되지 않도록하려면 어떻게합니까?


전환 중에 탐색 / 상태 표시 줄에 애니메이션이 표시되는 것을 방지하기 위해 사용할 수있는 두 가지 방법이 있습니다.

접근법 # 1 : 창의 기본 종료 / 입력 페이드 전환에서 상태 표시 줄 및 탐색 표시 줄을 제외

전환 중에 탐색 / 상태 표시 줄이 페이드 인 및 페이드 아웃되는 이유는 기본적으로 전환이 시작되면 공유되지 않은 모든보기 (탐색 / 상태 표시 줄 배경 포함)가 호출 / 활동에서 각각 페이드 아웃 / 인되기 때문입니다. . 그러나 창의 기본 종료 / 입력 Fade전환 에서 탐색 / 상태 표시 줄 배경을 제외하면이 문제를 쉽게 해결할 수 있습니다 . 액티비티 onCreate()메소드에 다음 코드를 추가하기 만하면됩니다 .

Transition fade = new Fade();
fade.excludeTarget(android.R.id.statusBarBackground, true);
fade.excludeTarget(android.R.id.navigationBarBackground, true);
getWindow().setExitTransition(fade);
getWindow().setEnterTransition(fade);

이 전환은 XML을 사용하여 활동 주제 (예 res/transition/window_fade.xml: 자신의 파일) 에서 선언 할 수도 있습니다 .

<?xml version="1.0" encoding="utf-8"?>
<fade xmlns:android="http://schemas.android.com/apk/res/android">
    <targets>
        <target android:excludeId="@android:id/statusBarBackground"/>
        <target android:excludeId="@android:id/navigationBarBackground"/>
    </targets>
</fade>

접근 # 2 : 상태 표시 줄 및 탐색 표시 줄을 공유 요소로 추가

이 접근 방식은 klmprt의 답변을 바탕으로 거의 나에게 도움이되었지만 여전히 몇 가지 수정 작업이 필요했습니다.

내 호출 활동에서 다음 코드를 사용하여 활동을 시작했습니다.

View statusBar = findViewById(android.R.id.statusBarBackground);
View navigationBar = findViewById(android.R.id.navigationBarBackground);

List<Pair<View, String>> pairs = new ArrayList<>();
if (statusBar != null) {
  pairs.add(Pair.create(statusBar, Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME));
}
if (navigationBar != null) {
  pairs.add(Pair.create(navigationBar, Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME));
}
pairs.add(Pair.create(mSharedElement, mSharedElement.getTransitionName()));

Bundle options = ActivityOptions.makeSceneTransitionAnimation(activity, 
        pairs.toArray(new Pair[pairs.size()])).toBundle();
startActivity(new Intent(context, NextActivity.class), options);

지금까지 이것은 klmprt가 그의 대답에서 제안한 것과 본질적으로 동일합니다. 그러나 onCreate()전환 중에 상태 표시 줄과 탐색 표시 줄이 "깜박이는"것을 방지하기 위해 호출 된 활동의 메소드에 다음 코드를 추가해야했습니다 .

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_next);

    // Postpone the transition until the window's decor view has
    // finished its layout.
    postponeEnterTransition();

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

상태 표시 줄과 탐색 표시 줄 배경을 공유 요소로 추가하면 창의 기본 종료 / 입력 페이드 전환 위에 강제로 그려 지므로 전환 중에 페이드되지 않습니다. 이 방법에 대한 자세한 내용은 이 Google+ 게시물 에서 확인할 수 있습니다 .


Completely prevent Activity transitions from interfering with shared element transitions:

On the exiting activity, call getWindow().setExitTransition(null);

On the entering activity, call getWindow().setEnterTransition(null);

From https://stackoverflow.com/a/34907685/967131

I suspect this may have side effects, but don't know for sure. It is dead simple and works though.

Prevent specific elements from blinking:

I started with Alex Lockwood's answer and did a fair bit of experimentation to try to get it working. The core of it is correct, although I didn't need the code he suggests for the receiving Activity, but I ran into some problems by calling it in a Fragment (instead of an Activity) and by setting a toolbar as the action bar.

Oh, the Fragment thing? I saw a lot of comments that trying to retrieve references to the status bar and navigation bar were null. The same thing happened to me as well, until I realized I wouldn't find those in the Fragment's layout... they were above that level. Hence, the code below to get the decor view from the Activity and search that. Then I found them with no problem.

In the end, I developed this utility method:

public static Bundle transitionOptions(Activity activity, int transitionViewResId, int transitionNameResId) {
   if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {
       return null;
   }

   View decorView = activity.getWindow().getDecorView();
   View statusBar = decorView.findViewById(android.R.id.statusBarBackground);
   View navigationBar = decorView.findViewById(android.R.id.navigationBarBackground);
   View appBarLayout = decorView.findViewById(**R.id.appbarlayout**);
   View transitionView = decorView.findViewById(transitionViewResId);
   String transitionName = activity.getString(transitionNameResId);

   List<Pair<View, String>> pairs = new ArrayList<>();
   pairs.add(Pair.create(statusBar, Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME));
   pairs.add(Pair.create(navigationBar, Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME));
   if (appBarLayout != null) {
       pairs.add(Pair.create(appBarLayout, activity.getString(**R.string.transition_appbarlayout**)));
   }
   pairs.add(Pair.create(transitionView, transitionName));
   //noinspection unchecked - we're not worried about the "unchecked" conversion of List<Pair> to Pair[] here
   return ActivityOptionsCompat.makeSceneTransitionAnimation(activity, pairs.toArray(new Pair[pairs.size()]))
           .toBundle();
}

Note R.string.transition_appbarlayout and R.id.appbarlayout. These IDs are arbitrary, as long as they match what your code uses. In my XML, I layout the custom action bar like so (edited down to the essentials):

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.AppBarLayout
    android:id="**@+id/appbarlayout**"
    android:transitionName="**@string/transition_appbarlayout**">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"/>
</android.support.design.widget.AppBarLayout>

If you don't use a Toolbar like this, that part can be removed from the utility method.

Then you would call it in your Fragment like so:

startActivity(intent, UIUtils.transitionOptions(getActivity(),
                        R.id.**my_view**,
                        R.string.**transition_my_view**));

Using whatever values you want, as long as it matches your XML.

This prevents the status bar, the tool bar and the navigation bar (back / home / recent apps buttons) from flashing during the transition. The rest of the Activity transition is normal.

In my case, our app theme has a android:windowBackground of blue. This causes a blue flash in the transition, which is quite frustrating. But rather than make a change that affects the entire app like that, for now I am going with the first, quick and dirty option.


You need to share them in ActivityOptions.makeSceneTransitionAnimation.

E.g:

ActivityOptions.makeSceneTransitionAnimation(... Pair.create(activity.findViewById(android.R.id.window_status_bar), Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME) 

(excuse the psuedo; I don't have the exact android.R.id value on hand)

You can run an appropriate transition after having shared the views.


As far as I understand this is caused by activity transition overlap. To overcome this issue I have used the following values in the onCreate() methods of both activities:

getWindow().setAllowEnterTransitionOverlap(false);
getWindow().setAllowReturnTransitionOverlap(false);

I just had this same issue, and the answers appear to be missing a critical piece to the puzzle. Remember that on a shared element transition, everything happens in the Destination Activity.

In order to remove the flashing effect, simply add the following to the activity being called:

Fade fade = new Fade();
fade.excludeTarget(android.R.id.statusBarBackground, true);
fade.excludeTarget(android.R.id.navigationBarBackground, true);

getWindow().setEnterTransition(fade);
getWindow().setExitTransition(fade);

This should solve your problem!


getWindow().setEnterTransition(null); on the Entering transition removed the white overlay for me.


Here is how I did it. I share both the Status Bar and the Navigation Bar in the SharedElementTransition along with an ImageView :

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  View imageView = view.findViewById(R.id.iv);
  Resources resources = view.getResources();
  imageView.setTransitionName(resources.getString(R.string.transition_image_thumbnail));

  Pair<View, String> p1 = Pair.create(imageView, resources.getString(R.string.transition_image_thumbnail));

  Window window = getActivity().getWindow();

  View navigationBar = getActivity().findViewById(android.R.id.navigationBarBackground);
  View statusBar = getActivity().findViewById(android.R.id.statusBarBackground);

  Pair<View, String> p2 = Pair.create(statusBar, statusBar.getTransitionName());
  Pair<View, String> p3 = Pair.create(navigationBar, navigationBar.getTransitionName());

  ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(),
          p1, p2, p3);

  ActivityCompat.startActivity(getActivity(), intent, options.toBundle());
} else {
  startActivity(intent);
}

참고URL : https://stackoverflow.com/questions/26600263/how-do-i-prevent-the-status-bar-and-navigation-bar-from-animating-during-an-acti

반응형