下面是一个使用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库来播放视频。在横竖屏切换时,我们通过监听配置变化来隐藏和显示相应的布局

Android kotlin ExoPlayer+SurfaceView使用ConstraintLayout添加标题简介等效果UI 横竖屏切换 布局隐藏与显示问题详细代码与实现

原文地址: https://www.cveoy.top/t/topic/iIaX 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录