ट्रांज़िशन का इस्तेमाल करके, लेआउट में बदलावों को ऐनिमेट करें

Compose का इस्तेमाल करके मैसेज लिखना
Android के लिए, Jetpack Compose को यूज़र इंटरफ़ेस (यूआई) टूलकिट के तौर पर सुझाया जाता है. Compose में ऐनिमेशन इस्तेमाल करने का तरीका जानें.

Android का ट्रांज़िशन फ़्रेमवर्क, आपको स्टार्टिंग और एंडिंग लेआउट उपलब्ध कराकर, अपने यूज़र इंटरफ़ेस (यूआई) में हर तरह की मोशन को ऐनिमेट करने देता है. आपके पास यह चुनने का विकल्प होता है कि आपको किस तरह का ऐनिमेशन चाहिए. जैसे, व्यू को धीरे-धीरे अंदर या बाहर करना या व्यू का साइज़ बदलना. ट्रांज़िशन फ़्रेमवर्क यह तय करता है कि शुरुआती लेआउट से आखिरी लेआउट में ऐनिमेशन कैसे किया जाए.

ट्रांज़िशन फ़्रेमवर्क में ये सुविधाएं शामिल हैं:

  • ग्रुप-लेवल के ऐनिमेशन: व्यू की हैरारकी में मौजूद सभी व्यू पर ऐनिमेशन इफ़ेक्ट लागू करें.
  • पहले से मौजूद ऐनिमेशन: फ़ेड आउट या मूवमेंट जैसे सामान्य इफ़ेक्ट के लिए, पहले से तय किए गए ऐनिमेशन का इस्तेमाल करें.
  • रिसॉर्स फ़ाइल के साथ काम करने की सुविधा: लेआउट रिसॉर्स फ़ाइलों से व्यू की हैरारकी और पहले से मौजूद ऐनिमेशन लोड करें.
  • लाइफ़साइकल कॉलबैक: ऐसे कॉलबैक पाएं जिनसे ऐनिमेशन और हैरारकी में बदलाव करने की प्रोसेस को कंट्रोल किया जा सकता है.

लेआउट में बदलाव होने के बीच ऐनिमेट होने वाले सैंपल कोड के लिए, बेसिक ट्रांज़िशन देखें.

दो लेआउट के बीच ऐनिमेशन करने की बुनियादी प्रोसेस इस तरह है:

  1. शुरू और खत्म होने वाले लेआउट के लिए, Scene ऑब्जेक्ट बनाएं. हालांकि, शुरुआती लेआउट का सीन अक्सर मौजूदा लेआउट से अपने-आप तय होता है.
  2. आपको किस तरह का ऐनिमेशन चाहिए, यह तय करने के लिए एक Transition ऑब्जेक्ट बनाएं.
  3. TransitionManager.go() को कॉल करने पर, सिस्टम लेआउट स्विच करने के लिए ऐनिमेशन चलाता है.

पहली इमेज में दिए गए डायग्राम में, आपके लेआउट, सीन, ट्रांज़िशन, और फ़ाइनल ऐनिमेशन के बीच के संबंध को दिखाया गया है.

पहली इमेज. ट्रांज़िशन फ़्रेमवर्क, ऐनिमेशन कैसे बनाता है, इसकी बुनियादी जानकारी देने वाला इलस्ट्रेशन.

सीन बनाना

सीन, व्यू की हैरारकी की स्थिति को सेव करते हैं. इसमें व्यू और उनकी प्रॉपर्टी वैल्यू भी शामिल होती हैं. ट्रांज़िशन फ़्रेमवर्क, शुरू और आखिर में दिखने वाले सीन के बीच ऐनिमेशन चला सकता है.

अपने कोड में मौजूद व्यू के ग्रुप या लेआउट रिसॉर्स फ़ाइल से सीन बनाए जा सकते हैं. हालांकि, ट्रांज़िशन के लिए शुरुआती सीन, अक्सर मौजूदा यूज़र इंटरफ़ेस (यूआई) से अपने-आप तय होता है.

किसी सीन में, अपनी कार्रवाइयां भी तय की जा सकती हैं. ये कार्रवाइयां, सीन बदलने पर चलती हैं. यह सुविधा, किसी सीन पर ट्रांज़िशन करने के बाद व्यू की सेटिंग को हटाने के लिए काम की है.

लेआउट संसाधन से सीन बनाना

सीधे लेआउट संसाधन फ़ाइल से Scene इंस्टेंस बनाया जा सकता है. इस तकनीक का इस्तेमाल तब करें, जब फ़ाइल में व्यू की हैरारकी ज़्यादातर स्टैटिक हो. इन व्यू से, Scene इंस्टेंस बनाते समय, व्यू हैरारकी की स्थिति के बारे में पता चलता है. व्यू की हैरारकी बदलने पर, सीन फिर से बनाएं. फ़्रेमवर्क, फ़ाइल में मौजूद व्यू की पूरी हैरारकी से सीन बनाता है. लेआउट फ़ाइल के किसी हिस्से से सीन नहीं बनाया जा सकता.

लेआउट रिसॉर्स फ़ाइल से Scene इंस्टेंस बनाने के लिए, अपने लेआउट से सीन रूट को ViewGroup के तौर पर फिर से पाएं. इसके बाद, Scene.getSceneForLayout() फ़ंक्शन को कॉल करें. इसके लिए, सीन के रूट और लेआउट फ़ाइल के संसाधन आईडी का इस्तेमाल करें. इस फ़ाइल में, सीन के लिए व्यू हैरारकी होती है.

सीन के लिए लेआउट तय करें

इस सेक्शन के बाकी हिस्से में दिए गए कोड स्निपेट से पता चलता है कि एक ही सीन रूट एलिमेंट का इस्तेमाल करके, दो अलग-अलग सीन कैसे बनाए जा सकते हैं. स्निपेट से यह भी पता चलता है कि एक-दूसरे से मिलते-जुलते कई Scene ऑब्जेक्ट को लोड किया जा सकता है.

इस उदाहरण में, लेआउट की ये परिभाषाएं शामिल हैं:

  • टेक्स्ट लेबल और चाइल्ड FrameLayout वाली गतिविधि का मुख्य लेआउट.
  • दो टेक्स्ट फ़ील्ड वाले पहले सीन के लिए, एक ConstraintLayout.
  • दूसरे सीन के लिए ConstraintLayout, जिसमें एक ही दो टेक्स्ट फ़ील्ड अलग-अलग क्रम में हैं.

इस उदाहरण को इस तरह से डिज़ाइन किया गया है कि गतिविधि के मुख्य लेआउट के चाइल्ड लेआउट में ही पूरा ऐनिमेशन दिखे. मुख्य लेआउट में टेक्स्ट लेबल, स्टैटिक रहता है.

गतिविधि के मुख्य लेआउट को इस तरह से तय किया गया है:

res/layout/activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/master_layout">
    <TextView
        android:id="@+id/title"
        ...
        android:text="Title"/>
    <FrameLayout
        android:id="@+id/scene_root">
        <include layout="@layout/a_scene" />
    </FrameLayout>
</LinearLayout>

इस लेआउट की परिभाषा में, सीन के रूट के लिए एक टेक्स्ट फ़ील्ड और एक चाइल्ड FrameLayout शामिल है. पहले सीन का लेआउट, मुख्य लेआउट फ़ाइल में शामिल होता है. इससे ऐप्लिकेशन, इसे शुरुआती यूज़र इंटरफ़ेस के हिस्से के तौर पर दिखा सकता है. साथ ही, इसे किसी सीन में भी लोड कर सकता है, क्योंकि फ़्रेमवर्क किसी सीन में सिर्फ़ पूरी लेआउट फ़ाइल को लोड कर सकता है.

पहले सीन का लेआउट इस तरह से तय किया गया है:

res/layout/a_scene.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/scene_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
    
</androidx.constraintlayout.widget.ConstraintLayout>

दूसरे सीन के लेआउट में, एक ही आईडी वाले दो टेक्स्ट फ़ील्ड हैं. हालांकि, इन्हें अलग-अलग क्रम में रखा गया है. इसे इस तरह परिभाषित किया गया है:

res/layout/another_scene.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/scene_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
    
</androidx.constraintlayout.widget.ConstraintLayout>

लेआउट से सीन जनरेट करना

दो शर्त वाले लेआउट की परिभाषाएं बनाने के बाद, उनमें से हर एक के लिए एक सीन पाया जा सकता है. इसकी मदद से, दो यूज़र इंटरफ़ेस (यूआई) कॉन्फ़िगरेशन के बीच ट्रांज़िशन किया जा सकता है. सीन पाने के लिए, आपके पास सीन रूट और लेआउट के संसाधन आईडी का रेफ़रंस होना चाहिए.

यहां दिए गए कोड स्निपेट में, सीन रूट का रेफ़रंस पाने और लेआउट फ़ाइलों से दो Scene ऑब्जेक्ट बनाने का तरीका बताया गया है:

Kotlin

val sceneRoot: ViewGroup = findViewById(R.id.scene_root)
val aScene: Scene = Scene.getSceneForLayout(sceneRoot, R.layout.a_scene, this)
val anotherScene: Scene = Scene.getSceneForLayout(sceneRoot, R.layout.another_scene, this)

Java

Scene aScene;
Scene anotherScene;

// Create the scene root for the scenes in this app.
sceneRoot = (ViewGroup) findViewById(R.id.scene_root);

// Create the scenes.
aScene = Scene.getSceneForLayout(sceneRoot, R.layout.a_scene, this);
anotherScene =
    Scene.getSceneForLayout(sceneRoot, R.layout.another_scene, this);

ऐप्लिकेशन में, अब व्यू हैरारकी (व्यू और व्यू ग्रुप के लेआउट का क्रम) के आधार पर दो Scene ऑब्जेक्ट हैं. दोनों सीन, res/layout/activity_main.xml में FrameLayout एलिमेंट से तय किए गए सीन रूट का इस्तेमाल करते हैं.

अपने कोड में सीन बनाना

आपके पास अपने कोड में, ViewGroup ऑब्जेक्ट से भी Scene इंस्टेंस बनाने का विकल्प होता है. इस तकनीक का इस्तेमाल तब करें, जब सीधे अपने कोड में व्यू की हैरारकी में बदलाव किया जा रहा हो या उन्हें डाइनैमिक तौर पर जनरेट किया जा रहा हो.

अपने कोड में व्यू हैरारकी से सीन बनाने के लिए, Scene(sceneRoot, viewHierarchy) कंस्ट्रक्टर का इस्तेमाल करें. इस कन्स्ट्रक्टर को कॉल करना, पहले से ही किसी लेआउट फ़ाइल को फ़्लोरेट करने के बाद, Scene.getSceneForLayout() फ़ंक्शन को कॉल करने के बराबर है.

नीचे दिए गए कोड स्निपेट में, अपने कोड में सीन के रूट एलिमेंट और सीन के लिए व्यू हैरारकी से Scene इंस्टेंस बनाने का तरीका बताया गया है:

Kotlin

val sceneRoot = someLayoutElement as ViewGroup
val viewHierarchy = someOtherLayoutElement as ViewGroup
val scene: Scene = Scene(sceneRoot, viewHierarchy)

Java

Scene mScene;

// Obtain the scene root element.
sceneRoot = (ViewGroup) someLayoutElement;

// Obtain the view hierarchy to add as a child of
// the scene root when this scene is entered.
viewHierarchy = (ViewGroup) someOtherLayoutElement;

// Create a scene.
mScene = new Scene(sceneRoot, mViewHierarchy);

सीन ऐक्शन बनाना

फ़्रेमवर्क की मदद से, किसी सीन में प्रवेश करने या उससे बाहर निकलने पर, सिस्टम की ओर से की जाने वाली कस्टम सीन कार्रवाइयां तय की जा सकती हैं. कई मामलों में, कस्टम सीन ऐक्शन तय करना ज़रूरी नहीं होता, क्योंकि फ़्रेमवर्क, सीन के बीच बदलाव को अपने-आप ऐनिमेट करता है.

सीन ऐक्शन, इन मामलों को मैनेज करने के लिए काम के होते हैं:

  • एक ही हैरारकी में न होने वाले व्यू को ऐनिमेट करने के लिए. सीन से बाहर निकलने और उसमें शामिल होने की कार्रवाइयों का इस्तेमाल करके, शुरुआत और आखिर में दिखने वाले सीन के लिए व्यू को ऐनिमेट किया जा सकता है.
  • उन व्यू को ऐनिमेट करने के लिए जिन्हें ट्रांज़िशन फ़्रेमवर्क अपने-आप ऐनिमेट नहीं कर सकता. जैसे, ListView ऑब्जेक्ट. ज़्यादा जानकारी के लिए, सीमाएं सेक्शन देखें.

कस्टम सीन ऐक्शन देने के लिए, अपनी कार्रवाइयों को Runnable ऑब्जेक्ट के तौर पर तय करें और उन्हें Scene.setExitAction() या Scene.setEnterAction() फ़ंक्शन में पास करें. फ़्रेमवर्क, ट्रांज़िशन ऐनिमेशन चलाने से पहले, शुरुआती सीन पर setExitAction() फ़ंक्शन को कॉल करता है. साथ ही, ट्रांज़िशन ऐनिमेशन चलाने के बाद, आखिरी सीन पर setEnterAction() फ़ंक्शन को कॉल करता है.

ट्रांज़िशन लागू करना

ट्रांज़िशन फ़्रेमवर्क, Transition ऑब्जेक्ट वाले सीन के बीच एनिमेशन के स्टाइल को दिखाता है. AutoTransition और Fade जैसी पहले से मौजूद सबक्लास का इस्तेमाल करके, Transition को इंस्टैंशिएट किया जा सकता है. इसके अलावा, अपने ट्रांज़िशन को भी तय किया जा सकता है. इसके बाद, एक से दूसरे सीन के बीच ऐनिमेशन चलाया जा सकता है. इसके लिए, आखिरी Scene और Transition को TransitionManager.go() पर पास करें.

ट्रांज़िशन लाइफ़साइकल, ऐक्टिविटी लाइफ़साइकल से मिलता-जुलता है. यह ट्रांज़िशन की उन स्थितियों को दिखाता है जिन्हें फ़्रेमवर्क, ऐनिमेशन के शुरू होने और खत्म होने के बीच मॉनिटर करता है. लाइफ़साइकल की अहम स्थितियों में, फ़्रेमवर्क कॉलबैक फ़ंक्शन को ट्रिगर करता है. इन फ़ंक्शन का इस्तेमाल करके, ट्रांज़िशन के अलग-अलग चरणों में अपने यूज़र इंटरफ़ेस में बदलाव किया जा सकता है.

ट्रांज़िशन बनाना

पिछले सेक्शन में, अलग-अलग व्यू हैरारकी की स्थिति दिखाने वाले सीन बनाने का तरीका बताया गया है. आपको शुरू और आखिर में जिस सीन को बदलना है उसे तय करने के बाद, ऐसा Transition ऑब्जेक्ट बनाएं जो ऐनिमेशन को परिभाषित करता हो. फ़्रेमवर्क की मदद से, रिसॉर्स फ़ाइल में बिल्ट-इन ट्रांज़िशन तय किया जा सकता है और उसे अपने कोड में इनफ़्लेट किया जा सकता है. इसके अलावा, सीधे अपने कोड में बिल्ट-इन ट्रांज़िशन का इंस्टेंस बनाया जा सकता है.

टेबल 1. पहले से मौजूद ट्रांज़िशन टाइप.

कक्षा टैग करें प्रभाव
AutoTransition <autoTransition/> डिफ़ॉल्ट ट्रांज़िशन. इस क्रम में, फ़ेड आउट, मूव, साइज़ बदलता है, और व्यू फ़ेड इन करता है.
ChangeBounds <changeBounds/> व्यू को मूव करता है और उनका साइज़ बदलता है.
ChangeClipBounds <changeClipBounds/> सीन बदलने से पहले और बाद में View.getClipBounds() को कैप्चर करता है और ट्रांज़िशन के दौरान उन बदलावों को ऐनिमेट करता है.
ChangeImageTransform <changeImageTransform/> सीन बदलने से पहले और बाद में, ImageView के मैट्रिक्स को कैप्चर करता है और ट्रांज़िशन के दौरान, उसे ऐनिमेट करता है.
ChangeScroll <changeScroll/> यह सीन बदलने से पहले और बाद में, टारगेट की स्क्रोल प्रॉपर्टी कैप्चर करता है और किसी भी बदलाव को ऐनिमेट करता है.
ChangeTransform <changeTransform/> सीन बदलने से पहले और बाद में, व्यू के स्केल और रोटेशन को कैप्चर करता है और ट्रांज़िशन के दौरान उन बदलावों को ऐनिमेट करता है.
Explode <explode/> शुरुआत और आखिर में दिखने वाले सीन में, टारगेट व्यू के दिखने की सेटिंग में हुए बदलावों को ट्रैक करता है. साथ ही, व्यू को सीन के किनारों से अंदर या बाहर ले जाता है.
Fade <fade/> fade_in व्यू में फ़ेड इन होता है.
fade_out व्यू को धीरे-धीरे फ़ेड आउट करता है.
fade_in_out (डिफ़ॉल्ट) के बाद fade_out और फिर fade_in दिखता है.
Slide <slide/> वीडियो के शुरुआती और आखिरी सीन में, टारगेट व्यू के दिखने की सेटिंग में बदलाव को ट्रैक करता है. साथ ही, व्यू को सीन के किसी एक किनारे से अंदर या बाहर ले जाता है.

किसी रिसॉर्स फ़ाइल से ट्रांज़िशन इंस्टेंस बनाना

इस तकनीक की मदद से, अपनी गतिविधि के कोड में बदलाव किए बिना, ट्रांज़िशन की परिभाषा में बदलाव किया जा सकता है. यह तकनीक, आपके ऐप्लिकेशन कोड से जटिल ट्रांज़िशन की परिभाषाओं को अलग करने के लिए भी काम की है. इस बारे में एक से ज़्यादा ट्रांज़िशन तय करने वाले सेक्शन में बताया गया है.

किसी संसाधन फ़ाइल में बिल्ट-इन ट्रांज़िशन तय करने के लिए, यह तरीका अपनाएं:

  • अपने प्रोजेक्ट में res/transition/ डायरेक्ट्री जोड़ें.
  • इस डायरेक्ट्री में एक नई एक्सएमएल संसाधन फ़ाइल बनाएं.
  • पहले से मौजूद किसी ट्रांज़िशन के लिए एक्सएमएल नोड जोड़ें.

उदाहरण के लिए, नीचे दी गई संसाधन फ़ाइल, Fade ट्रांज़िशन के बारे में बताती है:

res/transition/fade_transition.xml

<fade xmlns:android="http://schemas.android.com/apk/res/android" />

यहां दिए गए कोड स्निपेट में, किसी संसाधन फ़ाइल से अपनी गतिविधि में Transition इंस्टेंस को फ़ुल करने का तरीका बताया गया है:

Kotlin

var fadeTransition: Transition =
    TransitionInflater.from(this)
                      .inflateTransition(R.transition.fade_transition)

Java

Transition fadeTransition =
        TransitionInflater.from(this).
        inflateTransition(R.transition.fade_transition);

अपने कोड में एक ट्रांज़िशन इंस्टेंस बनाएं

अगर आपको अपने कोड में यूज़र इंटरफ़ेस में बदलाव करना है, तो यह तकनीक ट्रांज़िशन ऑब्जेक्ट को डाइनैमिक तौर पर बनाने के लिए काम की है. साथ ही, कुछ या बिना पैरामीटर वाले आसानी से बनाए जा सकने वाले ट्रांज़िशन इंस्टेंस बनाने के लिए भी यह तकनीक काम की है.

पहले से मौजूद ट्रांज़िशन का कोई इंस्टेंस बनाने के लिए, Transition क्लास की सबक्लास में से किसी एक सार्वजनिक कंस्ट्रक्टर को लागू करें. उदाहरण के लिए, नीचे दिया गया कोड स्निपेट, Fade ट्रांज़िशन का एक इंस्टेंस बनाता है:

Kotlin

var fadeTransition: Transition = Fade()

Java

Transition fadeTransition = new Fade();

ट्रांज़िशन लागू करना

आम तौर पर, किसी इवेंट के जवाब में, व्यू की अलग-अलग हैरारकी के बीच बदलाव करने के लिए ट्रांज़िशन लागू किया जाता है. जैसे, उपयोगकर्ता की कार्रवाई. उदाहरण के लिए, किसी खोज ऐप्लिकेशन पर विचार करें: जब कोई उपयोगकर्ता खोज के लिए कोई शब्द डालता है और खोज बटन पर टैप करता है, तो ऐप्लिकेशन एक ऐसे सीन में बदल जाता है जो खोज के नतीजों के लेआउट को दिखाता है. साथ ही, खोज बटन को धीरे-धीरे फीका करते हुए, खोज के नतीजों को धीरे-धीरे फ़ेड इन करता है.

अपनी गतिविधि में किसी इवेंट के रिस्पॉन्स में ट्रांज़िशन लागू करते समय सीन में बदलाव करने के लिए, TransitionManager.go() क्लास फ़ंक्शन को आखिरी सीन के साथ कॉल करें. साथ ही, ऐनिमेशन में इस्तेमाल करने के लिए ट्रांज़िशन इंस्टेंस, जैसा कि यहां दिए गए स्निपेट में दिखाया गया है:

Kotlin

TransitionManager.go(endingScene, fadeTransition)

Java

TransitionManager.go(endingScene, fadeTransition);

ट्रांज़िशन इंस्टेंस से तय किए गए ऐनिमेशन को चलाते समय, फ़्रेमवर्क, सीन रूट में मौजूद व्यू के लेआउट की हैरारकी को आखिरी सीन के लेआउट की हैरारकी में बदल देता है. शुरुआती सीन, आखिरी ट्रांज़िशन का आखिरी सीन है. अगर कोई पिछला ट्रांज़िशन नहीं है, तो शुरुआती सीन यूज़र इंटरफ़ेस की मौजूदा स्थिति से अपने-आप तय होता है.

अगर आपने ट्रांज़िशन इंस्टेंस की जानकारी नहीं दी है, तो ट्रांज़िशन मैनेजर अपने-आप ऐसा ट्रांज़िशन लागू कर सकता है जो ज़्यादातर स्थितियों में सही काम करता है. ज़्यादा जानकारी के लिए, TransitionManager क्लास के लिए एपीआई का रेफ़रंस देखें.

खास टारगेट व्यू चुनना

यह फ़्रेमवर्क, डिफ़ॉल्ट रूप से शुरुआत और आखिर में दिखने वाले सभी सीन पर ट्रांज़िशन लागू करता है. कुछ मामलों में, ऐसा हो सकता है कि आप किसी सीन में सिर्फ़ व्यू के सबसेट पर ऐनिमेशन लागू करना चाहें. फ़्रेमवर्क की मदद से, उन व्यू को चुना जा सकता है जिन्हें ऐनिमेट करना है. उदाहरण के लिए, फ़्रेमवर्क में ListView ऑब्जेक्ट में बदलावों को ऐनिमेट करने की सुविधा नहीं है. इसलिए, ट्रांज़िशन के दौरान उन्हें ऐनिमेट करने की कोशिश न करें.

ट्रांज़िशन के दौरान ऐनिमेट होने वाले हर व्यू को टारगेट कहा जाता है. सिर्फ़ ऐसे टारगेट चुने जा सकते हैं जो किसी सीन से जुड़ी व्यू हैरारकी का हिस्सा हों.

टारगेट की सूची से एक या एक से ज़्यादा व्यू हटाने के लिए, ट्रांज़िशन शुरू करने से पहले removeTarget() तरीका कॉल करें. टारगेट की सूची में सिर्फ़ वे व्यू जोड़ने के लिए जिन्हें आपने तय किया है, addTarget() फ़ंक्शन को कॉल करें. ज़्यादा जानकारी के लिए, Transition क्लास के लिए एपीआई रेफ़रंस देखें.

एक से ज़्यादा ट्रांज़िशन तय करना

किसी ऐनिमेशन का पूरा असर जानने के लिए, इसे अलग-अलग सीन के बीच होने वाले बदलावों से मैच करें. उदाहरण के लिए, अगर कुछ व्यू हटाए जा रहे हैं और सीन के बीच में दूसरे व्यू जोड़े जा रहे हैं, तो फ़ेड आउट या फ़ेड इन ऐनिमेशन से यह पता चलता है कि कुछ व्यू अब उपलब्ध नहीं हैं. अगर आपको व्यू को स्क्रीन पर अलग-अलग जगहों पर ले जाना है, तो बेहतर होगा कि आप व्यू को ऐनिमेशन के साथ मूव करें, ताकि उपयोगकर्ताओं को व्यू की नई जगह दिखे.

आपको सिर्फ़ एक ऐनिमेशन चुनने की ज़रूरत नहीं है, क्योंकि ट्रांज़िशन फ़्रेमवर्क की मदद से, ट्रांज़िशन सेट में ऐनिमेशन इफ़ेक्ट को जोड़ा जा सकता है. इस सेट में, बिल्ट-इन या कस्टम ट्रांज़िशन का एक ग्रुप होता है.

एक्सएमएल में ट्रांज़िशन के किसी कलेक्शन से ट्रांज़िशन सेट तय करने के लिए, res/transitions/ डायरेक्ट्री में एक रिसॉर्स फ़ाइल बनाएं और TransitionSet एलिमेंट में ट्रांज़िशन की सूची बनाएं. उदाहरण के लिए, नीचे दिया गया स्निपेट दिखाता है कि ऐसे ट्रांज़िशन सेट के बारे में कैसे बताया जाए जिसका व्यवहार AutoTransition क्लास जैसा ही है:

<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
    android:transitionOrdering="sequential">
    <fade android:fadingMode="fade_out" />
    <changeBounds />
    <fade android:fadingMode="fade_in" />
</transitionSet>

अपने कोड में ट्रांज़िशन सेट को TransitionSet ऑब्जेक्ट में फ़ुल करने के लिए, अपनी गतिविधि में TransitionInflater.from() फ़ंक्शन को कॉल करें. TransitionSet क्लास, Transition क्लास से मिलती-जुलती है. इसलिए, इसका इस्तेमाल किसी भी Transition इंस्टेंस की तरह ही, ट्रांज़िशन मैनेजर के साथ किया जा सकता है.

बिना सीन के ट्रांज़िशन लागू करना

यूज़र इंटरफ़ेस में बदलाव करने का सिर्फ़ एक तरीका, व्यू की हैरारकी बदलना नहीं है. मौजूदा हैरारकी में, चाइल्ड व्यू जोड़कर, उनमें बदलाव करके, और उन्हें हटाकर भी बदलाव किए जा सकते हैं.

उदाहरण के लिए, एक ही लेआउट के साथ सर्च इंटरैक्शन लागू किया जा सकता है. खोज एंट्री फ़ील्ड और खोज आइकॉन दिखाने वाले लेआउट से शुरू करें. नतीजे दिखाने के लिए यूज़र इंटरफ़ेस में बदलाव करने के लिए, जब उपयोगकर्ता खोज बटन पर टैप करता है, तो ViewGroup.removeView() फ़ंक्शन को कॉल करके खोज बटन को हटाएं और ViewGroup.addView() फ़ंक्शन को कॉल करके खोज के नतीजे जोड़ें.

अगर विकल्प के तौर पर दो ऐसी हैरारकी हैं जो करीब-करीब एक जैसी हैं, तो इस तरीके का इस्तेमाल किया जा सकता है. यूज़र इंटरफ़ेस में थोड़े से अंतर के लिए, दो अलग-अलग लेआउट फ़ाइलें बनाने और उन्हें मैनेज करने के बजाय, एक लेआउट फ़ाइल में व्यू हैरारकी (व्यू और व्यू ग्रुप के लेआउट का क्रम) हो सकती है. इसमें कोड में बदलाव किया जा सकता है.

अगर मौजूदा व्यू की हैरारकी में इस तरह बदलाव किए जाते हैं, तो आपको सीन बनाने की ज़रूरत नहीं है. इसके बजाय, देर से होने वाले ट्रांज़िशन का इस्तेमाल करके, व्यू हैरारकी की दो स्थितियों के बीच ट्रांज़िशन बनाया और लागू किया जा सकता है. ट्रांज़िशन फ़्रेमवर्क की यह सुविधा, व्यू की मौजूदा हैरारकी की स्थिति से शुरू होती है. साथ ही, व्यू में किए गए बदलावों को रिकॉर्ड करती है और ऐसा ट्रांज़िशन लागू करती है जो सिस्टम के यूज़र इंटरफ़ेस को फिर से ड्रॉ करने पर, बदलावों को ऐनिमेट करता है.

एक व्यू हैरारकी में, देर से ट्रांज़िशन बनाने के लिए, यह तरीका अपनाएं:

  1. ट्रांज़िशन को ट्रिगर करने वाला इवेंट होने पर, TransitionManager.beginDelayedTransition() फ़ंक्शन को कॉल करें. साथ ही, उन सभी व्यू का पैरंट व्यू और इस्तेमाल करने के लिए ट्रांज़िशन दें जिन्हें आपको बदलना है. फ़्रेमवर्क, चिल्ड्रन व्यू की मौजूदा स्थिति और उनकी प्रॉपर्टी वैल्यू को सेव करता है.
  2. अपने इस्तेमाल के उदाहरण के हिसाब से, चाइल्ड व्यू में बदलाव करें. फ़्रेमवर्क, चाइल्ड व्यू और उनकी प्रॉपर्टी में किए गए बदलावों को रिकॉर्ड करता है.
  3. जब सिस्टम आपके बदलावों के हिसाब से यूज़र इंटरफ़ेस को फिर से बनाता है, तो फ़्रेमवर्क, मूल स्थिति और नई स्थिति के बीच हुए बदलावों को ऐनिमेशन के तौर पर दिखाता है.

इस उदाहरण में, देर से होने वाले ट्रांज़िशन का इस्तेमाल करके, व्यू के क्रम में टेक्स्ट व्यू जोड़ने का तरीका बताया गया है. पहला स्निपेट लेआउट डेफ़िनिशन फ़ाइल दिखाता है:

res/layout/activity_main.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/mainLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <EditText
        android:id="@+id/inputText"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
    ...
</androidx.constraintlayout.widget.ConstraintLayout>

अगले स्निपेट में, टेक्स्ट व्यू को जोड़ने के लिए ऐनिमेशन वाला कोड दिखाया गया है:

MainActivity

Kotlin

setContentView(R.layout.activity_main)
val labelText = TextView(this).apply {
    text = "Label"
    id = R.id.text
}
val rootView: ViewGroup = findViewById(R.id.mainLayout)
val mFade: Fade = Fade(Fade.IN)
TransitionManager.beginDelayedTransition(rootView, mFade)
rootView.addView(labelText)

Java

private TextView labelText;
private Fade mFade;
private ViewGroup rootView;
...
// Load the layout.
setContentView(R.layout.activity_main);
...
// Create a new TextView and set some View properties.
labelText = new TextView(this);
labelText.setText("Label");
labelText.setId(R.id.text);

// Get the root view and create a transition.
rootView = (ViewGroup) findViewById(R.id.mainLayout);
mFade = new Fade(Fade.IN);

// Start recording changes to the view hierarchy.
TransitionManager.beginDelayedTransition(rootView, mFade);

// Add the new TextView to the view hierarchy.
rootView.addView(labelText);

// When the system redraws the screen to show this update,
// the framework animates the addition as a fade in.

ट्रांज़िशन लाइफ़साइकल कॉलबैक तय करना

ट्रांज़िशन लाइफ़साइकल, गतिविधि की लाइफ़साइकल से मिलता-जुलता है. यह ट्रांज़िशन की उन स्थितियों को दिखाता है जिन्हें फ़्रेमवर्क, TransitionManager.go() फ़ंक्शन को कॉल करने और ऐनिमेशन के पूरा होने के बीच की अवधि के दौरान मॉनिटर करता है. लाइफ़साइकल की अहम स्थितियों में, फ़्रेमवर्क TransitionListener इंटरफ़ेस से तय किए गए कॉलबैक को शुरू करता है.

ट्रांज़िशन लाइफ़साइकल कॉलबैक, कई कामों में मददगार होते हैं. उदाहरण के लिए, किसी सीन में बदलाव के दौरान, व्यू प्रॉपर्टी की वैल्यू को शुरुआती व्यू हैरारकी से आखिरी व्यू हैरारकी में कॉपी करने के लिए. आप वैल्यू को उसके शुरुआती व्यू से आखिरी व्यू हैरारकी के व्यू में कॉपी नहीं कर सकते, क्योंकि ट्रांज़िशन पूरा होने तक आखिरी व्यू हैरारकी नहीं बदली जाती. इसके बजाय, आपको वैल्यू को किसी वैरिएबल में स्टोर करना होगा. इसके बाद, फ़्रेमवर्क के ट्रांज़िशन पूरा होने पर, उसे आखिरी व्यू की हैरारकी में कॉपी करना होगा. ट्रांज़िशन पूरा होने पर सूचना पाने के लिए, अपनी गतिविधि में TransitionListener.onTransitionEnd() फ़ंक्शन लागू करें.

ज़्यादा जानकारी के लिए, TransitionListener क्लास के लिए एपीआई का रेफ़रंस देखें.

सीमाएं

इस सेक्शन में, ट्रांज़िशन फ़्रेमवर्क की कुछ सीमाओं के बारे में बताया गया है:

  • SurfaceView पर लागू किए गए ऐनिमेशन शायद सही तरीके से न दिखें. SurfaceView इंस्टेंस, यूज़र इंटरफ़ेस (यूआई) थ्रेड के बजाय किसी अन्य थ्रेड से अपडेट किए जाते हैं. इसलिए, हो सकता है कि अपडेट, दूसरे व्यू के ऐनिमेशन के साथ सिंक न हों.
  • ऐसा हो सकता है कि TextureView पर लागू किए जाने पर, कुछ खास तरह के ट्रांज़िशन से मनमुताबिक ऐनिमेशन इफ़ेक्ट न मिले.
  • ऐसी क्लास AdapterView का विस्तार करती हैं, जैसे कि ListView, अपने चाइल्ड व्यू को ऐसे तरीकों से मैनेज करती हैं जो ट्रांज़िशन फ़्रेमवर्क के साथ काम नहीं करते. अगर AdapterView के आधार पर किसी व्यू को ऐनिमेट करने की कोशिश की जाती है, तो हो सकता है कि डिवाइस का डिसप्ले काम करना बंद कर दे.
  • अगर ऐनिमेशन के साथ TextView का साइज़ बदलने की कोशिश की जाती है, तो ऑब्जेक्ट का पूरा साइज़ बदलने से पहले, टेक्स्ट नई जगह पर पॉप-अप हो जाता है. इस समस्या से बचने के लिए, उन व्यू का साइज़ बदलने को ऐनिमेशन न करें जिनमें टेक्स्ट शामिल है.