2017-10-11 20 views
8

J'utilise un ViewPager avec une instance de fragment unique dans laquelle je montre Media des fichiers comme Images, Vidéos, Audio.Arrêt de Exoplayer onSwipe de ViewPager

J'ai mis en œuvre ExoPlayer pour la gestion Video & Audio fichiers. Et Glide pour les images.

De this pour éviter les fuites de mémoire je libérer l'objet ExoPlayer comme celui-ci dans ItemViewerFragment.java:

private void releasePlayer() { 
     if (player != null) { 
      player.release(); 
      player = null; 
      trackSelector = null; 
      simpleExoPlayerView.setPlayer(null); 
     } 
    } 

    @Override 
    public void onStart() { 
     super.onStart(); 
     if (player == null && currentGalleryModel != null) { 
      initializePlayer(); 
     } 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 
     if (player == null && currentGalleryModel != null) { 
      initializePlayer(); 
     } 
    } 

    @Override 
    public void onPause() { 
     super.onPause(); 
     releasePlayer(); 
    } 

    @Override 
    public void onStop() { 
     super.onStop(); 
     releasePlayer(); 
    } 

Et dans onViewCreated() Je suis Initialisation vue comme ceci:

@Override 
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 
     super.onViewCreated(view, savedInstanceState); 

     if (currentGalleryModel.isVideo() || currentGalleryModel.isAudio()) { 

      simpleExoPlayerView.setVisibility(View.VISIBLE); 
      imageView.setVisibility(View.GONE); 

      initializePlayer(); 
     } else if (currentGalleryModel.isImage() || currentGalleryModel.isGif()) { 
      simpleExoPlayerView.setVisibility(View.GONE); 
      imageView.setVisibility(View.VISIBLE); 


      Glide.with(this) 
        .load(currentGalleryModel.getFilePath()) 
        .placeholder(android.R.color.black) 
        .fitCenter() 
        .diskCacheStrategy(DiskCacheStrategy.NONE) 
        .into(imageView); 

     } 
    } 

J'utilise FragmentStatePagerAdapeter . Ceci est la méthode getItem:

@Override 
public Fragment getItem(int position) { 
    return ItemViewerFragment.newInstance(mItems.get(position)); 
} 

Je ne suis pas en mesure de détecter la du fragment sur le premier coup de Viewpager. Au deuxième balayage, les fichiers video/audio sont arrêtés.

En activité j'ai essayé d'ajouter .addOnPageChangeListener:

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

    try { 
     ((ItemViewerFragment)mAdapter.getItem(mPreviousPos)).imHiddenNow(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     mPreviousPos = position; 
    } 

Et ItemViewerFragment.java:

public void imHiddenNow(){ 
     releasePlayer(); 
    } 

encore video/audio continue à jouer. Il s'agit d'un Video Link au Screencast.

Demo project GitHub link. Veuillez noter que la solution affichée ci-dessous ne fonctionne pas

+0

Comment obtenez-vous la position précédente dans le onScrollListener? –

+0

Plus je vois la méthode getItem renvoie une nouvelle instance à chaque fois qui peut être la cause. –

+0

Pendant l'initialisation, je stocke la position actuelle du 'GalleryModel' qui est en train de s'afficher. Supposons que j'ai 30 articles dans ma liste et que j'en affiche 5. Ensuite 'onScroll' la position précédente serait 5ème et le courant serait soit 4ème soit 6ème selon le côté où il a été défilé. –

Répondre

2

Voici le code pour l'adaptateur de téléavertisseur:

class ViewPagerAdapter extends FragmentPagerAdapter { 
    private final List<Fragment> mFragmentList = new ArrayList<>(); 
    private final List<String> mFragmentTitleList = new ArrayList<>(); 

    public ViewPagerAdapter(FragmentManager manager) { 
     super(manager); 
    } 

    @Override 
    public Fragment getItem(int position) { 
     return mFragmentList.get(position); 
    } 

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

    public void addFragment(Fragment fragment, String title) { 
     mFragmentList.add(fragment); 
     mFragmentTitleList.add(title); 
    } 

    @Override 
    public CharSequence getPageTitle(int position) { 
     return mFragmentTitleList.get(position); 
    } 
} 

Voici le Listener de défilement:

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { 
     @Override 
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 
      //Stop media here. 
     } 

     @Override 
     public void onPageSelected(int position) { 
      //Save your previous position here. 
     } 

     @Override 
     public void onPageScrollStateChanged(int state) { 

     } 
    }); 

Pour les médias, vous pouvez utiliser une boucle et ajouter tous les fragments à la liste à la fois et puis utiliser ceci pour l'efficacité:

viewPager.setOffscreenPageLimit(3); 

Cela fera en sorte que 3 instances de vous r fragment sont disponibles ce qui est suffisant.

Pour utiliser seul fragment je vous suggère de le faire comme ceci:

public MyFragment() { 

} 

//This is to send a file to the fragment if you need it. 
public static MyFragment newInstance(File file) { 
    MyFragment fragment = new MyFragment(); 
    Bundle bundle = new Bundle(); 
    bundle.putSerializable("file", file); 
    fragment.setArguments(bundle); 
    return fragment; 
} 

Ensuite, dans le onCreate de Fragment vous pouvez récupérer votre fichier comme ceci:

File file; 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    file = getArguments().getSerializable("file"); 

} 

Maintenant, ajoutez vos fragments pour pager comme ceci:

for (int i = 0; i < totalFiles; i++) { 
      viewPagerAdapter.addFragment(MyFragment.newInstance(fileList.get(i)); 
     } 

Espérons que cela aide.

+0

D'accord je le ferais un essai. Merci! –

+0

Donc supposons que j'ai 1000 fichiers multimédia. Cela créerait 1000 fragments? 'mFragmentList' serait-il si gros? –

+0

Comment gérez-vous la liste en ce moment? –

0

Cela fait plus d'un an que j'ai utilisé Exoplayer & J'ai un peu abordé un problème similaire. S'il vous plaît noter que les API ont changé un peu alors prenez le code suivant juste pour avoir une idée sur la façon de mettre en œuvre une solution potentielle. S'il vous plaît laissez-moi savoir si cela ne fonctionne pas, je vais regarder dans les API plus loin et revenir à vous.

Venir à la solution:

private int mPlayerCurrentPosition; 

private int getCurrentPlayerPosition() { 
    return mExoPlayer.getCurrentPosition(); 
} 

// call this from onPause 
private void releaseExoplayer() { 
    mPlayerCurrentPosition = getPlayerCurrentPosition(); 
    mExoPlayer.setPlayWhenReady(false); 
    mExoPlayer.release(); // this will make the player object eligible for GC 
} 

private void resumePlaybackFromPreviousPosition(int prevPosition) { 
    mExoPlayer.seekTo(mPlayerCurrentPosition); 
} 
+0

Merci! Le comportement est le même. Je veux mettre en pause le lecteur lors du premier balayage du 'viewPager' qui se passe dans le second balayage. –

+0

Avez-vous essayé d'appeler le releaseExoplayer() mentionné dans ma réponse de callbacks onPageScrolled et onPageScrollStateChanged pour viewPager? –

+0

Oui, je l'ai fait. Même si le fragment actuel 'onSwipe' arrête le lecteur. 'onSwipeBack' au même fragment ne reprend pas le lecteur. J'appelle 'resumePlaybackFromPreviousPosition' dans' onResume' du fragment –