Search code examples
androidandroid-fragmentsandroid-lifecycle

VideoView inside Fragment, How do i stop video from play when i swipe away?


I have a viewPager where i display both images and Video. However, when a user plays a video and immediately swipes to the next fragment, the previous Video continues to PLAY!

Here's how i played the video

videoView!!.setVideoURI(uri)
videoView!!.setMediaController(MediaController(context))
videoView!!.requestFocus()

play.setOnClickListener(View.OnClickListener {
    if (!videoView!!.isPlaying()) {
    videoView!!.start()
    videoView!!.setVisibility(View.VISIBLE)
}

I have tried inserting

if (videoView!!.isPlaying()) {
     videoView!!.setMediaController(null)
     videoView?.stopPlayback()
}

in onStop, onPause and onDetach of the viewPager's fragment but it is not working.

Your help would be invaluable!


Solution

  • A Simple Interface:

    interface Playable {
    
        fun play()
    
        fun stop()
    }
    

    fragments containing VideoView must implement this interface

    class VideoFragment : Fragment(), Playable {
    ...
        override fun play() {
            //play logic
        }
    
        override fun stop() {
            //stop logic
        }
    ...
    }
    

    PagerAdapter:

    class PagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm){
    
        private val instantiatedItems = SparseArrayCompat<WeakReference<Any>>()
        private var selectedPosition: Int by Delegates.observable(-1) { _, oldPosition, newPosition ->
            fun playableAt(position: Int) = instantiatedItems.get(position)?.get() as? Playable
            playableAt(oldPosition)?.stop()
            playableAt(newPosition)?.play()
        }
    ...
        override fun instantiateItem(container: ViewGroup, position: Int): Any {
            return super.instantiateItem(container, position).also {
                instantiatedItems.put(position, WeakReference(it))
            }
        }
    
        override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
            instantiatedItems.remove(position)
            super.destroyItem(container, position, `object`)
        }
    
        fun onPageSelected(position: Int) {
            selectedPosition = position
        }
    }
    

    finally:

    ...
    pager.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener() {
                override fun onPageSelected(position: Int) {
                    adapter.onPageSelected(position)//this method is declared in PagerAdapter
                }
            }.also {
                pager.post { it.onPageSelected(pager.currentItem) }
            })
    ...