视频组件优化

This commit is contained in:
2026-05-28 16:08:54 +08:00
parent bb0d3278d9
commit b2d3046560
7 changed files with 147 additions and 120 deletions

View File

@@ -29,6 +29,7 @@ import com.example.defenseapplication.bean.DeviceBean
import com.example.defenseapplication.bean.FamilyBean
import com.example.defenseapplication.bean.SwitchFamilyRequest
import com.example.defenseapplication.databinding.HomeMenuFragmentBinding
import com.example.defenseapplication.liveVideo.LiveVideoActivity
import com.example.defenseapplication.utils.DeviceIdEvent
import com.example.defenseapplication.utils.DeviceUpdateEvent
import com.example.defenseapplication.utils.FamilySwitchEvent
@@ -461,7 +462,7 @@ class HomeMenuFragment : Fragment() {
private fun onDeviceClicked(device: DeviceUi) {
if (device.isOnline) {
DeviceIdEvent.setDeviceId(device.deviceId)
val intent = Intent(requireContext(), com.example.defenseapplication.liveVideo.LiveVideoActivity::class.java)
val intent = Intent(requireContext(), LiveVideoActivity::class.java)
intent.putExtra("device_name", device.name)
startActivity(intent)
} else {

View File

@@ -1,10 +1,13 @@
package com.example.defenseapplication.liveVideo
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
@@ -13,9 +16,11 @@ import androidx.recyclerview.widget.LinearLayoutManager
import chuangyuan.ycj.videolibrary.listener.VideoInfoListener
import chuangyuan.ycj.videolibrary.video.ExoUserPlayer
import chuangyuan.ycj.videolibrary.video.VideoPlayerManager
import com.google.android.exoplayer2.ui.PlayerView
import com.example.defenseapplication.R
import com.example.defenseapplication.adapter.AlarmLogAdapter
import com.example.defenseapplication.databinding.AlarmLogActivityBinding
import com.example.defenseapplication.utils.ActivityManager
import com.gyf.immersionbar.ImmersionBar
import java.util.*
import com.bigkoo.pickerview.builder.TimePickerBuilder
@@ -28,6 +33,9 @@ class AlarmLogActivity : AppCompatActivity() {
private var adapter: AlarmLogAdapter? = null
private val alarmList = mutableListOf<String>()
private lateinit var exoPlayerManager: ExoUserPlayer
private var isMuted = false
private var isVoiceEnabled = false
private var isLightOn = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -94,6 +102,39 @@ class AlarmLogActivity : AppCompatActivity() {
.create()
exoPlayerManager.startPlayer()
setupControllerVisibilityListener()
}
private fun setupControllerVisibilityListener() {
binding.exoPlayContextId.post {
val playerView = findPlayerView(binding.exoPlayContextId)
playerView?.setControllerVisibilityListener { visibility ->
if (visibility == View.VISIBLE) {
binding.muteBar.visibility = View.VISIBLE
binding.functionBar.visibility = View.VISIBLE
} else {
binding.muteBar.visibility = View.GONE
binding.functionBar.visibility = View.GONE
}
}
}
}
private fun findPlayerView(view: View): PlayerView? {
if (view is PlayerView) {
return view
}
if (view is ViewGroup) {
for (i in 0 until view.childCount) {
val child = view.getChildAt(i)
val found = findPlayerView(child)
if (found != null) {
return found
}
}
}
return null
}
private fun initRecyclerView() {
@@ -122,6 +163,37 @@ class AlarmLogActivity : AppCompatActivity() {
binding.expandImg.setOnClickListener {
showDatePicker()
}
binding.ivMute.setOnClickListener {
toggleMute()
}
binding.ivDownload.setOnClickListener {
downloadVideo()
}
binding.ivDelete.setOnClickListener {
deleteVideo()
}
}
private fun toggleMute() {
isMuted = !isMuted
if (isMuted) {
binding.ivMute.setImageResource(R.drawable.mute)
Toast.makeText(this, R.string.sound_off, Toast.LENGTH_SHORT).show()
} else {
binding.ivMute.setImageResource(R.drawable.voice)
Toast.makeText(this, R.string.sound_on, Toast.LENGTH_SHORT).show()
}
}
private fun downloadVideo() {
Toast.makeText(this, R.string.download, Toast.LENGTH_SHORT).show()
}
private fun deleteVideo() {
Toast.makeText(this, R.string.delete, Toast.LENGTH_SHORT).show()
}
override fun onResume() {
@@ -158,7 +230,7 @@ class AlarmLogActivity : AppCompatActivity() {
val params = binding.exoPlayContextId.layoutParams
params.width = LinearLayout.LayoutParams.MATCH_PARENT
params.height = dpToPx(250)
params.height = dpToPx(280)
binding.exoPlayContextId.layoutParams = params
}

View File

@@ -23,11 +23,7 @@ import androidx.activity.OnBackPressedCallback
import chuangyuan.ycj.videolibrary.listener.VideoInfoListener
import chuangyuan.ycj.videolibrary.video.VideoPlayerManager
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
//智能防御机A1
class LiveVideoActivity : BaseActivity() {
private lateinit var binding: LiveVideoActivityBinding
@@ -37,8 +33,6 @@ class LiveVideoActivity : BaseActivity() {
private var isRecording = false
private var mediaRecorder: MediaRecorder? = null
private var micPulseAnimation: ScaleAnimation? = null
private var isFullscreen = false
private var fullscreenBackButton: ImageView? = null
private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
@@ -56,7 +50,6 @@ class LiveVideoActivity : BaseActivity() {
binding = LiveVideoActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
// ImmersionBar核心调用,沉浸式
ImmersionBar.with(this)
.statusBarDarkFont(true)
.titleBar(binding.topBar)
@@ -67,7 +60,6 @@ class LiveVideoActivity : BaseActivity() {
binding.tvTitle.text = deviceName
}
// 初始化播放器
initVideoPlayer()
initListener()
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
@@ -75,25 +67,23 @@ class LiveVideoActivity : BaseActivity() {
if (exoPlayerManager.onBackPressed()) {
return
}
// 无全屏时执行默认返回逻辑(如 finish
finish()
}
})
}
private fun initVideoPlayer() {
val videoPlayerView = binding.exoPlayContextId
exoPlayerManager = VideoPlayerManager.Builder(VideoPlayerManager.TYPE_PLAY_GESTURE, videoPlayerView)
.setPlayUri("https://media.w3.org/2010/05/sintel/trailer.mp4")//真实地址
.setPlayUri("https://media.w3.org/2010/05/sintel/trailer.mp4")
.setPosition(0)
.addVideoInfoListener(object : VideoInfoListener {
// 注意:此处的 p0: Long 是视频开始播放时的位置信息,可以按需使用
override fun onPlayStart(p0: Long) {
Log.d("AlarmLogActivity", "视频开始播放")
Log.d("LiveVideoActivity", "视频开始播放")
}
override fun onLoadingChanged() {
// 视频加载状态变化
}
override fun onPlayerError(p0: com.google.android.exoplayer2.ExoPlaybackException?) {
@@ -101,93 +91,18 @@ class LiveVideoActivity : BaseActivity() {
}
override fun onPlayEnd() {
Log.d("AlarmLogActivity", "播放结束")
Log.d("LiveVideoActivity", "播放结束")
}
// 修正点:库的接口要求必须实现 isPlaying 方法
override fun isPlaying(p0: Boolean) {
// p0 表示当前是否正在播放
}
fun onRepeatModeChanged(p0: Int) {
// 循环模式改变时的回调
}
})
.create()
exoPlayerManager.startPlayer()
setupFullscreenListener()
}
private fun setupFullscreenListener() {
binding.exoPlayContextId.setOnClickListener {
if (!isFullscreen) {
enterFullscreen()
}
}
}
private fun enterFullscreen() {
isFullscreen = true
binding.topBar.visibility = View.GONE
binding.functionBar.visibility = View.GONE
val params = binding.exoPlayContextId.layoutParams
params.width = LinearLayout.LayoutParams.MATCH_PARENT
params.height = LinearLayout.LayoutParams.MATCH_PARENT
binding.exoPlayContextId.layoutParams = params
exoPlayerManager.onConfigurationChanged(Configuration().apply {
orientation = Configuration.ORIENTATION_LANDSCAPE
})
showFullscreenBackButton()
}
private fun exitFullscreen() {
isFullscreen = false
binding.topBar.visibility = View.VISIBLE
binding.functionBar.visibility = View.VISIBLE
val params = binding.exoPlayContextId.layoutParams
params.width = LinearLayout.LayoutParams.MATCH_PARENT
params.height = 250
binding.exoPlayContextId.layoutParams = params
exoPlayerManager.onConfigurationChanged(Configuration().apply {
orientation = Configuration.ORIENTATION_PORTRAIT
})
hideFullscreenBackButton()
}
private fun showFullscreenBackButton() {
fullscreenBackButton = ImageView(this).apply {
setImageResource(R.drawable.back_white)
scaleType = ImageView.ScaleType.CENTER_CROP
val params = LinearLayout.LayoutParams(60, 60)
params.topMargin = 60
params.leftMargin = 20
layoutParams = params
setOnClickListener {
exitFullscreen()
}
}
(binding.root as ViewGroup).addView(fullscreenBackButton)
fullscreenBackButton?.bringToFront()
}
private fun hideFullscreenBackButton() {
fullscreenBackButton?.let {
(binding.root as ViewGroup).removeView(it)
fullscreenBackButton = null
}
}
private fun initListener() {
@@ -203,6 +118,7 @@ class LiveVideoActivity : BaseActivity() {
val intent = Intent(this, SettingsActivity::class.java)
startActivity(intent)
}
binding.llVoice.setOnClickListener {
toggleVoice()
}
@@ -219,14 +135,12 @@ class LiveVideoActivity : BaseActivity() {
Toast.makeText(this, R.string.view_alarm_log, Toast.LENGTH_SHORT).show()
}
// 点击xq箭头跳转到AlarmLogActivity
binding.xq.setOnClickListener {
val intent = Intent(this, AlarmLogActivity::class.java)
startActivity(intent)
}
}
private fun toggleVoice() {
isVoiceEnabled = !isVoiceEnabled
@@ -278,20 +192,14 @@ class LiveVideoActivity : BaseActivity() {
isRecording = true
binding.ivRecord.setImageResource(com.example.defenseapplication.R.drawable.copy_open)
// 隐藏告警日志区域,显示控制台区域
binding.llAlarmLog.visibility = View.GONE
binding.consoleBar.visibility = View.VISIBLE
// 麦克风切换成开启状态
binding.ivVoice.setImageResource(com.example.defenseapplication.R.drawable.voice_on_open)
isVoiceEnabled = true
// 启动语音录制
startVoiceRecording()
// 启动麦克风脉冲动画
//startMicPulseAnimation()
Toast.makeText(this, R.string.start_control_mode, Toast.LENGTH_SHORT).show()
}
@@ -299,24 +207,18 @@ class LiveVideoActivity : BaseActivity() {
isRecording = false
binding.ivRecord.setImageResource(com.example.defenseapplication.R.drawable.copy)
// 显示告警日志区域,隐藏控制台区域
binding.llAlarmLog.visibility = View.VISIBLE
binding.consoleBar.visibility = View.GONE
// 麦克风切换成关闭状态
binding.ivVoice.setImageResource(com.example.defenseapplication.R.drawable.voice)
isVoiceEnabled = false
// 停止语音录制
stopVoiceRecording()
// 停止麦克风脉冲动画
stopMicPulseAnimation()
Toast.makeText(this, R.string.stop_control_mode, Toast.LENGTH_SHORT).show()
}
private fun stopMicPulseAnimation() {
micPulseAnimation?.let {
binding.ivVoice.clearAnimation()
@@ -358,6 +260,7 @@ class LiveVideoActivity : BaseActivity() {
mediaRecorder = null
}
}
override fun onResume() {
super.onResume()
exoPlayerManager.onResume()
@@ -375,9 +278,6 @@ class LiveVideoActivity : BaseActivity() {
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
// 横竖屏切换时通知播放器
exoPlayerManager.onConfigurationChanged(newConfig)
}
}

View File

@@ -7,13 +7,66 @@
android:background="#F9F9F9"
android:orientation="vertical">
<!-- 视频播放区域 -->
<chuangyuan.ycj.videolibrary.widget.VideoPlayerView
android:id="@+id/exoPlayContextId"
<!-- 视频播放区域和悬浮按钮 -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="@android:color/transparent"
app:use_controller="true"/>
android:layout_height="wrap_content">
<!-- 视频播放区域 -->
<chuangyuan.ycj.videolibrary.widget.VideoPlayerView
android:id="@+id/exoPlayContextId"
android:layout_width="match_parent"
android:layout_height="280dp"
android:background="@android:color/transparent"
app:use_controller="true" />
<!-- 右上角按钮区域 - 下载和删除横向排列 -->
<LinearLayout
android:id="@+id/functionBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|end"
android:layout_marginTop="40dp"
android:layout_marginEnd="6dp"
android:orientation="horizontal"
android:visibility="gone">
<ImageView
android:id="@+id/ivDownload"
android:layout_width="40dp"
android:layout_height="40dp"
android:padding="8dp"
android:src="@drawable/download"/>
<ImageView
android:id="@+id/ivDelete"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="12dp"
android:padding="8dp"
android:src="@drawable/delete"/>
</LinearLayout>
<!-- 右下角按钮区域 - 静音按钮 -->
<LinearLayout
android:layout_marginBottom="40dp"
android:id="@+id/muteBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="6dp"
android:visibility="gone">
<ImageView
android:id="@+id/ivMute"
android:layout_width="40dp"
android:layout_height="40dp"
android:padding="8dp"
android:src="@drawable/mute"/>
</LinearLayout>
</FrameLayout>
<LinearLayout

View File

@@ -6,7 +6,6 @@
android:background="#F5F6F6"
android:name=".liveVideo.LiveVideoActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:screenOrientation="portrait"
android:orientation="vertical">
<!-- 顶部导航栏 -->
@@ -50,7 +49,7 @@
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="@android:color/transparent"
app:use_controller="false"/>
app:use_controller="true"/>
<!-- 功能按钮区域 -->
<LinearLayout

View File

@@ -347,6 +347,7 @@
<string name="exited_fullscreen">已退出全屏</string>
<string name="sound_on">声音已开启</string>
<string name="sound_off">声音已关闭</string>
<string name="download">下载</string>
<string name="light_on">灯光已开启</string>
<string name="light_off">灯光已关闭</string>
<string name="start_control_mode">开始控制模式</string>

View File

@@ -338,6 +338,7 @@
<string name="exited_fullscreen">Exited fullscreen</string>
<string name="sound_on">Sound on</string>
<string name="sound_off">Sound off</string>
<string name="download">Download</string>
<string name="light_on">Light on</string>
<string name="light_off">Light off</string>
<string name="start_control_mode">Start control mode</string>