clamp aspect ratio for embedded player

This commit is contained in:
Christian Schabesberger 2024-07-19 12:38:23 +02:00
parent 4d3eff9630
commit f11d35818f
8 changed files with 86 additions and 11 deletions

View File

@ -0,0 +1,4 @@
kotlin version: 2.0.20-Beta2
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output:
1. Kotlin compile daemon is ready

View File

@ -72,7 +72,7 @@ androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
newplayer = { group = "com.github.theScrabi", name = "NewPlayer", version.ref = "newplayer" } newplayer = { group = "com.github.theScrabi.NewPlayer", name = "new-player", version.ref = "newplayer" }
[plugins] [plugins]

View File

@ -20,14 +20,31 @@
package net.newpipe.newplayer package net.newpipe.newplayer
import android.app.Activity
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentContainer
import androidx.fragment.app.FragmentContainerView
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import net.newpipe.newplayer.internal.VideoPlayerFragment
@AndroidEntryPoint @AndroidEntryPoint
class VideoPlayerView : FrameLayout { class VideoPlayerView : FrameLayout {
val videoPlayerFragment:VideoPlayerFragment
var maxLayoutRatio: Float
get() = videoPlayerFragment.maxLayoutRatio
set(value) {videoPlayerFragment.maxLayoutRatio=value}
var minLayoutRatio: Float
get() = videoPlayerFragment.minLayoutRatio
set(value) {videoPlayerFragment.maxLayoutRatio = value}
@JvmOverloads @JvmOverloads
constructor( constructor(
context: Context, context: Context,
@ -35,5 +52,17 @@ class VideoPlayerView : FrameLayout {
defStyleAttr: Int = 0 defStyleAttr: Int = 0
) : super(context, attrs, defStyleAttr) { ) : super(context, attrs, defStyleAttr) {
val view = LayoutInflater.from(context).inflate(R.layout.video_player_view, this) val view = LayoutInflater.from(context).inflate(R.layout.video_player_view, this)
videoPlayerFragment = VideoPlayerFragment()
when (context) {
is AppCompatActivity -> {
context.supportFragmentManager.beginTransaction()
.add(R.id.video_player_fragment_container, videoPlayerFragment).commit()
}
else -> {
throw Exception("The context that should host the NewPlayer Embedded VideoPlayerView is not an AppCompatActivity: $context")
}
}
} }
} }

View File

@ -21,6 +21,7 @@
package net.newpipe.newplayer.internal package net.newpipe.newplayer.internal
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -42,7 +43,36 @@ import net.newpipe.newplayer.internal.ui.theme.VideoPlayerTheme
@AndroidEntryPoint @AndroidEntryPoint
class VideoPlayerFragment() : Fragment() { class VideoPlayerFragment() : Fragment() {
private val TAG = "VideoPlayerFragment"
private val viewModel: VideoPlayerViewModel by viewModels<VideoPlayerViewModelImpl>() private val viewModel: VideoPlayerViewModel by viewModels<VideoPlayerViewModelImpl>()
private var currentVideoRatio = 0F
private lateinit var composeView: ComposeView
var minLayoutRatio = 4F / 3F
set(value) {
if (value <= 0 && maxLayoutRatio < minLayoutRatio)
Log.e(
TAG,
"minLayoutRatio can not be 0 or smaller or bigger then maxLayoutRatio. Ignore: $value"
)
else {
field = value
updateViewRatio()
}
}
var maxLayoutRatio = 16F / 9F
set(value) {
if (value <= 0 && value < minLayoutRatio)
Log.e(
TAG,
"maxLayoutRatio can not be 0 smaller ans smaller then minLayoutRatio. Ignore: $value"
)
else {
field = value
updateViewRatio()
}
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
@ -51,16 +81,16 @@ class VideoPlayerFragment() : Fragment() {
): View? { ): View? {
val window = activity?.window!! val window = activity?.window!!
val insetsController = WindowCompat.getInsetsController(window, window.decorView) val insetsController = WindowCompat.getInsetsController(window, window.decorView)
insetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE insetsController.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
val view = inflater.inflate(R.layout.video_player_framgent, container, false) val view = inflater.inflate(R.layout.video_player_framgent, container, false)
val composeView = view.findViewById<ComposeView>(R.id.player_copose_view) composeView = view.findViewById(R.id.player_copose_view)
viewModel.listener = object : VideoPlayerViewModel.Listener { viewModel.listener = object : VideoPlayerViewModel.Listener {
override fun requestUpdateLayoutRatio(ratio: Float) { override fun requestUpdateLayoutRatio(videoRatio: Float) {
composeView.updateLayoutParams<ConstraintLayout.LayoutParams> { currentVideoRatio = videoRatio
dimensionRatio = "$ratio:1" updateViewRatio()
}
} }
} }
@ -77,4 +107,11 @@ class VideoPlayerFragment() : Fragment() {
return view return view
} }
private fun updateViewRatio() {
composeView.updateLayoutParams<ConstraintLayout.LayoutParams> {
val ratio = currentVideoRatio.coerceIn(minLayoutRatio, maxLayoutRatio)
dimensionRatio = "$ratio:1"
}
}
} }

View File

@ -166,7 +166,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
player.prepare() player.prepare()
} }
player.setMediaItem(MediaItem.fromUri(app.getString(R.string.ccc_chromebooks_video))) player.setMediaItem(MediaItem.fromUri(app.getString(R.string.portrait_video_example)))
player.playWhenReady = true player.playWhenReady = true
} }

View File

@ -20,8 +20,7 @@
<androidx.fragment.app.FragmentContainerView <androidx.fragment.app.FragmentContainerView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/video_player_fragment" android:id="@+id/video_player_fragment_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:minHeight="50dp" android:minHeight="50dp" />
android:name="net.newpipe.newplayer.internal.VideoPlayerFragment" />

View File

@ -23,4 +23,5 @@
<string name="ccc_6502_video">https://ftp.fau.de/cdn.media.ccc.de/congress/2010/mp4-h264-HQ/27c3-4159-en-reverse_engineering_mos_6502.mp4</string> <string name="ccc_6502_video">https://ftp.fau.de/cdn.media.ccc.de/congress/2010/mp4-h264-HQ/27c3-4159-en-reverse_engineering_mos_6502.mp4</string>
<string name="ccc_6502_audio">https://ftp.fau.de/cdn.media.ccc.de/congress/2010/ogg-audio-only/27c3-4159-en-reverse_engineering_mos_6502.ogg</string> <string name="ccc_6502_audio">https://ftp.fau.de/cdn.media.ccc.de/congress/2010/ogg-audio-only/27c3-4159-en-reverse_engineering_mos_6502.ogg</string>
<string name="ccc_chromebooks_video">https://ftp.fau.de/cdn.media.ccc.de/congress/2023/h264-hd/37c3-11929-eng-deu-swe-Turning_Chromebooks_into_regular_laptops_hd.mp4</string> <string name="ccc_chromebooks_video">https://ftp.fau.de/cdn.media.ccc.de/congress/2023/h264-hd/37c3-11929-eng-deu-swe-Turning_Chromebooks_into_regular_laptops_hd.mp4</string>
<string name="portrait_video_example">https://videos.pexels.com/video-files/5512609/5512609-hd_1080_1920_25fps.mp4</string>
</resources> </resources>

View File

@ -27,6 +27,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import net.newpipe.newplayer.VideoPlayerView
@AndroidEntryPoint @AndroidEntryPoint
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
@ -35,6 +36,10 @@ class MainActivity : AppCompatActivity() {
enableEdgeToEdge() enableEdgeToEdge()
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
val video_view = findViewById<VideoPlayerView>(R.id.new_player_video_view)
video_view.minLayoutRatio
//TODO: This is a dirty hack. Fix this later on //TODO: This is a dirty hack. Fix this later on
if (getResources().configuration.orientation != Configuration.ORIENTATION_LANDSCAPE) { if (getResources().configuration.orientation != Configuration.ORIENTATION_LANDSCAPE) {
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->