Как перестать воспроизводить видео на просмотр пейджера в Android?
Я использую View Pager, показывающий изображение и видео, я могу правильно показать изображение и видео, но у меня есть проблема, когда я пролистываю видео, затем воспроизводится видео, но я провожу пальцем по следующему или предыдущему, после чего видео все еще воспроизводится только рядом или предыдущий экран, но когда я перемещаю два слайда на следующий или предыдущий, видео останавливается, но почему бы не на следующем или предыдущем слайде.
Я ищу это больше, но я не получил никакого решения, любая помощь будет заметна. Заранее спасибо.
Вот мой код адаптера:
public class SelectedMediaViewPagerAdapter extends PagerAdapter {
private final Context context;
private final LayoutInflater layoutInflater;
public ArrayList<MediaItem> mediaItems;
PlayerView playerView;
SimpleExoPlayer player;
public String path = "";
public SelectedMediaViewPagerAdapter(Context context, ArrayList<MediaItem> mediaItems) {
this.mediaItems = mediaItems;
this.context = context;
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
DefaultTrackSelector trackSelector = new DefaultTrackSelector();
player = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
}
@Override
public int getCount() {
return mediaItems.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return (view == object);
}
@Override
public Object instantiateItem(final ViewGroup container, int position) {
RelativeLayout layout = (RelativeLayout) layoutInflater.inflate(R.layout.item_selected_media_view_pager, container, false);
RelativeLayout vidView= layout.findViewById(R.id.vidView);
ImageView imgView = layout.findViewById(R.id.imgView);
if (mediaItems.get(position).isVideo()) {
imgView.setVisibility(View.GONE);
vidView.setVisibility(View.VISIBLE);
String video_url;
playerView = layout.findViewById(R.id.player_view);
final ProgressBar progressBar = layout.findViewById(R.id.progresbar_video_play);
progressBar.setVisibility(View.VISIBLE);
playerView.setPlayer(player);
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context,
Util.getUserAgent(context, context.getResources().getString(R.string.app_name)));
// This is the MediaSource representing the media to be played.
MediaSource videoSource = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(mediaItems.get(position).getPath()));
// Prepare the player with the source.
player.prepare(videoSource);
player.setPlayWhenReady(false);
player.addListener(new Player.DefaultEventListener() {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playWhenReady) {
progressBar.setVisibility(View.GONE);
}
super.onPlayerStateChanged(playWhenReady, playbackState);
}
});
}else {
// path = drawable.get(drawable.size() - position - 1);
imgView.setVisibility(View.VISIBLE);
vidView.setVisibility(View.GONE);
Glide.with(context).load("file://" + mediaItems.get(position).getPath()).into(imgView);
}
container.addView(layout);
return layout;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((RelativeLayout) object);
}
}
2 ответа
Это происходит потому, что ViewPager сохраняет ряд фрагментов "живыми" (в состоянии возобновления) до и после текущего элемента. По умолчанию - по 1 с каждой стороны. Свойство, определяющее это,ViewPager.offScreenPageLimit
. Это сделано для облегчения плавного перехода к следующему / предыдущему виду при смахивании.
Вы можете использовать что-то вроде ниже, чтобы определить, когда страница изменяется. Затем вам нужно будет уведомить viewModel или службу, к которой каждый из ваших выгружаемых фрагментов имеет доступ, чтобы они могли определить, следует ли им приостановить или продолжить воспроизведение своего мультимедиа:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener {
@Override
public void onPageSelected(int position) {
// find your player and pause it if it's not in the current view
// Ideally you notify a viewModel that is shared between your paged
// fragments here and let each one determine if it needs to pause
// its player.
}
@Override
public void onPageScrollStateChanged(int state) { // do nothing }
@Override
public void onPageScrolled(int position, float offset, int offsetInPixels) { // do nothing }
})
Идея состоит в том, чтобы сохранить ссылку на текущую выбранную страницу в viewpager и остановить предыдущий проигрыватель viewHolder перед сохранением новой позиции. Вот как: В вашем фрагменте:
private var currentPage = 0
private val onPageScrolledListener = object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
getViewHolder(currentPage)?.stopVideo()
currentPage = position
}
}
перед сохранением новой позиции я нахожу предыдущего холдера и коллирую стоп на нем.
Вот метод getViewHolder()
fun getViewHolder(position: Int): VideoViewHolder =
(binding.pager.getChildAt(0) as? RecyclerView)?.let {
it.findViewHolderForAdapterPosition(position)?.let { mediaViewHolder ->
(mediaViewHolder as? MediaViewHolder.VideoViewHolder)
}
}
и внутри вашего ViewHolder сделайте этот метод
fun stopVideo() {
player?.stop()
}
не забудьте зарегистрировать слушателя в onViewCreated()
pager.registerOnPageChangeCallback(onPageScrolledListener)
и отмените регистрацию в onDestroy()
binding.pager.unregisterOnPageChangeCallback(onPageScrolledListener)