2013-05-27 94 views
0

存在一些問題,我似乎無法找到問題。如何強制從FragmentStatePagerAdapter子中強制重新創建片段

我有一個實現自定義TabAdapter的FragmentStatePagerAdapter。一切正常,除了我有一種情況,其中FragmentStatePagerAdapter中的某個片段可能會更改某些需要所有片段重新創建其視圖的項目。

例如,在片段D中,用戶更改了某些內容 - >然後碎片A,B,C中的值需要更改。這在片段A和B中立即發生,因爲它們的視圖還沒有被創建。但是,片段C已經創建,因爲它似乎始終創建3個片段,至少在默認情況下(前一個,當前,下一個)。因此,片段C不會被更新。

因此,最終我需要一種方法來強制適配器中的所有片段在其中一個片段(A,B,C或D)發生某些變化時重新創建其視圖。

這裏是我的FragmentStatePagerAdapter

public class MyTabsAdapter extends FragmentStatePagerAdapter implements 
    TabsAdapter { 

private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>(); 
private final ViewPager mPager; 

private Activity mContext; 

/* 
* TabInfo- Simple object to keep track of the tabs. 
*/ 
private class TabInfo { 
    private String fragName; 
    private String title; 

    TabInfo(String fragName, String title) { 
     this.fragName = fragName; 
     this.title = title; 
    } 

    String getFragName() { 
     return this.fragName; 
    } 

    String getTitle() { 
     return this.title; 
    } 
} 

public MyTabsAdapter(FragmentActivity ctx, ViewPager pager) { 
    super(ctx.getSupportFragmentManager()); 
    this.mContext = ctx; 
    this.mPager = pager; 

    this.mPager.setAdapter(this); 
} 

/* 
* getView - get Tab view 
*/ 
@SuppressLint("DefaultLocale") 
public View getView(int position) { 
    Button tab; 

    LayoutInflater inflater = mContext.getLayoutInflater(); 
    tab = (Button) inflater.inflate(R.layout.tab_scrolling, null); 

    tab.setText(this.mTabs.get(position).getTitle().toUpperCase()); 

    return tab; 
} 

public void addTab(String fragName, String title) { 
    TabInfo info = new TabInfo(fragName, title); 
    mTabs.add(info); 
} 

@Override 
public Fragment getItem(int position) { 
    String fragName = mTabs.get(position).getFragName(); 
    if (fragName == "FragmentA") { 
     return FragmentA.newInstance(); 
    } else if (fragName == "FragmentB") { 
     return FragmentB.newInstance(); 
    } else if (fragName == "FragmentC") { 
     return FragmentC.newInstance(); 
    } else if (fragName == "FragmentD") { 
     return FragmentD.newInstance(); 
    } 

    return null; 
} 

@Override 
public int getCount() { 
    return mTabs.size(); 
} 

} 

片段簡單地通過加入到這一點:

MyTabsAdapter mAdapter = new MyTabsAdapter(this, myViewPager); 
mAdapter.addTab("FragmentB", "Fragment B") 

這一切工作正常,我必須與標籤適配器/視圖/等任何問題。只要找到我可以在FragmentA/B/C/D發生變化時「強制」適配器刪除/重新創建其他項目。

謝謝,如果需要的話

回答

0

如果您需要更改適配器數據刪除並重新創建我已經在Android的Support4Demos做簡單的修改來證明我是如何更新我的適配器的片段頁面將提供更多的信息。

/** 
* Demonstrates combining a TabHost with a ViewPager to implement a tab UI 
* that switches between tabs and also allows the user to perform horizontal 
* flicks to move between the tabs. 
*/ 
public class FragmentTabsPager extends FragmentActivity implements View.OnClickListener,FragmentCallBack{ 

    TabHost mTabHost; 
    ViewPager mViewPager; 

    TabsAdapter mTabsAdapter; 

    private Button mBtn_nextFragment; 


    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setContentView(R.layout.fragment_tabs_pager); 
     mTabHost = (TabHost)findViewById(android.R.id.tabhost); 

     mBtn_nextFragment=(Button)findViewById(R.id.btn_next_fragment); 

     mBtn_nextFragment.setOnClickListener(this); 

     mTabHost.setup(); 

     mViewPager = (ViewPager)findViewById(R.id.pager); 

     mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager); 

     mTabsAdapter.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"), 
       FragmentStackSupport.CountingFragment.class, null); 
     mTabsAdapter.addTab(mTabHost.newTabSpec("contacts").setIndicator("Contacts"), 
       LoaderCursorSupport.CursorLoaderListFragment.class, null); 
     mTabsAdapter.addTab(mTabHost.newTabSpec("custom").setIndicator("Custom"), 
       LoaderCustomSupport.AppListFragment.class, null); 
     mTabsAdapter.addTab(mTabHost.newTabSpec("throttle").setIndicator("Throttle"), 
       LoaderThrottleSupport.ThrottledLoaderListFragment.class, null); 

     if (savedInstanceState != null) { 
      mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); 
     } 
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
     super.onSaveInstanceState(outState); 
     outState.putString("tab", mTabHost.getCurrentTabTag()); 
    } 

    /** 
    * This is a helper class that implements the management of tabs and all 
    * details of connecting a ViewPager with associated TabHost. It relies on a 
    * trick. Normally a tab host has a simple API for supplying a View or 
    * Intent that each tab will show. This is not sufficient for switching 
    * between pages. So instead we make the content part of the tab host 
    * 0dp high (it is not shown) and the TabsAdapter supplies its own dummy 
    * view to show as the tab content. It listens to changes in tabs, and takes 
    * care of switch to the correct paged in the ViewPager whenever the selected 
    * tab changes. 
    */ 
    public static class TabsAdapter extends FragmentStatePagerAdapter 
      implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener { 
     private final Context mContext; 
     private final TabHost mTabHost; 
     private final ViewPager mViewPager; 
     private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>(); 

     static final class TabInfo { 
      private final String tag; 
      private final Class<?> clss; 
      private final Bundle args; 

      TabInfo(String _tag, Class<?> _class, Bundle _args) { 
       tag = _tag; 
       clss = _class; 
       args = _args; 
      } 
     } 

     static class DummyTabFactory implements TabHost.TabContentFactory { 
      private final Context mContext; 

      public DummyTabFactory(Context context) { 
       mContext = context; 
      } 

      @Override 
      public View createTabContent(String tag) { 
       View v = new View(mContext); 
       v.setMinimumWidth(0); 
       v.setMinimumHeight(0); 
       return v; 
      } 
     } 

     public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager pager) { 
      super(activity.getSupportFragmentManager()); 
      mContext = activity; 
      mTabHost = tabHost; 
      mViewPager = pager; 
      mTabHost.setOnTabChangedListener(this); 
      mViewPager.setAdapter(this); 
      mViewPager.setOnPageChangeListener(this); 
     } 

     public void clearData(){ 

      mTabs.clear(); 
      notifyDataSetChanged(); 

     } 

     public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) { 
      tabSpec.setContent(new DummyTabFactory(mContext)); 
      String tag = tabSpec.getTag(); 

      TabInfo info = new TabInfo(tag, clss, args); 
      mTabs.add(info); 

      mTabHost.addTab(tabSpec); 

      notifyDataSetChanged(); 
     } 

     @Override 
     public int getCount() { 
      return mTabs.size(); 
     } 

     @Override 
     public Fragment getItem(int position) { 
      TabInfo info = mTabs.get(position); 
      return Fragment.instantiate(mContext, info.clss.getName(), info.args); 
     } 

     @Override 
     public void onTabChanged(String tabId) { 
      int position = mTabHost.getCurrentTab(); 
      mViewPager.setCurrentItem(position); 
     } 

     @Override 
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 

     } 

     @Override 
     public void onPageSelected(int position) { 
      // Unfortunately when TabHost changes the current tab, it kindly 
      // also takes care of putting focus on it when not in touch mode. 
      // The jerk. 
      // This hack tries to prevent this from pulling focus out of our 
      // ViewPager. 
      TabWidget widget = mTabHost.getTabWidget(); 
      int oldFocusability = widget.getDescendantFocusability(); 
      widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); 
      mTabHost.setCurrentTab(position); 
      widget.setDescendantFocusability(oldFocusability); 

     } 

     @Override 
     public void onPageScrollStateChanged(int state) { 
     } 
    } 

    @Override 
    public void onClick(View v) { 


     mTabsAdapter.clearData(); 

     mTabHost.clearAllTabs(); 
     //mTabsAdapter.notifyDataSetChanged(); 

     Bundle mBundleSimple=new Bundle(); 
     mBundleSimple.putString("data", "SimpleData"); 

     mTabsAdapter.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"), 
       FragmentStackSupport.CountingFragment.class, mBundleSimple); 

     Bundle mBundleContacts=new Bundle(); 
     mBundleContacts.putString("data", "Contacts"); 

     mTabsAdapter.addTab(mTabHost.newTabSpec("contacts").setIndicator("Contacts"), 
       LoaderCursorSupport.CursorLoaderListFragment.class, mBundleContacts); 

     Bundle mBundleCustom=new Bundle(); 
     mBundleCustom.putString("data", "Custom"); 

     mTabsAdapter.addTab(mTabHost.newTabSpec("custom").setIndicator("Custom"), 
       LoaderCustomSupport.AppListFragment.class, mBundleCustom); 

     Bundle mBundleThrottle=new Bundle(); 
     mBundleThrottle.putString("data", "Throttle"); 

     mTabsAdapter.addTab(mTabHost.newTabSpec("throttle").setIndicator("Throttle"), 
       LoaderThrottleSupport.ThrottledLoaderListFragment.class, mBundleThrottle); 


     mViewPager.setAdapter(mTabsAdapter); 

    } 

    @Override 
    public void ClickButton(String strToken) { 

     if(strToken.equalsIgnoreCase("OneBtn")){ 


      mTabsAdapter.clearData(); 

      mTabHost.clearAllTabs(); 
      //mTabsAdapter.notifyDataSetChanged(); 

      Bundle mBundleSimple=new Bundle(); 
      mBundleSimple.putString("data", "SimpleData"); 

      mTabsAdapter.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"), 
        FragmentStackSupport.CountingFragment.class, mBundleSimple); 

      Bundle mBundleContacts=new Bundle(); 
      mBundleContacts.putString("data", "SimpleData"); 

      mTabsAdapter.addTab(mTabHost.newTabSpec("contacts").setIndicator("Contacts"), 
        LoaderCursorSupport.CursorLoaderListFragment.class, mBundleContacts); 

      Bundle mBundleCustom=new Bundle(); 
      mBundleCustom.putString("data", "Custom"); 

      mTabsAdapter.addTab(mTabHost.newTabSpec("custom").setIndicator("Custom"), 
        LoaderCustomSupport.AppListFragment.class, mBundleCustom); 

      Bundle mBundleThrottle=new Bundle(); 
      mBundleThrottle.putString("data", "Throttle"); 

      mTabsAdapter.addTab(mTabHost.newTabSpec("throttle").setIndicator("Throttle"), 
        LoaderThrottleSupport.ThrottledLoaderListFragment.class, mBundleThrottle); 


      mViewPager.setAdapter(mTabsAdapter); 
     } 

    } 
} 

在上面的片段活動中,我已經做出以下更改以重新創建適配器數據。

1.製作清除碎片列表的公共函數,在本例中爲mTabs。 2.清除碎片數組後添加您的新片段與您所需的更改,在上面的類,你可以看到,我已經添加片段與它的捆綁,並且我可以在所有片段類。 3.在ViewPager中設置Adaper。

下面是保存片段代碼的類。

public class FragmentStackSupport extends FragmentActivity { 
    int mStackLevel = 1; 

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

     // Watch for button clicks. 
     Button button = (Button)findViewById(R.id.new_fragment); 
     button.setOnClickListener(new OnClickListener() { 
      public void onClick(View v) { 
       addFragmentToStack(); 
      } 
     }); 
     button = (Button)findViewById(R.id.home); 
     button.setOnClickListener(new OnClickListener() { 
      public void onClick(View v) { 
       // If there is a back stack, pop it all. 
       FragmentManager fm = getSupportFragmentManager(); 
       if (fm.getBackStackEntryCount() > 0) { 
        fm.popBackStack(fm.getBackStackEntryAt(0).getId(), 
          FragmentManager.POP_BACK_STACK_INCLUSIVE); 
       } 
      } 
     }); 

     if (savedInstanceState == null) { 
      // Do first time initialization -- add initial fragment. 
      Fragment newFragment = CountingFragment.newInstance(mStackLevel); 
      FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
      ft.add(R.id.simple_fragment, newFragment).commit(); 
     } else { 
      mStackLevel = savedInstanceState.getInt("level"); 
     } 
    } 

    @Override 
    public void onSaveInstanceState(Bundle outState) { 
     super.onSaveInstanceState(outState); 
     outState.putInt("level", mStackLevel); 
    } 


    void addFragmentToStack() { 
     mStackLevel++; 

     // Instantiate a new fragment. 
     Fragment newFragment = CountingFragment.newInstance(mStackLevel); 

     // Add the fragment to the activity, pushing this transaction 
     // on to the back stack. 
     FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
     ft.replace(R.id.simple_fragment, newFragment); 
     ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); 
     ft.addToBackStack(null); 
     ft.commit(); 
    } 



    public static class CountingFragment extends Fragment implements OnClickListener { 
     int mNum; 

     Button mBtnOne; 

     FragmentCallBack mFragmentCallBack; 

     /** 
     * Create a new instance of CountingFragment, providing "num" 
     * as an argument. 
     */ 
     static CountingFragment newInstance(int num) { 
      CountingFragment f = new CountingFragment(); 

      // Supply num input as an argument. 
      Bundle args = new Bundle(); 
      args.putInt("num", num); 
      f.setArguments(args); 

      return f; 
     } 

     /** 
     * When creating, retrieve this instance's number from its arguments. 
     */ 
     @Override 
     public void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      mNum = getArguments() != null ? getArguments().getInt("num") : 1; 


      if(getArguments()!=null){ 

       if(getArguments().containsKey("data")){ 

        String dataIs=getArguments().getString("data"); 

        Log.v("LOG_TAG", "THis Tab data is "+ dataIs); 


       } 
      } 
     } 

     /** 
     * The Fragment's UI is just a simple text view showing its 
     * instance number. 
     */ 
     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
       Bundle savedInstanceState) { 

      if(getArguments()!=null){ 

       if(getArguments().containsKey("data")){ 

        String dataIs=getArguments().getString("data"); 

        Log.v("LOG_TAG", "THis Tab data is onCreateView "+ dataIs); 


       } 
      } 

      View v = inflater.inflate(R.layout.hello_world, container, false); 

      TextView tv = (TextView) v.findViewById(R.id.text); 

      mBtnOne=(Button)v.findViewById(R.id.btn_one); 

      mBtnOne.setOnClickListener(this); 

      tv.setText("Fragment #" + mNum); 
      tv.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.gallery_thumb)); 
      return v; 
     } 

     @Override 
     public void onClick(View v) { 

      try{ 
       mFragmentCallBack=(FragmentCallBack) this.getActivity(); 

       mFragmentCallBack.ClickButton("OneBtn"); 

      }catch(ClassCastException classExc){ 

       classExc.printStackTrace(); 
      } 

     } 
    } 

} 

現在,當一些事情是在你的任何片段的變化,你需要創建一個界面,發送回叫FragmentActivity持有你ViewPager這樣你就可以刪除現有的片段,再重新創建它。

這是我的接口類。

public interface FragmentCallBack { 


    public void ClickButton(String strToken); 
} 

希望你會得到你如何在你的代碼中做同樣的事情。