50

कैसे जोड़ें मैं एक ViewPager तीन Fragments साथ है, हर एक से पता चलता एक List (या Grid)।एक ViewPager अंदर एक टुकड़ा नेस्टेड टुकड़ा (Android 4.2) का उपयोग कर

नए Android API level 17 (जेली बीन 4.2) में, सुविधाओं में से एक Nested Fragments है। नई कार्यक्षमता वर्णन कहते हैं:

यदि आप टुकड़े कि बाईं ओर स्वाइप और सही और स्क्रीन स्थान के बहुमत का उपभोग बनाने के लिए ViewPager का उपयोग, अब आप प्रत्येक खंड पेज में टुकड़े सम्मिलित कर सकते हैं।

तो, अगर मैं सही समझ में, अब मैं Fragments के साथ एक ViewPager (एक बटन उदाहरण के लिए अंदर के साथ) बना सकते हैं अंदर है, और जब उपयोगकर्ता प्रेस बटन बिना ढीला ViewPager इस नई सुविधा का उपयोग कर एक और Fragment दिखा।

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

पीएस: मुझे यह जानने के लिए केवल getChildFragmentManager के साथ काम करने में दिलचस्पी है।

+3

मैं इस जल्दी अगले सप्ताह के लिए एक नमूना पर काम किया जाएगा। यदि किसी ने तब तक किसी जवाब के साथ चिंतित नहीं किया है, तो मैं उस समय कुछ पोस्ट करने का प्रयास करूंगा। – CommonsWare

+0

आप @CommonsWare – sabadow

उत्तर

93

मान लें कि आपने सही एक्सएमएल लेआउट बनाए हैं। अब एक दृश्यपटल में टुकड़े प्रदर्शित करना बहुत आसान है जो किसी अन्य टुकड़े द्वारा होस्ट किया जाता है।

कोड एक माता पिता टुकड़ा में इस तरह दिखता है:

@Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     return inflater.inflate(R.layout.fragment_parent, container, false); 
    } 

    @Override 
    public void onViewCreated(View view, Bundle savedInstanceState) { 
     super.onViewCreated(view, savedInstanceState); 

     ViewPager mViewPager = (ViewPager) view.findViewById(R.id.viewPager); 
     mViewPager.setAdapter(new MyAdapter(getChildFragmentManager())); 
    } 

    public static class MyAdapter extends FragmentPagerAdapter { 

     public MyAdapter(FragmentManager fm) { 
      super(fm); 
     } 

     @Override 
     public int getCount() { 
      return 4; 
     } 

     @Override 
     public Fragment getItem(int position) { 
      Bundle args = new Bundle(); 
      args.putInt(TextViewFragment.POSITION_KEY, position); 
      return TextViewFragment.newInstance(args); 
     } 
    } 

यह जब FragmentPagerAdapter instantiating Fragment.getChildFragmentManager() उपयोग करने के लिए महत्वपूर्ण है। यह भी ध्यान रखें कि आप बच्चों के टुकड़ों पर Fragment.setRetainInstance() का उपयोग नहीं कर सकते हैं या आपको अपवाद मिलेगा।

स्रोत कोड में पाया जा सकता:https://github.com/marcoRS/nested-fragments

+1

मैं इस SherlockFragments और support.v4 release11 साथ (ViewPager, वह यह है कि युक्त टुकड़ा) कर समस्याओं दिखाई दे रही है, ViewPager सामग्री एडाप्टर के माध्यम से सेट हो जाता है लेकिन बच्चे के टुकड़े :(प्रदर्शित नहीं करते – straya

+0

हाय Straya। मैं के साथ मेरी उदाहरण का परीक्षण किया है शेरलॉकफ्रैगमेंट्स और मुझे कोई त्रुटि नहीं दिखाई दे रही है। आप क्या त्रुटि देख रहे हैं? –

+1

हेया, मुझे मिश्रण में एंड्रॉइड-व्यूपेगर इंडिकेटर भी मिला है।ViewPager और ViewPagerIndicator प्रदर्शित होते हैं (मेरे पास Fragment में ViewPager के ऊपर एक टेक्स्ट व्यू है, इसलिए मैं देख सकता हूं कि वह टुकड़ा प्रदर्शित होता है), लेकिन ViewPager के बच्चे Fragments (FragmentPagerAdapter के माध्यम से प्रदान किया गया) प्रदर्शित नहीं होते हैं। मैं पृष्ठों, संकेतक अद्यतनों के बीच स्वाइप कर सकता हूं लेकिन अभी भी बाल टुकड़े नहीं। – straya

11

संपादित करें: आप एक ViewPager आप अभी भी नेस्टेड टुकड़े इस्तेमाल कर सकते हैं में एक पृष्ठ के सभी सामग्री को बदलना चाहते हैं, लेकिन कुछ परिवर्तनों की आवश्यकता है तो। नीचे दिए गए नमूना जाँच करें (FragmentActivity, की स्थापना ViewPager और PagerAdapter कोड के पिछले टुकड़ा के रूप में ही हैं):

// this will act as a fragment container, representing one page in the ViewPager 
public static class WrapperFragment extends Fragment implements 
     ReplaceListener { 

    public static WrapperFragment newInstance(int position) { 
     WrapperFragment wp = new WrapperFragment(); 
     Bundle args = new Bundle(); 
     args.putInt("position", position); 
     wp.setArguments(args); 
     return wp; 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
     FrameLayout fl = new FrameLayout(getActivity()); 
     fl.setId(10000); 
     if (getChildFragmentManager().findFragmentByTag("initialTag") == null) { 
      InitialInnerFragment iif = new InitialInnerFragment(); 
      Bundle args = new Bundle(); 
      args.putInt("position", getArguments().getInt("position")); 
      iif.setArguments(args); 
      getChildFragmentManager().beginTransaction() 
        .add(10000, iif, "initialTag").commit(); 
     } 
     return fl; 
    } 

    // required because it seems the getChildFragmentManager only "sees" 
    // containers in the View of the parent Fragment. 
    @Override 
    public void onReplace(Bundle args) { 
     if (getChildFragmentManager().findFragmentByTag("afterTag") == null) { 
      InnerFragment iif = new InnerFragment(); 
      iif.setArguments(args); 
      getChildFragmentManager().beginTransaction() 
        .replace(10000, iif, "afterTag").addToBackStack(null) 
        .commit(); 
     } 
    } 

} 

// the fragment that would initially be in the wrapper fragment 
public static class InitialInnerFragment extends Fragment { 

    private ReplaceListener mListener; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
     mListener = (ReplaceListener) this.getParentFragment(); 
     LinearLayout ll = new LinearLayout(getActivity()); 
     Button b = new Button(getActivity()); 
     b.setGravity(Gravity.CENTER_HORIZONTAL); 
     b.setText("Frame " + getArguments().getInt("position")); 
     b.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       Bundle args = new Bundle(); 
       args.putInt("positionInner", 
         getArguments().getInt("position")); 
       if (mListener != null) { 
        mListener.onReplace(args); 
       } 
      } 
     }); 
     ll.setOrientation(LinearLayout.VERTICAL); 
     ll.addView(b, new LinearLayout.LayoutParams(250, 
       LinearLayout.LayoutParams.WRAP_CONTENT)); 
     return ll; 
    } 

} 

public static class InnerFragment extends Fragment { 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
     TextView tv = new TextView(getActivity()); 
     tv.setText("InnerFragment in the outher Fragment with position " 
       + getArguments().getInt("positionInner")); 
     return tv; 
    } 

} 

public interface ReplaceListener { 
    void onReplace(Bundle args); 
} 

का शीघ्रता से अवलोकन यह काम करता है पर, लेकिन जैसा कि मैंने यह परीक्षण नहीं किया मुद्दों दिखाई दे सकते हैं बहुत ज्यादा।

क्या कोई ऐसा करने का एक सरल उदाहरण दिखा सकता है?

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

public class NestedFragments extends FragmentActivity { 

    @Override 
    protected void onCreate(Bundle arg0) { 
     super.onCreate(arg0); 
     ViewPager vp = new ViewPager(this); 
     vp.setId(5000); 
     vp.setAdapter(new MyAdapter(getSupportFragmentManager())); 
     setContentView(vp); 
    } 

    private static class MyAdapter extends FragmentPagerAdapter { 

     public MyAdapter(FragmentManager fm) { 
      super(fm); 
     } 

     @Override 
     public Fragment getItem(int position) { 
      return WrapperFragment.newInstance(position); 
     } 

     @Override 
     public int getCount() { 
      return 8; 
     } 
    } 

    public static class WrapperFragment extends Fragment { 

     public static WrapperFragment newInstance(int position) { 
      WrapperFragment wp = new WrapperFragment(); 
      Bundle args = new Bundle(); 
      args.putInt("position", position); 
      wp.setArguments(args); 
      return wp; 
     } 

     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
       Bundle savedInstanceState) { 
      LinearLayout ll = new LinearLayout(getActivity()); 
      FrameLayout innerFragContainer = new FrameLayout(getActivity()); 
      innerFragContainer.setId(1111); 
      Button b = new Button(getActivity()); 
      b.setText("Frame " + getArguments().getInt("position")); 
      b.setOnClickListener(new OnClickListener() { 

       @Override 
       public void onClick(View v) { 
        InnerFragment innerFragment = new InnerFragment(); 
        Bundle args = new Bundle(); 
        args.putInt("positionInner", 
          getArguments().getInt("position")); 
        innerFragment.setArguments(args); 
        FragmentTransaction transaction = getChildFragmentManager() 
          .beginTransaction(); 
        transaction.add(1111, innerFragment).commit(); 
       } 
      }); 
      ll.setOrientation(LinearLayout.VERTICAL); 
      ll.addView(b, new LinearLayout.LayoutParams(
        LinearLayout.LayoutParams.MATCH_PARENT, 
        LinearLayout.LayoutParams.WRAP_CONTENT)); 
      ll.addView(innerFragContainer, new LinearLayout.LayoutParams(
        LinearLayout.LayoutParams.MATCH_PARENT, 
        LinearLayout.LayoutParams.MATCH_PARENT)); 
      return ll; 
     } 

    } 

    public static class InnerFragment extends Fragment { 

     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
       Bundle savedInstanceState) { 
      TextView tv = new TextView(getActivity()); 
      tv.setText("InnerFragment in the outher Fragment with position " 
        + getArguments().getInt("positionInner")); 
      return tv; 
     } 

    } 

} 

मैं आलसी था और कोड में सब कुछ किया, लेकिन मुझे यकीन है कि यह कर सकते हैं कर रहा हूँ फुफ्फुसीय एक्सएमएल लेआउट के साथ काम करें।

+1

बहुत बहुत शुक्रिया धन्यवाद, मैं कोशिश कर रहा है और पुनर्रचना एक्सएमएल लेआउट फाइलों के साथ उपयोग करने के लिए और ठीक से काम करने लगता है कर रहा हूँ;) – sabadow

+0

मुझे लगता है कि जहां आप का उपयोग 'transaction.add (1111, innerFragment) .commit() ; ''प्रतिस्थापन विधि' का उपयोग करना चाहिए, क्योंकि बटन दबाए जाने पर हर बार पदानुक्रम में एक लेआउट जोड़ें। इसके अलावा मैं एक्सएमएल लेआउट का उपयोग करने के लिए उदाहरण को दोबारा प्रतिक्रिया देता हूं और पेज ** की सभी ** ** को प्रतिस्थापित करने के लिए बदलने की कोशिश करता हूं। लेकिन मैं इसे अभी तक नहीं बना सका, हमेशा 'बटन' शीर्ष पर रहता है। कोई उपाय? – sabadow

+0

@ लक्सप्रोग: यह वह परिदृश्य नहीं है जिसके बारे में मैं सोच रहा था। मैं एक नमूने पर काम करने जा रहा हूं जहां 'व्यूपागर' स्वयं को एक टुकड़े द्वारा होस्ट किया जाता है और इसके पृष्ठों के लिए टुकड़े होते हैं। उस * को 'getChildFragmentManager() 'को' पेजर एडाप्टर 'में पास करने का मामला होना चाहिए, लेकिन मैं इसे पहले कोशिश करना चाहता हूं। आपका उदाहरण एक 'व्यूपैगर' होल्डिंग टुकड़े का प्रदर्शन कर रहा है जो स्वयं को अन्य टुकड़े रखते हैं - पूरी तरह से उचित, बस जब मैं प्रश्न पढ़ता हूं तो मैं सोच रहा था। – CommonsWare

6

मैं 3 तत्वों और सूचकांक 2 और 3 और यहाँ के लिए 2 उप तत्वों के साथ एक ViewPager बनाया है मुझे क्या करना ..

enter image description here

चाहता था

मैं पिछले सवाल और stackoverflow से जवाब की मदद से इस लागू किया और यहाँ की कड़ी है है।

ViewPagerChildFragments

+0

के अंदर अलग-अलग लेआउट कैसे ला सकता हूं इस कोड के साथ कुछ बग हैं जैसे कि यह बदलते अभिविन्यास पर क्रैश हो रहा है। क्या आपने कभी उन्हें ठीक किया है? –

+0

क्या कोई इस कोड के साथ बग को ठीक करने में कामयाब रहा है जो ऐप को अभिविन्यास परिवर्तन पर क्रैश करने का कारण बनता है? –