2

I followed the tutorial below (scroll down to the "Fullscreen Image Slideshow" section) to implement a fullscreen slideshow, except instead of using images in the slideshow, I'm using videos:

http://www.androidhive.info/2016/04/android-glide-image-library-building-image-gallery-app/

Here is my implementation of the DialogFragment and the PagerAdapter:

public class SlideshowDialogFragment extends DialogFragment {

    private ArrayList<Video> videos;

    private ViewPager viewPager;

    private MyViewPagerAdapter myViewPagerAdapter;

    private int selectedPosition = 0;

    public static SlideshowDialogFragment newInstance() {
        SlideshowDialogFragment fragment = new SlideshowDialogFragment();

        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_slideshow, container, false);

        videos = (ArrayList<Video>) getArguments().getSerializable("videos");
        selectedPosition = getArguments().getInt("position");

        viewPager = (ViewPager) v.findViewById(R.id.viewPager);

        myViewPagerAdapter = new MyViewPagerAdapter();
        viewPager.setAdapter(myViewPagerAdapter);

        setCurrentItem(selectedPosition);

        return v;
    }

    private void setCurrentItem(int position) {
        viewPager.setCurrentItem(position, false);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Black_NoTitleBar_Fullscreen);
    }

    public class MyViewPagerAdapter extends PagerAdapter {

        private LayoutInflater layoutInflater;

        public MyViewPagerAdapter() {

        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            layoutInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            View view = layoutInflater.inflate(R.layout.video_layout, container, false);

            Video video = videos.get(position);

            TextureVideoView videoView = (TextureVideoView) view.findViewById(R.id.videoView);

            Uri videoUri = Uri.parse(video.getUrl());

            videoView.setVideoURI(videoUri);
            videoView.setMediaController(null);
            videoView.requestFocus();

            container.addView(view);

            return view;
        }

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

        @Override
        public boolean isViewFromObject(View view, Object obj) {
            return view == ((View) obj);
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }
    }
}

The problem is that, right now, the videos automatically play as soon as they're loaded. And, also, because ViewPager loads the next and previous slide (which I want it to do), the slideshow also automatically plays the next and previous videos as well (which I don't want it to do).

So my question is, how can modify my code so that it only plays a video when the current slide is active, and then pause/stop the video when the slide becomes inactive?

FYI: The methods to start and stop the video are videoView.start() and videoView.stop().

asd91zxcv
  • 23
  • 4

1 Answers1

0

You can use the same approach from my other answer here.

Keep an array of video view references in the ViewPager adapter, so that you can start the video currently being shown, and pause any video views that are instantiated but not currently shown.

Changes to the adapter:

public class MyViewPagerAdapter extends PagerAdapter {

    private LayoutInflater layoutInflater;

    //Added:
    public TextureVideoView[] videoViews = new TextureVideoView[videos.size()];

    public MyViewPagerAdapter() {

    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        layoutInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View view = layoutInflater.inflate(R.layout.video_layout, container, false);

        Video video = videos.get(position);

        TextureVideoView videoView = (TextureVideoView) view.findViewById(R.id.videoView);

        Uri videoUri = Uri.parse(video.getUrl());

        videoView.setVideoURI(videoUri);
        videoView.setMediaController(null);
        videoView.requestFocus();

        container.addView(view);

        //Added:
        videoViews[position] = videoView;

        return view;
    }

    //.............
}

Then, outside of the adapter, use a ViewPager.OnPageChangeListener to start the current video, and pause the ones on either side:

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

  @Override
  public void onPageSelected(int position) {

    for (int i = 0; i < videos.size(); i++) {
      TextureVideoView videoView = myViewPagerAdapter.videoViews[i];
      if (videoView == null) continue;
      if (i == position) {
        videoView.start();
      } else {
        videoView.stop();
      }
    }
  }

  @Override
  public void onPageScrollStateChanged(int state) {  }
});
Community
  • 1
  • 1
Daniel Nugent
  • 43,104
  • 15
  • 109
  • 137
  • Works great, thanks! Should I be aware of any performance issues? – asd91zxcv Apr 05 '17 at 00:39
  • Glad it works! It should be fine performance-wise. That loop inside `onPageSelected` should only need to start the current video, and stop the two videos on either side. The only way it would be a problem is if you had a large number of pages, and also modified the offscreen page limit to be larger than 2. As long as you leave the default offscreen page limit, it should be fine. – Daniel Nugent Apr 05 '17 at 00:42