2017-09-13 3 views
0

J'ai une seule activité dans l'application avec 4 fragments qui sont commutés en bas du menu onglet. Donc, c'est toujours l'un des 4 fragments sur l'écran à la fois. Cela semble simple, mais je me demande pourquoi en changeant de fragments, un nouvel objet Fragment doit être recréé à chaque fois? Ceci est de la documentation Android:Comment éviter de créer un objet Fragment à chaque fois en changeant de 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(); 

Je pourrais essayer stocker des références à des fragments de mon propre et ramasser l'objet prêt à chaque fois, mais je trouve des exemples de ce style d'utilisation du fragment, de sorte qu'il pourrait être quelque chose de mal avec elle ?

+0

voir ma réponse à jour –

Répondre

1

Vous pouvez définir les fragments dans un ViewPager et basculer simplement la page ViewPager.

Essayez ceci:

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: Comment créer un 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*/); 
     } 
    } 
} 

puis dans votre 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

Je sais ViewPager que par la mise en œuvre des pages à faire glisser. Savez-vous s'il est possible de désactiver n'importe quel type d'animation et de glisser des gestes et de le faire remplacer des fragments instantanément? –

+0

J'ai aussi vu que ViewPager ne conserve qu'un nombre limité de fragments à la fois. Donc, si elle n'a qu'un cache de 3, alors les fragments situés dans mon cas seront toujours recréés. –

+1

Oui. Vous avez juste besoin de créer un composant ViewPager personnalisé. Je vais modifier mon post avec le code @ArnieSchwarzvogel –

0

Créer tout le fragment une fois et l'utiliser ou faites de votre objet fragment un singleton pour le faire.

Singleton Exemple:

class MyFragment extends Fragment{ 
    private static MyFragment instance; 

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

    return instance; 
    } 
} 

créer fragment d'objet en utilisant par MyFragment.getInstance();

Maintenant, il ne va pas créer un nouvel objet à chaque fois.

0

Vous pouvez ajouter un TAG à votre fragment tout en remplaçant et le récupérer plus tard en utilisant FragmentManager « s findFragmentByTag:

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

Bonne idée aussi. –

+0

Malheureusement, cela ne fonctionne pas - FragmentManager ne fait pas que mettre en cache des fragments, il est utilisé uniquement en combinaison avec putFragment(), ce qui est une histoire totalement différente –