मैं एक गतिविधि दृश्य एनीमेशन संक्रमण के दौरान स्टेटस बार और नेविगेशन बार को एनिमेट करने से कैसे रोकूँ?


127

सबसे पहले, मेरी स्थिति पट्टी पृष्ठभूमि गहरे भूरे रंग के लिए सेट है, और मेरा नेविगेशन बार पृष्ठभूमि डिफ़ॉल्ट काला है। मैं मटेरियल लाइट थीम का उपयोग कर रहा हूं।

मैं ActivityOptions.makeSceneTransitionAnimationडिफ़ॉल्ट बदलावों के साथ एक नई गतिविधि शुरू कर रहा हूं , और मैं ध्यान देता हूं कि स्थिति और नेविगेशन बार संक्षिप्त रूप से सफेद और फिर सही रंगों में वापस आते हैं।

प्रलेखन के अनुसार :

एक संक्रमण का पूरा प्रभाव प्राप्त करने के लिए, आपको कॉलिंग और कॉलिंग गतिविधियों दोनों पर विंडो सामग्री संक्रमण सक्षम करना होगा। अन्यथा, कॉलिंग गतिविधि निकास संक्रमण शुरू कर देगी, लेकिन फिर आपको एक विंडो संक्रमण दिखाई देगा (जैसे स्केल या फीका)

मैं getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);कॉलिंग और कॉलिंग गतिविधियों दोनों पर उपयोग कर रहा हूं ।

इसी तरह, यदि मैं एक स्लाइड में प्रवेश संक्रमण को बदलता हूं, तो स्थिति और नेविगेशन बार दोनों को एक सफेद पृष्ठभूमि के साथ स्लाइड संक्रमण होता है।

मैं एक गतिविधि दृश्य एनीमेशन संक्रमण के दौरान स्टेटस बार और नेविगेशन बार को एनिमेट करने से कैसे रोकूँ?

जवाबों:


217

दो दृष्टिकोण हैं जिनका उपयोग आप कर सकते हैं कि मैं संक्रमण के दौरान नेविगेशन / स्थिति पट्टी को एनिमेट करने से रोकने के लिए जानता हूं:

दृष्टिकोण # 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);

यह संक्रमण एक्सएमएल का उपयोग करके गतिविधि के विषय में भी घोषित किया जा सकता है (यानी अपनी 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+ पोस्ट में मिल सकती है ।


14
कोई भी विचार क्यों FindViewById (android.R.id.navigationBarBackground) लॉलीपॉप पर अशक्त लौट रहा है? मैं
radzio

3
दृष्टिकोण # 2 काम करता है, लेकिन संक्रमण होने पर अभी भी एक झिलमिलाहट (गतिविधि में) है। स्थिति पट्टी और नेविगेशन बार अब और फ़्लिकर नहीं करते हैं।
अक्षत

16
@alex यह मेरे लिए लगभग पूरी तरह से काम कर रहा था जब तक कि हमने android.support.design.widget.TabLayout और android.support.design.widget.Appget.AppBarLayout के साथ नई समर्थन लाइब्रेरी में स्विच नहीं किया था - अब टिमटिमा रहा है
Noa Drach

6
android.R.id.navigationBarBackground आपको सैमसंग या एचटीसी डिवाइस पर एक NPE दे सकता है क्योंकि उनके पास ऑन लाइन नेविगेशन बार नहीं है। साझा तत्वों के रूप में उन्हें जोड़ने से पहले एक अशक्त जांच करें
लड़का

8
मैं एंड्रॉइड नूगट के साथ नेक्सस 6 पर इस समाधान की कोशिश कर रहा हूं। लेकिन दोनों दृष्टिकोण मेरे लिए काम नहीं कर रहे हैं।
परदीप क्र

4

साझा तत्व संक्रमण के साथ हस्तक्षेप से गतिविधि संक्रमण को पूरी तरह से रोकें:

बाहर निकलने की गतिविधि पर, कॉल getWindow ()। SetExitTransition (नल);

प्रवेश गतिविधि पर, कॉल getWindow ()। SetEnterTransition (नल);

से https://stackoverflow.com/a/34907685/967131

मुझे संदेह है कि इसके दुष्प्रभाव हो सकते हैं, लेकिन यह निश्चित रूप से नहीं पता है। यह मृत सरल है और यद्यपि काम करता है।

निमिष से विशिष्ट तत्वों को रोकें:

मैंने एलेक्स लॉकवुड के जवाब के साथ शुरुआत की और इसे काम में लाने की कोशिश करने के लिए बहुत कुछ प्रयोग किया। इसका मूल सही है, हालाँकि मुझे प्राप्त गतिविधि के लिए उनके द्वारा सुझाए गए कोड की आवश्यकता नहीं थी, लेकिन मैं इसे कुछ समस्याओं में एक फ्रैगमेंट (गतिविधि के बजाय) में और टूलबार को एक्शन बार के रूप में सेट करके चला गया।

बेनाम: ओह, बात बात है? मैंने बहुत सारी टिप्पणियाँ देखीं जो स्टेटस बार और नेविगेशन बार के संदर्भों को पुनः प्राप्त करने की कोशिश कर रही थीं। मेरे साथ भी ऐसा ही हुआ, जब तक मुझे एहसास हुआ कि मैं उन लोगों को फ्रेग्मेंट के लेआउट में नहीं पाऊंगा ... वे उस स्तर से ऊपर थे। इसलिए, गतिविधि से सजावट दृश्य प्राप्त करने के लिए नीचे दिए गए कोड और खोज करें। तब मैंने उन्हें बिना किसी समस्या के पाया।

अंत में, मैंने इस उपयोगिता विधि को विकसित किया:

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();
}

नोट R.string.transition_appbarlayout और R.id.appbarlayout । जब तक वे आपके कोड का उपयोग करते हैं, तब तक ये आईडी मनमानी होती हैं। मेरे XML में, मैं कस्टम एक्शन बार को लेआउट की तरह (आवश्यक को नीचे संपादित) करता हूं:

<?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>

यदि आप इस तरह एक टूलबार का उपयोग नहीं करते हैं, तो उस भाग को उपयोगिता विधि से हटाया जा सकता है।

तब आप इसे अपने फ्रैगमेंट में जैसे कहेंगे:

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

जब तक यह आपके XML से मेल खाता है, तब तक आप जो भी मान चाहते हैं उसका उपयोग करना

यह स्थिति पट्टी, टूल बार और नेविगेशन बार (बैक / होम / हाल के ऐप्स बटन) को संक्रमण के दौरान चमकने से रोकता है। बाकी गतिविधि संक्रमण सामान्य है।

मेरे मामले में, हमारे ऐप की थीम android:windowBackgroundनीले रंग की है। यह संक्रमण में एक नीली चमक का कारण बनता है, जो काफी निराशाजनक है। लेकिन इसके बजाय एक परिवर्तन करें जो पूरे ऐप को प्रभावित करता है जैसे, अब मैं पहले, त्वरित और गंदे विकल्प के साथ जा रहा हूं।


3

आपको उन्हें साझा करने की आवश्यकता है ActivityOptions.makeSceneTransitionAnimation.

उदाहरण के लिए:

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

(psuedo का बहाना; मेरे पास सटीक android.R.id मान नहीं है)

विचारों को साझा करने के बाद आप एक उपयुक्त संक्रमण चला सकते हैं।


क्या यह आपके लिए काम करता है? मैंने यह कोशिश की और स्थिति बार और नेविगेशन बार अभी भी संक्रमण के दौरान सफेद चमकती है।
rlay3

हां, इसने मेरे लिए काम किया। क्या आप सुनिश्चित हैं कि कोई अन्य दृश्य नहीं है जो उन्हें अस्थायी रूप से ओवरलैप कर रहा हो सकता है? क्या आपने समस्या को अलग करने के लिए 'सैंडबॉक्स' वातावरण में एक साधारण गतिविधि संक्रमण स्थापित करने की कोशिश की है?
klmprt

@klmprt मुझे लगता है कि आपको इसे काम करने के लिए प्रवेश संक्रमण को स्थगित करने की भी आवश्यकता है ... मैं केवल विचारों को साझा करने से स्थिति / नेविगेशन बार को एनिमेट करने से रोकने में सक्षम नहीं था। मुझे लगता है कि आपको विंडो का सजावट देखने के लिए उसके लेआउट को पूरा करने से पहले प्रतीक्षा करने की आवश्यकता है ताकि आप प्रवेश संक्रमण शुरू कर सकें।
एलेक्स लॉकवुड

@klmprt मेरा जवाब अभी भी संबोधित नहीं करता है, हालांकि यह है कि संक्रमण के दौरान एक्शन बार की पृष्ठभूमि के रंग को कैसे रोका जाए। यदि दोनों गतिविधि एक ही एक्शन बार बैकग्राउंड कलर को साझा करते हैं, तो एक्शन बार का बैकग्राउंड कलर चेतन को दिखाई देगा क्योंकि कॉलिंग एक्टिविटी बार धीरे-धीरे फीका पड़ जाता है और एक्टिविटी एक्शन बार धीरे से फीका पड़ जाता है। क्या आपको पता है कि इसे कैसे प्राप्त किया जा सकता है। मुद्दा?
एलेक्स लॉकवुड

@ चकमा वास्तव में, मुझे लगता है कि एक और भी बेहतर समाधान है। आप बस नेविगेशन / स्टेटस बार पृष्ठभूमि को विंडो के डिफ़ॉल्ट निकास में लक्ष्य के रूप में बाहर कर सकते हैं / फीका संक्रमण दर्ज कर सकते हैं। विवरण के लिए मेरा अद्यतन उत्तर देखें।
एलेक्स लॉकवुड

3

जहां तक ​​मैं समझता हूं कि यह गतिविधि संक्रमण ओवरलैप के कारण होता है। इस समस्या को दूर करने के लिए मैंने onCreate()दोनों गतिविधियों के तरीकों में निम्नलिखित मूल्यों का उपयोग किया है :

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

3

मेरे पास बस यही मुद्दा था, और जवाब पहेली को एक महत्वपूर्ण टुकड़ा याद आ रहे हैं। याद रखें कि एक साझा तत्व संक्रमण पर, सब कुछ गंतव्य गतिविधि में होता है ।

चमकती प्रभाव को हटाने के लिए, बस निम्नलिखित गतिविधि को जोड़ने के लिए कहा जा रहा है:

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

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

इससे आपकी समस्या का समाधान हो जाना चाहिए!


नमस्ते। क्या यह शीर्ष उत्तर में # 1 दृष्टिकोण के समान नहीं है?
rlay3

@ rlay3 पूरी तरह से नहीं। जहाँ तक मैं बता सकता हूँ, उन्होंने कभी इस तथ्य का उल्लेख नहीं किया कि यह केवल गंतव्य गतिविधि में निर्धारित किया जाना चाहिए।
ल्यूक वेगनर

हे @LukeWaggoner क्या आप मेरी यह मदद कर सकते हैं: stackoverflow.com/questions/50189286/…
blackHawk

आपको स्थिति और नेविगेशनबार को गतिविधि, कॉलर और कॉल दोनों में शामिल नहीं करना चाहिए।
जियोवन्नी डि ग्रेगोरियो


0

यहाँ देखें कि मैंने यह कैसे किया। मैं दोनों का हिस्सा Status Barहै और Navigation Barमें SharedElementTransitionएक के साथ 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);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.