我有ViewPager
FragmentStatePagerAdapter
,允许用户使用VideoView
滚动浏览视频。它工作正常,但当您按下后退按钮时,viewpager向左滚动并在关闭viewpager活动之前简要显示前一个ViewView
。
我理解FragmentStatePagerAdapter
将缓存片段/视图以更好地进行内存管理,但在关闭之前显示宝贵的视图似乎很奇怪。这是正常的,还是有任何方法可以确保视图在当前寻呼机不是焦点时完全隐藏?
这是我的适配器的代码。基本上我会返回两个片段中的一个,用它创建一个包含该照片或视频的视图。
inner class MyAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
override fun getCount(): Int = photoInfo.size
override fun getItemPosition(`object`: Any?): Int = super.getItemPosition(`object`)
override fun getItem(position: Int): Fragment {
when (photoInfo[position].type) {
PHOTO -> {
return PhotoFragment.newInstance(photoInfo[position])
}
VIDEO-> {
return VideoFragment.newInstance(photoInfo[position])
}
else -> {
return PhotoFragment.newInstance(photoInfo[position])
}
}
}
}
视频片段:
class VideoFragment : Fragment(), AnkoLogger {
internal var photo: String? = null
internal var totalSize: Int? = null
internal var thumbnail: String? = null
var player: SimpleExoPlayer? = null
var simpleExoPlayerView: SimpleExoPlayerView? = null
var error = false
var shouldLoop = true
var autoPlay = true
var proxy: HttpProxyCacheServer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
photo = arguments.getString("photo")
thumbnail = arguments.getString("thumbnail")
totalSize = arguments.getInt("size")
shouldLoop = defaultSharedPreferences.getBoolean("loop_webm_preference", true)
autoPlay = defaultSharedPreferences.getBoolean("autplay_webm_preference", true)
proxy = getProxy(activity)
}
override fun onDestroyView() {
player?.release()
super.onDestroyView()
}
override fun onPause() {
super.onPause()
}
fun checkAndSetVolume() {
val isMuted = defaultSharedPreferences.getBoolean("mute_video", false)
when (isMuted) {
true -> {
simpleExoPlayerView?.findViewById<ImageButton>(R.id.exo_mute)?.imageResource = R.drawable.volume_on
player?.volume = 0f
}
false -> {
simpleExoPlayerView?.findViewById<ImageButton>(R.id.exo_mute)?.imageResource = R.drawable.volume_off
player?.volume = 1f
}
}
}
override fun getUserVisibleHint(): Boolean {
return super.getUserVisibleHint()
}
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
if (!isVisibleToUser) {
player?.playWhenReady = false
player?.playbackState
player?.seekTo(0)
} else if (isVisible && isVisibleToUser && (proxy?.isCached(photo) == true) && !error) {
checkAndStartAutoplay()
}
}
fun checkAndStartAutoplay() {
checkAndSetVolume()
player?.playWhenReady = autoPlay
player?.playbackState
}
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
simpleExoPlayerView = SimpleExoPlayerView(context)
val mainHandler = Handler()
val bandwidthMeter = DefaultBandwidthMeter()
val videoTrackSelectionFactory = AdaptiveTrackSelection.Factory(bandwidthMeter)
val trackSelector = DefaultTrackSelector(videoTrackSelectionFactory)
player = ExoPlayerFactory.newSimpleInstance(context, trackSelector)
val fl = FrameLayout(context)
simpleExoPlayerView?.player = player
simpleExoPlayerView?.setShutterBackgroundColor(Color.TRANSPARENT)
player?.repeatMode = if (shouldLoop) 1 else 0
player?.addListener(object : Player.DefaultEventListener() {
override fun onPlayerError(error: ExoPlaybackException?) {
val tv = TextView(context)
tv.text = getString(android.R.string.VideoView_error_text_unknown)
tv.textColor = Color.WHITE
tv.textAlignment = TextView.TEXT_ALIGNMENT_CENTER
fl.addView(tv, FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER))
this@VideoFragment.error = true
}
override fun onLoadingChanged(isLoading: Boolean) {
super.onLoadingChanged(isLoading)
if (!isLoading) {
if (this@VideoFragment.isVisible && this@VideoFragment.userVisibleHint) {
checkAndStartAutoplay()
}
}
}
})
val proxyUrl = proxy?.getProxyUrl(photo)
val dataSourceFactory = DefaultDataSourceFactory(context, Util.getUserAgent(context, "Omnichan"), bandwidthMeter)
val videoSource = ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(Uri.parse(proxyUrl))
player?.prepare(videoSource)
fl.addView(simpleExoPlayerView, FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER))
simpleExoPlayerView?.findViewById<ImageButton>(R.id.exo_mute)?.setOnClickListener {
val isMuted = defaultSharedPreferences.getBoolean("mute_video", false)
defaultSharedPreferences.edit().putBoolean("mute_video", !isMuted).apply()
checkAndSetVolume()
}
return fl
}
companion object {
internal fun newInstance(photoInfo: PhotoInfo): VideoFragment {
val f = VideoFragment()
val args = Bundle()
args.putString("photo", photoInfo.photoUrl)
args.putString("thumbnail", photoInfo.thumbnailUrl)
f.arguments = args
return f
}
private var sharedProxy: HttpProxyCacheServer? = null
private fun newProxy(context: Context): HttpProxyCacheServer {
return HttpProxyCacheServer.Builder(context)
.maxCacheSize((1024 * 1024 * 256).toLong()) // 256 Mb for cache
.build()
}
fun getProxy(context: Context): HttpProxyCacheServer {
return sharedProxy ?: newProxy(context)
}
}
}