2017-09-13 40 views
0

我只有一個活動的應用程序與4個片段切換底部選項卡菜單。所以它一次只能在屏幕上顯示4個片段之一。看起來很簡單,但我問自己爲什麼通過切換片段,每次都必須重新創建新的Fragment對象?這是從Android文檔:如何避免每次通過切換片段來創建Fragment對象?

FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
// Replace the contents of the container with the new fragment 
ft.replace(R.id.your_placeholder, new FooFragment()); 
// or ft.add(R.id.your_placeholder, new FooFragment()); 
// Complete the changes added above 
ft.commit(); 

我可以嘗試存儲由我自己片段的引用,每次挑現成的對象,但我發現這樣的片段使用風格的建築,所以它可能是錯的?

+0

看到我更新的答案 –

回答

1

您可以在ViewPager中設置片段,並切換ViewPager頁面。

試試這個:

viewPager = (ViewPager) findViewById(R.id.viewpager); 
    FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager()); 
    adapter.addFragment(new ExplorerFragment(), "Fragment1", false); 
    adapter.addFragment(new NotificationFragment(), "Fragment2", false); 
    adapter.addFragment(new HistoryFragment(), "Fragment3", false); 
    adapter.addFragment(new AccountFragment(), "Fragment4", false); 
    viewPager.setAdapter(adapter); 

    bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { 
     @Override 
     public boolean onNavigationItemSelected(@NonNull MenuItem item) { 
      int id = item.getItemId(); 
      switch (id){ 
       case R.id.action_explorer: 
        viewPager.setCurrentItem(0); 
        final Menu bottomMenu = bottomNavigationView.getMenu(); 
        final MenuItem targetMenuItem = bottomMenu.getItem(0); 
        targetMenuItem.setChecked(true); 
        break; 
       case R.id.action_notification: 
        viewPager.setCurrentItem(1); 
        final Menu bottomMenu1 = bottomNavigationView.getMenu(); 
        final MenuItem targetMenuItem1 = bottomMenu1.getItem(1); 
        targetMenuItem1.setChecked(true); 
        break; 
       case R.id.action_history: 
        viewPager.setCurrentItem(2); 
        final Menu bottomMenu2 = bottomNavigationView.getMenu(); 
        final MenuItem targetMenuItem2 = bottomMenu2.getItem(2); 
        targetMenuItem2.setChecked(true); 
        break; 
       case R.id.action_account: 
        viewPager.setCurrentItem(3); 
        final Menu bottomMenu4 = bottomNavigationView.getMenu(); 
        final MenuItem targetMenuItem4 = bottomMenu4.getItem(3); 
        targetMenuItem4.setChecked(true); 
        break; 
       case R.id.action_search: 
        break; 
      } 
      return true; 
     } 
    }); 

EDIT1:如何創建NonSwipeableViewPager:

public class NonSwipeableViewPager extends ViewPager { 

    public NonSwipeableViewPager(Context context) { 
     super(context); 
     setMyScroller(); 
    } 

    public NonSwipeableViewPager(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     setMyScroller(); 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent event) { 
     // Never allow swiping to switch between pages 
     return false; 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     // Never allow swiping to switch between pages 
     return false; 
    } 

    //down one is added for smooth scrolling 

    private void setMyScroller() { 
     try { 
      Class<?> viewpager = ViewPager.class; 
      Field scroller = viewpager.getDeclaredField("mScroller"); 
      scroller.setAccessible(true); 
      scroller.set(this, new MyScroller(getContext())); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public class MyScroller extends Scroller { 
     public MyScroller(Context context) { 
      super(context, new DecelerateInterpolator()); 
     } 

     @Override 
     public void startScroll(int startX, int startY, int dx, int dy, int duration) { 
      super.startScroll(startX, startY, dx, dy, 350 /*1 secs*/); 
     } 
    } 
} 

,然後在你的XML:

<com.project.Components.NonSwipeableViewPager 
    android:id="@+id/viewpager" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_above="@id/bottom_navigation"/> 
+0

我知道ViewPager只有通過實現滑動瀏覽的網頁。你知道是否有可能禁用任何類型的動畫和輕掃手勢,只是使其立即替換碎片? –

+0

另外我見過ViewPager一次只保留有限數量的片段。所以如果它只有3的緩存,那麼我的情況下,位於邊緣的碎片將不斷重新創建。 –

+1

是的。您只需創建一個自定義的ViewPager組件。我將使用代碼@ArnieSchwarzvogel編輯我的文章 –

0

創建的所有片段一次,並用它或者使你的片段對象成爲一個單例來實現它。

辛格爾頓例子:

class MyFragment extends Fragment{ 
    private static MyFragment instance; 

    public static MyFragment getInstance(){ 
    if(instance == null) 
     instance = new MyFragment(); 

    return instance; 
    } 
} 

使用MyFragment.getInstance();

現在,它不會產生新的對象,每次創建對象片段。

0

您可以將TAG添加到您的片段,同時更換,然後再使用FragmentManagerfindFragmentByTag檢索:

FragmentManager fm = getSupportFragmentManager(); 
FragmentTransaction ft = fm.beginTransaction(); 
// Replace the contents of the container with the new fragment 
Fragment fooFrag = fm.findFragmentByTag("foo-frag-tag"); 

if(fooFrag == null) { 
    fooFrag = new FooFrag(); 
} 

ft.replace(R.id.your_placeholder, fooFrag, "foo-frag-tag"); 
// or ft.add(R.id.your_placeholder, new FooFragment()); 
// Complete the changes added above 
ft.commit(); 
+0

好主意。 –

+0

不幸的是,這不起作用--FragmentManager不會簡單地緩存片段,它僅與putFragment()結合使用,這是一個完全不同的故事 –

相關問題