Android kotlin ExoPlayer+SurfaceView使用ConstraintLayout添加标题简介等效果UI 横竖屏切换 布局隐藏与显示问题详细代码与实现
下面是一个使用ConstraintLayout和ExoPlayer库实现标题和简介等效果UI,并处理横竖屏切换以及布局隐藏和显示的示例代码:
XML布局文件:activity_main.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/titleTextView"
app:layout_constraintDimensionRatio="16:9"
/>
<TextView
android:id="@+id/titleTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Title"
android:textSize="24sp"
app:layout_constraintBottom_toTopOf="@+id/descriptionTextView"
app:layout_constraintTop_toBottomOf="@+id/surfaceView" />
<TextView
android:id="@+id/descriptionTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Description"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/controllerView"
app:layout_constraintTop_toBottomOf="@+id/titleTextView" />
<LinearLayout
android:id="@+id/controllerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#80000000"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent">
<ImageButton
android:id="@+id/playButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:src="@android:drawable/ic_media_play" />
<ImageButton
android:id="@+id/pauseButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:src="@android:drawable/ic_media_pause" />
<SeekBar
android:id="@+id/seekBar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:max="100"
android:paddingLeft="16dp"
android:paddingRight="16dp" />
<TextView
android:id="@+id/positionTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:textColor="#FFFFFF" />
<TextView
android:id="@+id/durationTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:textColor="#FFFFFF" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
import android.content.res.Configuration
import android.net.Uri
import android.os.Bundle
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.view.View
import android.widget.ImageButton
import android.widget.SeekBar
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import com.google.android.exoplayer2.*
import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.source.hls.HlsMediaSource
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout
import com.google.android.exoplayer2.ui.PlayerView
import com.google.android.exoplayer2.upstream.DataSource
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import com.google.android.exoplayer2.util.Util
class MainActivity : AppCompatActivity(), Player.EventListener, SurfaceHolder.Callback {
private lateinit var surfaceView: SurfaceView
private lateinit var playerView: PlayerView
private lateinit var titleTextView: TextView
private lateinit var descriptionTextView: TextView
private lateinit var controllerView: ConstraintLayout
private lateinit var playButton: ImageButton
private lateinit var pauseButton: ImageButton
private lateinit var seekBar: SeekBar
private lateinit var positionTextView: TextView
private lateinit var durationTextView: TextView
private lateinit var player: SimpleExoPlayer
private lateinit var dataSourceFactory: DataSource.Factory
private lateinit var mediaSource: MediaSource
private var playbackPosition: Long = 0
private var currentWindow: Int = 0
private var playWhenReady = true
private var isFullscreen = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
surfaceView = findViewById(R.id.surfaceView)
playerView = findViewById(R.id.playerView)
titleTextView = findViewById(R.id.titleTextView)
descriptionTextView = findViewById(R.id.descriptionTextView)
controllerView = findViewById(R.id.controllerView)
playButton = findViewById(R.id.playButton)
pauseButton = findViewById(R.id.pauseButton)
seekBar = findViewById(R.id.seekBar)
positionTextView = findViewById(R.id.positionTextView)
durationTextView = findViewById(R.id.durationTextView)
// 设置SurfaceView的回调
surfaceView.holder.addCallback(this)
// 创建ExoPlayer实例
player = SimpleExoPlayer.Builder(this).build()
player.addListener(this)
// 创建数据源工厂
dataSourceFactory = DefaultDataSourceFactory(this, Util.getUserAgent(this, "ExoPlayerDemo"))
// 创建媒体源
val uri = Uri.parse("http://example.com/video.mp4")
mediaSource = ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(uri)
// 设置播放器
player.prepare(mediaSource)
player.playWhenReady = playWhenReady
// 设置播放器视图
playerView.player = player
// 设置全屏按钮点击事件
playerView.findViewById<ImageButton>(R.id.exo_fullscreen_button).setOnClickListener {
toggleFullscreen()
}
}
override fun onStart() {
super.onStart()
if (Util.SDK_INT >= 24) {
initializePlayer()
}
}
override fun onResume() {
super.onResume()
if (Util.SDK_INT < 24 || player == null) {
initializePlayer()
}
}
override fun onPause() {
super.onPause()
if (Util.SDK_INT < 24) {
releasePlayer()
}
}
override fun onStop() {
super.onStop()
if (Util.SDK_INT >= 24) {
releasePlayer()
}
}
private fun initializePlayer() {
playerView.onResume()
if (player == null) {
player = SimpleExoPlayer.Builder(this).build()
player.addListener(this)
playerView.player = player
player.playWhenReady = playWhenReady
player.seekTo(currentWindow, playbackPosition)
}
}
private fun releasePlayer() {
if (player != null) {
playbackPosition = player.currentPosition
currentWindow = player.currentWindowIndex
playWhenReady = player.playWhenReady
player.removeListener(this)
player.release()
player = null
}
}
private fun toggleFullscreen() {
if (isFullscreen) {
supportActionBar?.show()
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
val params = surfaceView.layoutParams as ConstraintLayout.LayoutParams
params.dimensionRatio = "16:9"
params.width = ConstraintLayout.LayoutParams.MATCH_PARENT
params.height = 0
surfaceView.layoutParams = params
isFullscreen = false
} else {
supportActionBar?.hide()
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
val params = surfaceView.layoutParams as ConstraintLayout.LayoutParams
params.dimensionRatio = "16:9"
params.width = ConstraintLayout.LayoutParams.MATCH_PARENT
params.height = ConstraintLayout.LayoutParams.MATCH_PARENT
surfaceView.layoutParams = params
isFullscreen = true
}
}
override fun onSurfaceCreated(holder: SurfaceHolder) {
player.setVideoSurface(holder.surface)
}
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {}
override fun surfaceDestroyed(holder: SurfaceHolder) {}
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
if (playbackState == Player.STATE_READY && playWhenReady) {
// 播放器就绪并且正在播放
} else if (playbackState == Player.STATE_READY) {
// 播放器就绪但没有播放
} else if (playbackState == Player.STATE_ENDED) {
// 播放完成
}
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
// 横屏
titleTextView.visibility = View.GONE
descriptionTextView.visibility = View.GONE
controllerView.visibility = View.GONE
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
// 竖屏
titleTextView.visibility = View.VISIBLE
descriptionTextView.visibility = View.VISIBLE
controllerView.visibility = View.VISIBLE
}
}
}
这个示例代码中,我们使用了SurfaceView来显示视频画面,使用ConstraintLayout来实现标题和简介等效果UI,并使用ExoPlayer库来播放视频。在横竖屏切换时,我们通过监听配置变化来隐藏和显示相应的布局
原文地址: https://www.cveoy.top/t/topic/iIaX 著作权归作者所有。请勿转载和采集!