优化视频播放

优化Player UI
This commit is contained in:
Lindong 2026-01-29 01:25:09 +08:00
parent 999e882af3
commit b795f4458a
8 changed files with 323 additions and 245 deletions

View File

@ -39,7 +39,7 @@ class VersionActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnT
// For Testing
val shouldShowDebug = false//BuildConfig.DEBUG
val shouldShowDebug = true//BuildConfig.DEBUG
llTesting.isVisible = shouldShowDebug
if (shouldShowDebug) {
butCash.setOnClickListener {

View File

@ -14,7 +14,6 @@ import android.view.animation.Animation
import android.view.animation.AnimationSet
import android.view.animation.ScaleAnimation
import android.widget.FrameLayout
import androidx.annotation.NonNull
import androidx.core.view.isVisible
import com.ama.core.architecture.appBase.AppViewsEmptyViewModelFragment
import com.ama.core.architecture.util.AndroidUtil
@ -28,8 +27,6 @@ import com.gamedog.vididin.youtubestatistic.TickerTimer
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.PlayerConstants
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.YouTubePlayer
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.listeners.AbstractYouTubePlayerListener
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.listeners.YouTubePlayerCallback
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.utils.loadOrCueVideo
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.options.IFramePlayerOptions
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView
import com.viddin.videos.free.databinding.VididinappFeatureHomeItemLayoutBinding as ViewBinding
@ -192,7 +189,6 @@ class HomeItemFragment : AppViewsEmptyViewModelFragment<ViewBinding>() {
mPlayer = youTubePlayer
val playerUiController = MyPlayerControlView(mPlayerView!!)
mPlayerView!!.setCustomPlayerUi(playerUiController.rootView)
if (mPendingPlay) {
mPlayer?.loadVideo(mVideoData!!.id, mCurPlayedSecond)
} else if (mIsPreloading) {
@ -392,7 +388,6 @@ class HomeItemFragment : AppViewsEmptyViewModelFragment<ViewBinding>() {
private fun hidePlayIconAnim() {
return
if (!binding?.playIcon!!.isVisible) {
return
}
@ -400,7 +395,7 @@ class HomeItemFragment : AppViewsEmptyViewModelFragment<ViewBinding>() {
with (binding?.playIcon!!) {
val animationSet = AnimationSet(true)
animationSet.duration = 250
animationSet.duration = 100
val alphaAnimation = AlphaAnimation(0.6f, 0.3f)
val scaleAnimation = ScaleAnimation(
1.0f, 0.5f,
@ -428,12 +423,11 @@ class HomeItemFragment : AppViewsEmptyViewModelFragment<ViewBinding>() {
}
private fun showPlayIconAnim() {
return
with (binding?.playIcon!!) {
visibility = View.VISIBLE
val animationSet = AnimationSet(true)
animationSet.duration = 250
animationSet.duration = 100
val alphaAnimation = AlphaAnimation(0.3f, 0.6f)
val scaleAnimation = ScaleAnimation(
0.5f, 1.0f,

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -11,7 +11,7 @@ import org.json.JSONObject
class IFramePlayerOptions private constructor(private val playerOptions: JSONObject) {
companion object {
fun getDefault(context: Context) = Builder(context).controls(1).build()
fun getDefault(context: Context) = Builder(context).controls(0).build()
}
override fun toString(): String {

View File

@ -37,23 +37,89 @@
var player;
var timerId;
function hideYouTubeUI() {
setInterval(() => {
const playerIFrame = document.querySelector("iframe");
if (!playerIFrame) {
return;
}
const frameDoc = playerIFrame.contentDocument || playerIFrame.contentWindow.document;
if (!frameDoc) {
return;
}
const selectorsToHide = [
'.ytp-chrome-top',
'.ytp-chrome-bottom',
'.ytp-gradient-top',
'.ytp-gradient-bottom',
'.ytp-youtube-button',
'.ytp-watermark',
'.ytp-ce-element',
'.ytp-paid-content-overlay',
'.ytp-bezel-container',
'.ytp-spinner',
'.ytp-cards-teaser',
'.ytp-cards-button',
'.ytp-show-cards-title'
];
selectorsToHide.forEach(selector => {
const elements = frameDoc.querySelectorAll(selector);
elements.forEach(el => {
if (el.style.display !== 'none') {
el.style.display = 'none';
}
});
});
// Special handling for pause overlays to avoid black screen issue
const pauseOverlays = ['.ytp-pause-overlay', '.ytp-pause-overlay-container'];
pauseOverlays.forEach(selector => {
const elements = frameDoc.querySelectorAll(selector);
elements.forEach(el => {
if (el.style.visibility !== 'hidden') {
el.style.visibility = 'hidden';
el.style.pointerEvents = 'none';
}
});
});
if (player && typeof player.unloadModule === 'function') {
player.unloadModule('captions');
}
// Disable captions if any
const captions = frameDoc.querySelector('.ytp-caption-window-container');
if (captions) {
captions.style.display = 'none';
}
}, 50);
}
function onYouTubeIframeAPIReady() {
YouTubePlayerBridge.sendYouTubeIFrameAPIReady();
var playerVars = <<injectedPlayerVars>>;
// Force some player vars to hide UI elements at the API level
// but avoid overriding everything to stay compatible
playerVars.rel = 0;
playerVars.iv_load_policy = 3;
playerVars.modestbranding = 1;
var youtubePlayerConfig = {
height: '100%',
width: '100%',
events: {
onReady: function(event) { YouTubePlayerBridge.sendReady() },
onReady: function(event) { YouTubePlayerBridge.sendReady();hideYouTubeUI(); },
onStateChange: function(event) { sendPlayerStateChange(event.data) },
onPlaybackQualityChange: function(event) { YouTubePlayerBridge.sendPlaybackQualityChange(event.data) },
onPlaybackRateChange: function(event) { YouTubePlayerBridge.sendPlaybackRateChange(event.data) },
onError: function(error) { YouTubePlayerBridge.sendError(error.data) },
onApiChange: function(event) { YouTubePlayerBridge.sendApiChange() }
},
playerVars: <<injectedPlayerVars>>
playerVars: playerVars
};
if (<<injectedVideoId>>) {

View File

@ -25,7 +25,8 @@ class DefaultPlayerUiController(
private val youTubePlayer: YouTubePlayer
) : PlayerUiController {
val rootView: View = View.inflate(youTubePlayerView.context, R.layout.ayp_default_player_ui, null)
val rootView: View =
View.inflate(youTubePlayerView.context, R.layout.ayp_default_player_ui, null)
private var youTubePlayerMenu: YouTubePlayerMenu = DefaultYouTubePlayerMenu(
youTubePlayerView.context
@ -38,7 +39,8 @@ class DefaultPlayerUiController(
private val panel: View = rootView.findViewById(R.id.panel)
private val controlsContainer: View = rootView.findViewById(R.id.controls_container)
private val extraViewsContainer: LinearLayout = rootView.findViewById(R.id.extra_views_container)
private val extraViewsContainer: LinearLayout =
rootView.findViewById(R.id.extra_views_container)
private val videoTitle: TextView = rootView.findViewById(R.id.video_title)
private val liveVideoIndicator: TextView = rootView.findViewById(R.id.live_video_indicator)
@ -50,9 +52,11 @@ class DefaultPlayerUiController(
private val fullscreenButton: ImageView = rootView.findViewById(R.id.fullscreen_button)
private val customActionLeft: ImageView = rootView.findViewById(R.id.custom_action_left_button)
private val customActionRight: ImageView = rootView.findViewById(R.id.custom_action_right_button)
private val customActionRight: ImageView =
rootView.findViewById(R.id.custom_action_right_button)
private val youtubePlayerSeekBar: YouTubePlayerSeekBar = rootView.findViewById(R.id.youtube_player_seekbar)
private val youtubePlayerSeekBar: YouTubePlayerSeekBar =
rootView.findViewById(R.id.youtube_player_seekbar)
private val fadeControlsContainer: FadeViewHelper = FadeViewHelper(controlsContainer)
private var onFullscreenButtonListener: View.OnClickListener
@ -66,11 +70,19 @@ class DefaultPlayerUiController(
private var isMatchParent = false
private val youTubePlayerStateListener = object : AbstractYouTubePlayerListener() {
override fun onStateChange(youTubePlayer: YouTubePlayer, state: PlayerConstants.PlayerState) {
override fun onStateChange(
youTubePlayer: YouTubePlayer,
state: PlayerConstants.PlayerState
) {
updateState(state)
if (state === PlayerConstants.PlayerState.PLAYING || state === PlayerConstants.PlayerState.PAUSED || state === PlayerConstants.PlayerState.VIDEO_CUED) {
panel.setBackgroundColor(ContextCompat.getColor(panel.context, android.R.color.transparent))
panel.setBackgroundColor(
ContextCompat.getColor(
panel.context,
android.R.color.transparent
)
)
progressBar.visibility = View.GONE
if (isPlayPauseButtonEnabled) playPauseButton.visibility = View.VISIBLE
@ -83,7 +95,8 @@ class DefaultPlayerUiController(
updatePlayPauseButtonIcon(false)
if (state === PlayerConstants.PlayerState.BUFFERING) {
progressBar.visibility = View.VISIBLE
// progressBar.visibility = View.VISIBLE
progressBar.visibility = View.GONE
panel.setBackgroundColor(
ContextCompat.getColor(
panel.context,
@ -133,6 +146,7 @@ class DefaultPlayerUiController(
}
private fun initClickListeners() {
fadeControlsContainer.isDisabled = true
youTubePlayer.addListener(youtubePlayerSeekBar)
youTubePlayer.addListener(fadeControlsContainer)
youTubePlayer.addListener(youTubePlayerStateListener)
@ -218,12 +232,14 @@ class DefaultPlayerUiController(
}
override fun showCurrentTime(show: Boolean): PlayerUiController {
youtubePlayerSeekBar.videoCurrentTimeTextView.visibility = if (show) View.VISIBLE else View.GONE
youtubePlayerSeekBar.videoCurrentTimeTextView.visibility =
if (show) View.VISIBLE else View.GONE
return this
}
override fun showDuration(show: Boolean): PlayerUiController {
youtubePlayerSeekBar.videoDurationTextView.visibility = if (show) View.VISIBLE else View.GONE
youtubePlayerSeekBar.videoDurationTextView.visibility =
if (show) View.VISIBLE else View.GONE
return this
}

View File

@ -2,6 +2,7 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
xmlns:app="http://schemas.android.com/apk/res-auto">
<View
@ -93,6 +94,7 @@
android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_centerInParent="true" />
<LinearLayout