2012-10-09 146 views
2

首先我readed一些其他線程說起這個,像這樣: Replace Fragment inside a ViewPagerViewPager + FragmentPagerAdapter +每個標籤多個片段

我有一個自定義FragmentStackAdapter來管理應用程序的所有片段,最後請求客戶端將在所有應用程序中顯示選項卡,因此我決定實施SherlockActionBar +選項卡+ viewpager(用於幻燈片)。

我有下實現FragmentStackAdapter的:

public class FragmentStackAdapter extends FragmentPagerAdapter { 

/** 
* Logging tag 
*/ 
private final static String TAG = "FragmentStackAdapter"; 

/** 
* Fragment Manager 
*/ 
private FragmentManager fm; 

/** 
* Container of this adapter 
*/ 
private ViewPager pager; 

/** 
* Current tab position (SET THIS in the TAB LISTENER) 
*/ 
private Integer currentTabPosition; 

/** 
* Array of stacks to get fragment stack list. 
*/ 
private SparseArray<LinkedList<Fragment>> stackFragments = new SparseArray<LinkedList<Fragment>>(); 

/** 
* Default constructor 
* @param fm FragmentManager 
*/ 
public FragmentStackAdapter(FragmentManager fm, ViewPager pager) { 

    super(fm); 
    this.fm = fm; 
    this.pager = pager; 
} 

public void addRootFragmentAtPosition(int tabPos, Fragment rootFragment) { 

    if (tabPos > stackFragments.size() - 1) { 
     stackFragments.put(tabPos, new LinkedList<Fragment>()); 
    } 

    LinkedList<Fragment> stack = stackFragments.get(tabPos); 
    stack.add(0, rootFragment); 

} 

public Fragment getRootFragment(int tabPos) { 

    return stackFragments.get(tabPos).get(0); 

} 

public void addFragment(Fragment f) { 

    startUpdate(pager); 

    Tools.logLine(TAG, "addFragment(): Fragment:" + f + ", in position: " + currentTabPosition); 
    LinkedList<Fragment> stack = stackFragments.get(currentTabPosition); 
    Fragment last = stack.getLast(); 
    stack.addLast(f); 

    fm.beginTransaction() 
     .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) 
     .remove(last) 
     .add(pager.getId(), f) 
     .commit(); 


    finishUpdate(pager); 
    notifyDataSetChanged(); 

} 

/** 
* Goes back in the current selected tab. 
* @return true if it goes back, false if cannot cause the stack is in the last element. Util for handle super.onPressback(). 
*/ 
public boolean back() { 

    LinkedList<Fragment> stack = stackFragments.get(currentTabPosition); 

    if (stack.size() > 1) { 

     startUpdate(pager); 

     Fragment currentFragment = stack.getLast(); 
     stack.removeLast(); 
     fm.beginTransaction() 
      .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) 
      .remove(currentFragment) 
      .add(pager.getId(), stack.getLast()) 
     .commit(); 

     notifyDataSetChanged(); 
     finishUpdate(pager); 

     return true; 

    } 

    return false; 
} 

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

@Override 
public Fragment getItem(int pos) { 

    LinkedList<Fragment> stack = stackFragments.get(pos); 

    Fragment last = stack.getLast(); 

    Tools.logLine(TAG, "getItem() pos: " + pos + ", fragment:" + last.toString() + ", isV:" + last.isVisible() + ", isD:" + last.isDetached()); 
    return last; 

} 

@Override 
public int getItemPosition(Object object) { 

    int size = stackFragments.size(); 
    for (int i = 0 ; i < size ; i++) { 

     int key = stackFragments.keyAt(i); 
     LinkedList<Fragment> stack = stackFragments.get(key); 

     if (stack.contains(object)) { 

      int indexOf = stack.indexOf(object); 

      // is root activity and is the current selected tab 
      if (key == currentTabPosition && indexOf == 0) { 

       return POSITION_NONE; // force reload this fragment 

      } else if (indexOf == 0) { // if root and other, no changes 

       return POSITION_UNCHANGED; 

      } 

      Tools.logLine(TAG, "getItemPos:, indexOf: " + indexOf + ", Object:" + object.toString()); 
      return indexOf; // return the pos of the activity 

     } 

    } 

    Tools.logLine(TAG, "getItemPos: RETURN DEFAULTTTTT POSITION_NONE, " + object.toString()); 

    return POSITION_NONE; // the current item is not in the stack, so probabilly we removed it pressing back. Reload this tab will get another getItem and return the new corresponding item 

} 

@Override 
public CharSequence getPageTitle(int position) { 

    return "Near"; 

} 

@Override 
public long getItemId(int position) { 

    LinkedList<Fragment> stack = stackFragments.get(position); 
    Fragment f = stack.getLast(); 

    int rtnid = f.hashCode(); 

    Tools.logLine(TAG, "getItemId() for pos: " + position + ", Fragment: "+ f +", rtnId: " + rtnid + ", hex: " + Integer.toString(rtnid, 16)); 

    return rtnid; 

} 

public void setCurrentTabPostion(int currentTabPosition) { 
    this.currentTabPosition = currentTabPosition; 
} 
    } 

這是我從我的MainActivity初始化:

//指定UI fieds viewPager =(ViewPager)findViewById(R。 id.pager);

// Configure the StackAdapter 
    fragmentAdapter = new FragmentStackAdapter(getSupportFragmentManager(), viewPager); 
    fragmentAdapter.addRootFragmentAtPosition(TIMELINE_TAG, new TimelineActivity()); 
    fragmentAdapter.addRootFragmentAtPosition(NEAR_TAG, new NearFragment()); 

我認爲它的工作原理確定當我打電話fragmentAdapter.addFragment()它顯示了新片段在先前加載片段,但是當我處理失敗「回()」方法表示該堆棧跟蹤:

 did=1: thread exiting with uncaught exception (group=0x400205a0) 
     FATAL EXCEPTION: main 
     java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. 
      at android.view.ViewGroup.addViewInner(ViewGroup.java:2062) 
      at android.view.ViewGroup.addView(ViewGroup.java:1957) 
      at android.view.ViewGroup.addView(ViewGroup.java:1914) 
      at android.view.ViewGroup.addView(ViewGroup.java:1894) 
      at android.support.v4.app.NoSaveStateFrameLayout.wrap(NoSaveStateFrameLayout.java:40) 
      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:875) 
      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1083) 
      at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:635) 
      at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1431) 
      at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:431) 
      at com.bbva.tweetmeter.ui.FragmentStackAdapter.getItemPosition(FragmentStackAdapter.java:311) 
      at android.support.v4.view.ViewPager.dataSetChanged(ViewPager.java:712) 
      at android.support.v4.view.ViewPager$PagerObserver.onChanged(ViewPager.java:2519) 
      at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:31) 
      at android.support.v4.view.PagerAdapter.notifyDataSetChanged(PagerAdapter.java:276) 
      at com.bbva.tweetmeter.ui.FragmentStackAdapter.back(FragmentStackAdapter.java:154) 
      at com.bbva.tweetmeter.ui.MainActivity.onBackPressed(MainActivity.java:210) 
      at android.app.Activity.onKeyUp(Activity.java:1985) 
      at android.view.KeyEvent.dispatch(KeyEvent.java:1513) 
      at android.app.Activity.dispatchKeyEvent(Activity.java:2210) 
      at com.actionbarsherlock.app.SherlockFragmentActivity.dispatchKeyEvent(SherlockFragmentActivity.java:122) 
      at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1769) 
      at android.view.ViewRoot.deliverKeyEventToViewHierarchy(ViewRoot.java:2716) 
      at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2688) 
      at android.view.ViewRoot.handleMessage(ViewRoot.java:1969) 
      at android.os.Handler.dispatchMessage(Handler.java:99) 
      at android.os.Looper.loop(Looper.java:143) 
      at android.app.ActivityThread.main(ActivityThread.java:4293) 
      at java.lang.reflect.Method.invokeNative(Native Method) 
      at java.lang.reflect.Method.invoke(Method.java:507) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 
      at dalvik.system.NativeStart.main(Native Method) 

爲什麼顯示此跟蹤如果我替換以前的片段爲什麼有父母附加?任何方式來處理這個?

隨意問,如果我不解釋正確

+0

*更新*我看到的是當我調用back()方法時,主碎片已經連接。我不知道爲什麼,因爲我已經刪除了addFragment方法... – PaNaVTEC

回答

1

這是onCreateView執行片段中的一個問題。我返回的視圖保存在一個實例變量allways,然後當片段重新附加調用onCreateView另一次,但返回相同的視圖,所以這個視圖已經有一個父。正確的實現是重新創建其他視圖,而不是保存在前一個視圖的實例變量中。

+0

這裏有一個替代解決方案:http://stackoverflow.com/a/15336705/878126或者你可以使用setOffscreenPageLimit:http://developer.android.com /reference/android/support/v4/view/ViewPager.html#setOffscreenPageLimit(int) –

4

我有,當我用

View res = inflater.inflate(R.layout.fragment_guide_search, container); 

內Fragment.onCreateView(...同樣的問題

必須調用

View res = inflater.inflate(R.layout.fragment_guide_search, container, false); 

View res = inflater.inflate(R.layout.fragment_guide_search, null); 

BE CA關於最後的選擇。要了解究竟偏偏閱讀這篇大文章: http://www.doubleencore.com/2013/05/layout-inflation-as-intended/

1

我使用FragmentPagerAdapter時,如果您正在使用FragmentPagerAdapter工作就用destroyItem內FragmentPagerAdapter方法有同樣的問題。

@Override 
public void destroyItem(ViewGroup container, int position, Object object) 
{ 
     FragmentTransaction ft=fm.beginTransaction(); 
     ft.remove((Fragment) object); 
     ft.commit(); 
} 

setOffscreenPageLimit(int limit)消耗更多的內存,在某些情況下,它不能正常工作。 其任何一方的保留狀態見說明。 setOffscreenPageLimit(int limit) - 設置在空閒狀態下視圖層次結構中應保留在當前頁面任一側的頁數。

相關問題