3

以前的片段嘛,想想我有兩個片段FragmentTab1 & ShowAllContactFragmentFragmentTab1列表視圖 &和按鈕組成。當按鈕被點擊時,我替換ViewPager中的ShowAllContactFragment。當顯示ShowAllContactFragment時,用戶可以通過選擇列表視圖中的複選框來選擇多個聯繫人&它也有一個ADD聯繫人按鈕。如何在片段更新列表視圖時回內viewpager

我需要什麼:我想更新現有的FragmentTab1列表視圖,當用戶按下在ShowAllContactFragment ADD按鈕,選擇在此列表視圖一些接觸之後。我也刪除ShowAllContactFragment,並顯示FragmentTab1何時會發生。

我的解決狀態:我按照android developers論壇在片段之間通過Activity進行數據通信。我就快完成了。我在MainActivity的ShowAllContactFragment &實現中創建了Interface OnContactSelectedListener。一切都好! 。經過調試,我檢查了我的回調方法,我在MainActivity中有數據但我無法替代ShowAllContactFragment &無法顯示前一個片段FragmentTab1 &更新它的列表視圖。

從FragmentTab1打開ShowAllContactFragment,我寫的一樣:

ShowAllContactFragment allContactsFragment = new ShowAllContactFragment(); 

      FragmentTransaction transaction = getFragmentManager() 
        .beginTransaction(); 
      transaction.addToBackStack(null); 
      transaction.add(R.id.fragmentTabLayout1, allContactsFragment); 
      transaction.commit(); 

我的MainActivity & FragmentAdapter看起來:

public class MainActivity extends SherlockFragmentActivity implements 
     ShowAllContactFragment.OnContactSelectedListener { 

    ActionBar.Tab Tab1, Tab2, Tab3, Tab4; 
    private Context context = this; 
    // view pager 
    // Declare Variables 
    ActionBar actionBar; 
    ViewPager mPager; 
    Tab tab; 
    FragmentAdapter mAdapter; 
    List<Fragment> fragmentList = new ArrayList<Fragment>(); 
    ArrayList<Person> blackListPersonList; 

    private final static String TAG_FRAGMENT = "TAG_FRAGMENT"; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     // set application in portrait mode 
     ActivityHelper.initialize(this); 

     actionBar = getSupportActionBar(); 
     actionBar.setDisplayShowHomeEnabled(true); 
     actionBar.setDisplayShowTitleEnabled(true); 
     actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 
     addFragmentsInList(); 
     // Locate ViewPager in activity_main.xml 
     mPager = (ViewPager) findViewById(R.id.pager); 
     // add an adapter to pager 
     mAdapter = new FragmentAdapter(getSupportFragmentManager(), mPager, 
       actionBar, fragmentList); 
     mPager.setAdapter(mAdapter); 
     addActionBarTabs(); 

    } 

    public void addFragmentsInList() { 

     FragmentTab1 aFragmentTab1 = new FragmentTab1(); 

     fragmentList.add(new FragmentTab1()); 
     fragmentList.add(new FragmentTab2()); 
     fragmentList.add(new FragmentTab3()); 

    } 

    private void addActionBarTabs() { 

     String[] tabs = { "Tab 1", "Tab 2", "Tab 3" }; 
     for (String tabTitle : tabs) { 
      ActionBar.Tab tab = actionBar.newTab().setText(tabTitle) 
        .setTabListener(tabListener); 
      actionBar.addTab(tab); 

     } 

    } 

    private ActionBar.TabListener tabListener = new ActionBar.TabListener() { 
     @Override 
     public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) { 
      mPager.setCurrentItem(tab.getPosition()); 
     } 

     @Override 
     public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) { 
     } 

     @Override 
     public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) { 
     } 
    }; 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // add action menu here 
     MenuInflater inflater = getSupportMenuInflater(); 
     inflater.inflate(R.menu.activity_itemlist, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     // Handle presses on the action bar items 
     switch (item.getItemId()) { 
     case R.id.add_item: 
      // openSearch(); 
      Toast.makeText(context, " add_item ", Toast.LENGTH_SHORT).show(); 
      return true; 
     case R.id.about: 
      // composeMessage(); 
      Toast.makeText(context, " about", Toast.LENGTH_SHORT).show(); 
      return true; 
     default: 
      return super.onOptionsItemSelected(item); 
     } 
    } 

    class FragmentAdapter extends FragmentPagerAdapter implements 
      ViewPager.OnPageChangeListener { 

     private ViewPager mViewPager; 
     final int TOTAL_PAGES = 3; 
     private List<Fragment> fragments; 
     SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>(); 

     public FragmentAdapter(FragmentManager fm, ViewPager pager, 
       ActionBar actionBar, List<Fragment> fragmentsList) { 
      super(fm); 
      this.mViewPager = pager; 
      this.mViewPager.setOnPageChangeListener(this); 
      this.fragments = fragmentsList; 
     } 

     @Override 
     public Fragment getItem(int position) { 
      // switch (position) { 
      // case 0: 
      // return FragmentTab1.newInstance(); 
      // case 1: 
      // return FragmentTab2.newInstance(); 
      // case 2: 
      // return FragmentTab3.newInstance(); 
      // default: 
      // throw new IllegalArgumentException(
      // "The item position should be less or equal to:" 
      // + TOTAL_PAGES); 
      // } 

      return this.fragments.get(position); 
     } 

     @Override 
     public int getCount() { 
      // return TOTAL_PAGES; 
      return this.fragments.size(); 

     } 

     public ViewPager getViewPager() { 

      return mViewPager; 
     } 

     // added newly 
     @Override 
     public Object instantiateItem(ViewGroup container, int position) { 
      Fragment fragment = (Fragment) super.instantiateItem(container, 
        position); 
      registeredFragments.put(position, fragment); 
      return fragment; 
     } 

     @Override 
     public void destroyItem(ViewGroup container, int position, Object object) { 
      registeredFragments.remove(position); 
      super.destroyItem(container, position, object); 
     } 

     public Fragment getRegisteredFragment(int position) { 
      return registeredFragments.get(position); 
     } 

     @Override 
     public void onPageScrollStateChanged(int arg0) { 

     } 

     @Override 
     public void onPageScrolled(int arg0, float arg1, int arg2) { 

     } 

     @Override 
     public void onPageSelected(int position) { 
      actionBar.setSelectedNavigationItem(position); 
     } 
    } 

    @Override 
    public void onBackPressed() { 

     Log.e(TAG_FRAGMENT, "onBackPressed"); 

     FragmentManager fm = getSupportFragmentManager(); 
     if (fm.getBackStackEntryCount() > 0) { 
      Log.i("MainActivity", "popping backstack"); 
      fm.popBackStack(); 
     } else { 
      Log.i("MainActivity", "nothing on backstack, calling super"); 
      super.onBackPressed(); 
     } 

    } 


    @Override 
    public void onContactSelected(ArrayList<Person> contactNumberlist) { 
     // data comes here, no problem. 
     this.blackListPersonList = contactNumberlist; 
     Log.d("onContactSelected", "onContactSelected"); 

     // get error here 
     FragmentTab1 aFragmentTab1 = (FragmentTab1) mAdapter.getItem(0); 

     if (aFragmentTab1 != null) { 
      aFragmentTab1.updateFragment1(blackListPersonList); 
     } 
     FragmentTransaction transaction = getSupportFragmentManager() 
       .beginTransaction(); 

     transaction.add(R.id.fragment_all_contacts_layout, aFragmentTab1); 
     transaction.commit(); 

    } 

    public ArrayList<Person> getBlackListContacts() { 

     return blackListPersonList; 
    } 

    // public Fragment getFragment(ViewPager pager){ 
    // Fragment theFragment = fragments.get(pager.getCurrentItem()); 
    // return theFragment; 
    // } 

} 

FrgmentTab1樣子:

public class FragmentTab1 extends SherlockFragment implements OnClickListener { 

    Button btnTest; 
    ViewPager pager; 
    LinearLayout layoutBlockNumbers; 
    LinearLayout layoutContact, layoutCallLog, layoutSMSLog, layoutManually; 
    public Context mContext; 
    CustomizedDialog dialog; 
    private static final int CONTACT_PICKER_RESULT = 1001; 
    private static final String DEBUG_TAG = "Contact List"; 
    private static final double RESULT_OK = -1; 

    ListView listViewOnlyBlackListNumber; 
    ArrayList<Person> personList; 
    BlackListAdapter aBlackListAdapter; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 

     View rootView = inflater.inflate(R.layout.fragmenttab1, container, 
       false); 

     layoutBlockNumbers = (LinearLayout) rootView 
       .findViewById(R.id.layoutAddBlockNumbers); 
     layoutBlockNumbers.setOnClickListener(this); 

     listViewOnlyBlackListNumber = (ListView) rootView 
       .findViewById(R.id.listViewOnlyBlackListNumber); 

     personList = ((MainActivity) getActivity()).getBlackListContacts(); 

     if (personList != null) { 
      aBlackListAdapter = new BlackListAdapter(getActivity(), personList, 
        m_onSelectedEventCalender); 
      listViewOnlyBlackListNumber.setAdapter(aBlackListAdapter); 

     } else { 
      listViewOnlyBlackListNumber.setEmptyView(container); 
     } 

     return rootView; 

    } 

    public void updateFragment1(ArrayList<Person> personList) { 

     // trying to update when came back here 
     aBlackListAdapter = new BlackListAdapter(getActivity(), personList, 
       m_onSelectedEventCalender); 

     listViewOnlyBlackListNumber.setAdapter(aBlackListAdapter); 
     aBlackListAdapter.notifyDataSetChanged(); 
    } 
} 

得到錯誤在onContactSelected,內MainActivity

 10-30 00:22:29.674: E/AndroidRuntime(26834): FATAL EXCEPTION: main 
    java.lang.IllegalStateException: Can't change container ID of fragment FragmentTab1{42d27380 #0 id=0x7f040032 android:switcher:2130968626:0}: was 2130968626 now 2130968638 
    E/AndroidRuntime(26834):  at android.support.v4.app.BackStackRecord.doAddOp(BackStackRecord.java:407) 
    E/AndroidRuntime(26834): at android.support.v4.app.BackStackRecord.add(BackStackRecord.java:384) 
    E/AndroidRuntime(26834): at com.mobigic.callblocker.MainActivity.onContactSelected(MainActivity.java:240) 

希望有人幫助我。

+0

我認爲你有當你添加新的片段推棧這個片段來嘗試堆棧您的要求,當你回壓檢查堆棧的大小,如果大小> 0從堆棧別的然後彈出片段完成活動.... –

+0

Haresh: 我的問題很簡單。 FragmentTab1有一個列表視圖和一個按鈕。當點擊一個按鈕時,我會在FragmentTab1上方打開新的ShowAllContactFragment。然後從ShowAllContactFragment中選擇一些項目,並在此佈局中單擊按鈕完成&顯示前一個FragmentTab1並根據選定項目更新它的ListView。 我無法從ShowAllContactFragment更新FragmentTab1中的列表。主要活動中已有數據對象。我使用MainActivity進行通信。 fragmetns之間。 –

+0

我完全理解你的問題。您想要打開另一個片段供用戶選擇一些數據,然後當用戶按下OK按鈕時,您想要將該數據傳回舊片段。我不明白的是在哪裏'ViewPager'進入這個地方?爲什麼你使用'ViewPager'有特別的原因嗎?你所描述的不需要任何'ViewPager'。 –

回答

1

你的問題不是很清楚,特別是關於你如何處理這些片段的部分。就像當你展示ShowAllContactFragment片段時,你將它放在哪個佈局中?從您發佈的代碼看來,您似乎是盲目地在包含ViewPager的佈局中直接添加ShowAllContactFragment片段,這是不對的。

與該錯誤相關,您將通過ViewPager的適配器獲得FragmentManager已管理的片段之一的引用,然後重試將其添加到事務中,該操作將失敗。如果您試圖顯示前面顯示的FragmentTab1片段,則在顯示並使用ShowAllContactFragment片段後,您應嘗試通過其popBackStack...()方法之一簡單地刪除FragmentManager的最後記錄動作。

編輯:我看着你的代碼,但你在做什麼仍然不明確。我已經查看了主要活動的佈局,但是您沒有編號爲R.id.fragment_all_contacts_layout的容器,所以我假設您不知何故試圖將新的FragmentTab1插入舊FragmentTab1的佈局中,但實際上並未有任何意義(更不用說你將ShowAllContactFragment添加到我也看不到的編號爲R.id.fragmentTabLayout1的容器)。無論如何,我假設你想到替換FragmentTab1ViewPager。爲此,您需要一個包裝片段來保存兩個嵌套片段,並啓用它們之間的通信。例如包裝片段:

public static class WrapperFragment extends Fragment implements 
     OnContactSelectedListener { 

    private static final String TAG_FIRST = "tag_first"; 
    private static final String TAG_SECOND = "tag_second"; 
    private static final int CONTENT_ID = 1000; 
    private FragmentTab1 mFrag1; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
     FrameLayout content = new FrameLayout(getActivity()); 
     content.setId(CONTENT_ID); 
     if (getChildFragmentManager().findFragmentByTag(TAG_SECOND) == null) { 
      mFrag1 = (FragmentTab1) getChildFragmentManager() 
        .findFragmentByTag(TAG_FIRST); 
      if (mFrag1 == null) { 
       mFrag1 = new FragmentTab1(); 
       getChildFragmentManager().beginTransaction() 
         .add(CONTENT_ID, mFrag1, TAG_FIRST).commit(); 
      } 
     } 
     return content; 
    } 

    @Override 
    public void onContactSelected(List<Person> contactNumberlist) { 
     getChildFragmentManager().popBackStackImmediate(); 
     mFrag1.updateFragment1(contactNumberlist); 
    } 

    public void showPickerfragment() { 
     getChildFragmentManager().beginTransaction() 
       .replace(CONTENT_ID, new ShowAllContactFragment()) 
       .addToBackStack(null).commit(); 
    } 

} 

這將是你在ViewPager的適配器,而不是FragmentTab1片段用片段。注意它實現了OnContactSelectedListener接口。您還需要做出一些改變代碼的其他部分:

@Override 
public void onClick(View v) { 
    if (v == layoutCallLog) { 
    dialog.dismiss(); 
      // make the wrapper fragment to open the ShowAllContactFragment fragment 
      ((WrapperFragment) getParentFragment()).showPickerfragment(); 
      // rest of the code 

ShowAllContactFragment將需要進行修改,以發送選擇事件,其中將實現其接口的包裝片段:

@Override 
public void onClick(View v) { 
    if (v == btnAdd) { 
     Toast.makeText(getActivity(), "" + blockListedPersonList.size(), 
       Toast.LENGTH_SHORT).show(); 
      ((OnContactSelectedListener) getParentFragment()) 
       .onContactSelected(blockListedPersonList); 
    } 
} 

並在主活動處理返回按鈕時ShowAllContactFragment被示出在ViewPager

@Override 
public void onBackPressed() { 
    if (mViewPager.getCurrentItem() == 0) { // I assumed 0 is the position in the adapter where the WrapperFragment will be used 
     Fragment targetPage = getSupportFragmentManager() 
       .findFragmentByTag("android:switcher:" + PAGER_ID + ":" + 0); // PAGER_ID is the id of the ViewPager 
     if (targetPage.getChildFragmentManager().getBackStackEntryCount() > 0) { 
      targetPage.getChildFragmentManager().popBackStack(); 
     } 
     return; 
    } 
    super.onBackPressed(); 
} 

請分鐘d您需要保存嵌套片段的數據。

+0

感謝您的時間。我分享這3個班。請幫我完成剩下的工作。 @Luksprog My FragmentTab1 class:http://pastie.org/8457405 ShowAllContactFragment:http://pastie.org/8457408 MainActivity:http:// pastie。org/8457413 我希望這會清除你,修復bug。考慮我是片段中的新人。 –

+0

@shihab_returns您還可以發佈您在'MainActivity','R.layout.activity_main'中使用的xml佈局嗎? – Luksprog

+0

當然。 R.layout.activity_main: http://pastie.org/8458770#10 –

1

您好我在型動物項目FragmentActivity和ViewPager使用,有兩種解決方案

1:你可以使用onHiddenChanged(布爾隱藏)梅索德您FragmentTab1。

@Override public void onHiddenChanged(boolean hidden) { // TODO Auto-generated method stub if(!hidden) { //check if personList size is changed and then call updateFragment1() methode } super.onHiddenChanged(hidden); }

2:如果你喜歡使用靜態梅索德可以使updateFragment1()梅索德靜態的,所以當用戶按添加通話updateFragment1()。

希望它能幫助