2012-10-22 23 views
55

में स्लाइड करने के लिए मैं FragmentTransaction.setCustomAnimations का उपयोग करके निम्न प्रभाव प्राप्त करने का प्रयास कर रहा हूं।फ्रैगमेंट ट्रांज़ेक्शन एनीमेशन शीर्ष

  1. टुकड़ा एक दिखा रहा है
  2. टुकड़ा बी टुकड़ा एक साथ टुकड़ा एक बदलें प्रतिस्थापन के दौरान दिखाई रहना चाहिए। टुकड़े बी को दाईं ओर से स्लाइड करना चाहिए। फ्रैगमेंट बी को फ्रैगमेंट ए के शीर्ष पर स्लाइड करना चाहिए।

मुझे एनीमेशन सेटअप में स्लाइड प्राप्त करने में कोई समस्या नहीं है। मेरी समस्या यह है कि मैं यह नहीं समझ सकता कि फ्रैगमेंट को कैसे बनाए रखना है, जहां यह है और फ्रेमिंग बी के तहत हो, जबकि एनीमेशन में स्लाइड चल रही है। कोई फर्क नहीं पड़ता कि मैं क्या करता हूं ऐसा लगता है कि टुकड़ा ए शीर्ष पर है।

मैं इसे कैसे प्राप्त कर सकता हूं?

यहाँ FragmentTransaction कोड है:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
ft.setCustomAnimations(R.anim.slide_in_right, R.anim.nothing, R.anim.nothing, 
    R.anim.slide_out_right); 
ft.replace(R.id.fragment_content, fragment, name); 
ft.addToBackStack(name); 
ft.commit(); 

आप देख सकते हैं मैं "बाहर" एनीमेशन के लिए एक एनीमेशन R.anim.nothing परिभाषित किया है क्योंकि मैं वास्तव में टुकड़ा एक अन्य कुछ भी नहीं करना चाहते हैं बस लेनदेन के दौरान यह कहां रहने के बजाय।

slide_in_right.xml

<translate xmlns:android="http://schemas.android.com/apk/res/android" 
    android:duration="@android:integer/config_mediumAnimTime" 
    android:fromXDelta="100%p" 
    android:toXDelta="0" 
    android:zAdjustment="top" /> 

nothing.xml
<alpha xmlns:android="http://schemas.android.com/apk/res/android" 
    android:duration="@android:integer/config_mediumAnimTime" 
    android:fromAlpha="1.0" 
    android:toAlpha="1.0" 
    android:zAdjustment="bottom" /> 
+1

मैंने एक बग रिपोर्ट दायर की है क्योंकि वर्तमान जेड ऑर्डरिंग सिर्फ सादा गलत है। https://code.google.com/p/android/issues/detail?id=163384&thanks=163384&ts=1428443402 – sbaar

उत्तर

9

मैं एक समाधान है जो मेरे लिए काम करता पाया। मैं एक FragmentStatePagerAdapter के साथ एक ViewPager का उपयोग कर समाप्त हो गया। ViewPager स्वाइपिंग व्यवहार प्रदान करता है और टुकड़ों में FragmentStatePagerAdapter स्वैप प्रदान करता है। आने वाले पृष्ठ के नीचे "एक पृष्ठ" दिखाई देने वाला एक पृष्ठ होने के प्रभाव को प्राप्त करने के लिए अंतिम चाल पृष्ठ ट्रांसफॉर्मर का उपयोग करना है। PageTransformer पृष्ठों के बीच ViewPager के डिफ़ॉल्ट संक्रमण को ओवरराइड करता है। यहां एक उदाहरण पृष्ठ ट्रांसफॉर्मर है जो अनुवाद के साथ प्रभाव और बाईं ओर वाले पृष्ठ पर स्केलिंग की एक छोटी राशि प्राप्त करता है।

final IncomingFragment newFrag = new IncomingFragment(); 
newFrag.setEnterAnimationListener(new Animation.AnimationListener() { 
       @Override 
       public void onAnimationStart(Animation animation) { 

       } 

       @Override 
       public void onAnimationEnd(Animation animation) { 
        clearSelection(); 
        inFrag.clearEnterAnimationListener(); 

        getFragmentManager().beginTransaction().remove(OutgoingFragment.this).commit(); 
       } 

       @Override 
       public void onAnimationRepeat(Animation animation) { 

       } 
      }); 

getActivity().getSupportFragmentManager().beginTransaction() 
        .setCustomAnimations(R.anim.slide_in_from_right, 0) 
        .add(R.id.container, inFrag) 
        .addToBackStack(null) 
        .commit(); 

यह OutgoingFragment वर्ग की एक आंतरिक वर्ग के भीतर से बुलाया जा रहा है:

public class ScalePageTransformer implements PageTransformer { 
    private static final float SCALE_FACTOR = 0.95f; 

    private final ViewPager mViewPager; 

    public ScalePageTransformer(ViewPager viewPager) { 
      this.mViewPager = viewPager; 
    } 

    @SuppressLint("NewApi") 
    @Override 
    public void transformPage(View page, float position) { 
     if (position <= 0) { 
      // apply zoom effect and offset translation only for pages to 
      // the left 
      final float transformValue = Math.abs(Math.abs(position) - 1) * (1.0f - SCALE_FACTOR) + SCALE_FACTOR; 
      int pageWidth = mViewPager.getWidth(); 
      final float translateValue = position * -pageWidth; 
      page.setScaleX(transformValue); 
      page.setScaleY(transformValue); 
      if (translateValue > -pageWidth) { 
       page.setTranslationX(translateValue); 
      } else { 
       page.setTranslationX(0); 
      } 
     } 
    } 

} 
+0

ग्रेट सॉल्यूशन, लेकिन दुर्भाग्य से फिट नहीं होता है अगर आप ढेर को बदलना चाहते हैं, खासतौर से घटने की दिशा में - यह चमक (पूरे तत्व को फिर से निकालने) की ओर जाता है। –

20

मैं अगर आप अभी भी एक जवाब की जरूरत है, लेकिन मैं हाल ही में करने के लिए आवश्यक नहीं जानता:

यहाँ एनीमेशन संसाधन हैं वही करो और मुझे जो चाहिए आप करने का एक तरीका मिला।

FragmentManager fm = getFragmentManager(); 
FragmentTransaction ft = fm.beginTransaction(); 

MyFragment next = getMyFragment(); 

ft.add(R.id.MyLayout,next); 
ft.setCustomAnimations(R.anim.slide_in_right,0); 
ft.show(next); 
ft.commit(); 

मैं एक FrameLayout में मेरी टुकड़ा प्रदर्शित:

मैं कुछ इस तरह बनाया है।

ft.remove(myolderFrag); 

यह एनीमेशन के दौरान प्रदर्शित नहीं किया जाता:

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

slide_in_right.xml

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android" > 
<translate android:duration="150" android:fromXDelta="100%p" 
android:interpolator="@android:anim/linear_interpolator" 
android:toXDelta="0" /> 
</set> 
+0

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

+1

@ domji84 ' <सेट xmlns: android =" http://schemas.android.com/apk/res/android "> <अनुवाद एंड्रॉयड: अवधि = "150" एंड्रॉयड: fromXDelta = "100% पी" एंड्रॉयड: क्षेपक = "@ एंड्रॉयड: anim/linear_interpolator" एंड्रॉयड: toXDelta = "0" /> ' – Meph

+0

धन्यवाद। 'overridePendingTransition (R.anim.my_animation, 0)' वह पंक्ति है जिसे मैं ढूंढ रहा था। –

2

मैं एक वैकल्पिक समाधान (भारी परीक्षण नहीं) है कि मैं प्रस्तावों अब तक की तुलना में अधिक सुंदर लगता है पाया।

एक नया टुकड़ा डाला जा रहा है, एनीमेशन पूर्ण हो जाता है, तो पुराना टुकड़ा हटा दिया जा रहा है।

कुछ अनुप्रयोगों में इसके साथ कुछ स्मृति समस्याएं हो सकती हैं लेकिन यह दोनों टुकड़ों को अनिश्चित काल तक बनाए रखने से बेहतर है।

+0

मेरे लिए यह अब तक का सबसे अच्छा समाधान है। मैं वही करता था लेकिन एनीमेशन के दौरान सिस्टम को हैंडलर से रोककर और फिर पिछले खंड को हटाकर, लेकिन यह बहुत बेहतर था। – JDenais

+0

इनकमिंग फ्रैगमेंट और आउटगोइंग फ्रैगमेंट कक्षाएं कहां से आईं? क्या वे कस्टम हैं? इसके पीछे कार्यान्वयन को समझ में नहीं आता है। शायद जब यह लिखा गया था तो 'Fragment.setEnterAnimationListener (...)' के रूप में ऐसा कोई फ़ंक्शन था ... या वह उस खंड के लिए एक कस्टम फ़ंक्शन है? – NineToeNerd

4

अधिक प्रयोग के बाद (इसलिए यह मेरा दूसरा जवाब है), समस्या यह प्रतीत होती है कि आर.निम। कुछ भी 'गायब' नहीं होता है जब हम एक और एनीमेशन चाहते हैं जो स्पष्ट रूप से 'रहें' कहता है।

मेक फ़ाइल no_animation.xml: समाधान इस तरह एक सच्चे 'कुछ भी नहीं' एनीमेशन को परिभाषित करने के लिए है

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android"> 
    <scale 
     android:interpolator="@android:anim/linear_interpolator" 
     android:fromXScale="1.0" 
     android:toXScale="1.0" 
     android:fromYScale="1.0" 
     android:toYScale="1.0" 
     android:duration="200" 
     /> 
    <alpha xmlns:android="http://schemas.android.com/apk/res/android" 
     android:fromAlpha="1.0" 
     android:toAlpha="0.0" 
     android:duration="200" 
     android:startOffset="200" 
     /> 
</set> 

अब बस के रूप में आप अन्यथा जो कार्य करें:

getActivity().getSupportFragmentManager().beginTransaction() 
       .setCustomAnimations(R.anim.slide_in_right, R.anim.no_animation) 
       .replace(R.id.container, inFrag, FRAGMENT_TAG) 
       .addToBackStack("Some text") 
       .commit(); 
+0

मैं इसे आज़माउंगा लेकिन मैंने उचित "stay_put" एनीमेशन करने के बारे में हालांकि किया था और यह सब कुछ नए टुकड़े की स्लाइडिंग एनीमेशन को अग्रभूमि पर रहने वाले पुराने टुकड़े के साथ कवर किया गया था। लेकिन मैं आपको no_animation की शुरुआत ऑफसेट देखता हूं तो शायद यह चाल है। मैं आपको बता दूंगा कि मैं आपके समाधान के बारे में क्या सोचता हूं। – JDenais

+1

अच्छा विचार लेकिन यह काम नहीं कर रहा है क्योंकि लेनदेन तुरंत टुकड़े को हटा देता है और मैं एनीमेशन के दौरान दूसरे खंड के नीचे सफेद स्क्रीन देख सकता हूं। –

+0

इस बात के बारे में उलझन में आपने सोचा कि इसकी आवश्यकता क्यों है। मैंने अभी 0 का उपयोग किया जहां मैं कोई संक्रमण नहीं चाहता था और यह बहुत अच्छा काम करता था। ऐसा लगता है कि आपने ऊपर क्या किया है। – NineToeNerd

11

लॉलीपॉप से ​​शुरू, आप आपके प्रवेश खंड के अनुवाद अनुवाद को बढ़ा सकते हैं। यह बाहर निकलने के ऊपर दिखाई देगा।

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

@Override 
public void onViewCreated(View view, Bundle savedInstanceState) { 
    super.onViewCreated(view, savedInstanceState); 
    ViewCompat.setTranslationZ(getView(), 100.f); 
} 

आप केवल एनीमेशन की अवधि के लिए translationZ मूल्य को संशोधित करना चाहते हैं, तो आप कुछ इस तरह करना चाहिए:

@Override 
public Animation onCreateAnimation(int transit, final boolean enter, int nextAnim) { 
    Animation nextAnimation = AnimationUtils.loadAnimation(getContext(), nextAnim); 
    nextAnimation.setAnimationListener(new Animation.AnimationListener() { 

     private float mOldTranslationZ; 

     @Override 
     public void onAnimationStart(Animation animation) { 
      if (getView() != null && enter) { 
       mOldTranslationZ = ViewCompat.getTranslationZ(getView()); 
       ViewCompat.setTranslationZ(getView(), 100.f); 
      } 
     } 

     @Override 
     public void onAnimationEnd(Animation animation) { 
      if (getView() != null && enter) { 
       ViewCompat.setTranslationZ(getView(), mOldTranslationZ); 
      } 
     } 

     @Override 
     public void onAnimationRepeat(Animation animation) { 
     } 
    }); 
    return nextAnimation; 
} 
+0

इसे खोजने पर अच्छा काम, इस समाधान को बहुत पहले ढूंढ रहा था और अब इसे हल किया गया है। –

+0

धन्यवाद। काम करने लगता है। क्या मुझे पता है कि 'क्रिएटएनीमेशन' पर ओवरराइड करने के लिए, हमें 'एनीमेशन यूटिलसलोडएनीमेशन' के माध्यम से मैन्युअल रूप से एनीमेशन बनाने की आवश्यकता है? मुझे एहसास है कि अगर मैं super.onCreateAnimation के माध्यम से 'एनीमेशन' प्राप्त करने का प्रयास करता हूं, तो यह शून्य है। –

+0

@ चेकोयानचेंग क्योंकि 'Fragment.onCreateAnimation()' विधि डिफ़ॉल्ट रूप से कुछ भी नहीं करती है और केवल शून्य लौटाती है। यह तरीका आपको खुद को एनीमेशन बनाने की संभावना छोड़ने के लिए है। यदि आप 'FragmentManager.loadAnimation()' विधि को देखते हैं, तो आप इसे पहले 'fragment.onCreateAnimation()' से एनीमेशन प्राप्त करने का प्रयास करेंगे और यदि यह शून्य हो जाता है तो FragmentManager एनीमेशन स्वयं बनाता है। – JFrite

0
FragmentTransaction ft = ((AppCompatActivity) context).getSupportFragmentManager().beginTransaction(); 
       ft.setCustomAnimations(0, R.anim.slide_out_to_right); 
      if (!fragment.isAdded()) 
      { 
       ft.add(R.id.fragmentContainerFrameMyOrders, fragment); 
       ft.show(fragment); 
      } 
      else 
       ft.replace(R.id.fragmentContainerFrameMyOrders, fragment); 
      ft.commit(); 
0

यह मेरा रुचि रखने वाले किसी के लिए वर्तमान कार्यवाही।

समारोह में जोड़ने के लिए नई Fragment:

final Fragment toRemove = fragmentManager.findFragmentById(containerID); 
if (toRemove != null) { 
    new Handler().postDelayed(new Runnable() { 
      @Override 
      public void run() { 
       fragmentManager.beginTransaction().hide(toRemove).commit(); 
      } 
     }, 
     getResources().getInteger(android.R.integer.config_mediumAnimTime) + 100); 
     // Use whatever duration you chose for your animation for this handler 
     // I added an extra 100 ms because the first transaction wasn't always 
     // fast enough 
} 
fragmentManager.beginTransaction() 
    .setCustomAnimations(enter, 0, 0, popExit).add(containerID, fragmentToAdd) 
    .addToBackStack(tag).commit(); 

और onCreate में:

final FragmentManager fragmentManager = getSupportFragmentManager(); 
fragmentManager.addOnBackStackChangedListener(
     new FragmentManager.OnBackStackChangedListener() { 
      @Override 
      public void onBackStackChanged() { 
       Fragment current = fragmentManager.findFragmentById(containerID); 
       if (current != null && current.isHidden()) { 
        fragmentManager.beginTransaction().show(current).commit(); 
       } 
      } 
     }); 

मैं ऊपर एक हैंडलर के बजाय AnimationListener किसी प्रकार पसंद करते हैं, लेकिन मैं नहीं देखा किसी भी तरह से आप लेनदेन एनीमेशन के अंत का पता लगाने के लिए एक का उपयोग कर सकते हैं जो onCreateAnimation() जैसे टुकड़े से बंधे नहीं थे। उचित श्रोता के साथ कोई भी सुझाव/संपादन की सराहना की जाएगी।

मैं Fragment एस इंगित करता हूं कि मैं इस तरह से हल्का वजन जोड़ रहा हूं, इसलिए मुझे उनके टुकड़े के साथ टुकड़े के कंटेनर में रखने की कोई समस्या नहीं है।

आप टुकड़ा आप Handler के Runnable में fragmentManager.beginTransaction().remove(toRemove).commitAllowingStateLoss(); डाल सकता है दूर करने के लिए, और में OnBackStackChangedListener चाहते हैं:

// Use back stack entry tag to get the fragment 
Fragment current = getCurrentFragment(); 
if (current != null && !current.isAdded()) { 
    fragmentManager.beginTransaction() 
     .add(containerId, current, current.getTag()) 
     .commitNowAllowingStateLoss(); 
} 

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

संपादित करें:

FragmentTransaction: मैं निम्नलिखित कार्य है कि शायद FragmentTransaction.remove() और FragmentTransaction.add() ऊपर बदल सकते खोज की। detach():

यूआई से दिए गए टुकड़े को अलग करें। यह वही स्थिति है जब इसे बैक स्टैक पर रखा जाता है: यूआई से टुकड़ा हटा दिया जाता है, हालांकि इसके राज्य को अभी भी खंड प्रबंधक द्वारा सक्रिय रूप से प्रबंधित किया जा रहा है। इस राज्य में जाने पर इसका दृश्य पदानुक्रम नष्ट हो जाता है।

FragmentTransactionattach():

पहले विभाजित (टुकड़े) के साथ यूआई से अलग होने के बाद एक टुकड़ा दोबारा संलग्न करें। इससे यूआई से जुड़ा हुआ, और प्रदर्शित होने के लिए इसके दृश्य पदानुक्रम को फिर से बनाया जा सकता है।

संबंधित मुद्दे