make fit inside foo work

This commit is contained in:
Christian Schabesberger 2024-07-23 12:32:24 +02:00
parent 3903e89781
commit b26cf2b402
5 changed files with 79 additions and 60 deletions

View File

@ -4,6 +4,14 @@
<selectionStates>
<SelectionState runConfigName="TestApp">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2024-07-23T10:30:52.346401525Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="PhysicalDevice" identifier="serial=981f7af2" />
</handle>
</Target>
</DropdownSelection>
<DialogSelection />
</SelectionState>
</selectionStates>
</component>

View File

@ -38,7 +38,7 @@ import kotlinx.coroutines.flow.update
import net.newpipe.newplayer.utils.VideoSize
import kotlinx.parcelize.Parcelize
import net.newpipe.newplayer.NewPlayer
import net.newpipe.newplayer.ui.ContentFitMode
import net.newpipe.newplayer.ui.ContentScale
val VIDEOPLAYER_UI_STATE = "video_player_ui_state"
@ -51,7 +51,7 @@ data class VideoPlayerUIState(
var uiVisible: Boolean,
val contentRatio: Float,
val uiRatio: Float,
val contentFitMode: ContentFitMode
val contentFitMode: ContentScale
) : Parcelable {
companion object {
val DEFAULT = VideoPlayerUIState(
@ -60,7 +60,7 @@ data class VideoPlayerUIState(
uiVisible = false,
contentRatio = 16 / 9F,
uiRatio = 16F / 9F,
contentFitMode = ContentFitMode.FIT_INSIDE
contentFitMode = ContentScale.FIT_INSIDE
)
}
}
@ -71,6 +71,7 @@ interface VideoPlayerViewModel {
val uiState: StateFlow<VideoPlayerUIState>
var minContentRatio: Float
var maxContentRatio: Float
var contentFitMode: ContentScale
fun initUIState(instanceState: Bundle)
fun play()
@ -129,6 +130,14 @@ class VideoPlayerViewModelImpl @Inject constructor(
}
}
override var contentFitMode: ContentScale
get() = mutableUiState.value.contentFitMode
set(value) {
mutableUiState.update {
it.copy(contentFitMode = value)
}
}
private fun installExoPlayer() {
player?.let { player ->
Log.d(TAG, "Install player: ${player.videoSize.width}")
@ -227,6 +236,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
override val uiState = MutableStateFlow(VideoPlayerUIState.DEFAULT)
override var minContentRatio = 4F / 3F
override var maxContentRatio = 16F / 9F
override var contentFitMode = ContentScale.FIT_INSIDE
override fun initUIState(instanceState: Bundle) {
println("dummy impl")

View File

@ -1,8 +1,8 @@
package net.newpipe.newplayer.ui
enum class ContentFitMode {
enum class ContentScale {
FILL,
FIT_INSIDE,
ZOOM
CROP
}

View File

@ -28,6 +28,8 @@ import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
@ -45,6 +47,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.media3.common.Player
import net.newpipe.newplayer.model.VideoPlayerViewModel
import net.newpipe.newplayer.model.VideoPlayerViewModelImpl
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
@ -107,60 +110,13 @@ fun VideoPlayerUI(
.aspectRatio(uiState.uiRatio), color = Color.Black
) {
Box(contentAlignment = Alignment.Center) {
val viewBoxModifier = Modifier
when (uiState.contentFitMode) {
ContentFitMode.FILL -> {
println("fit mode fill")
viewBoxModifier.fillMaxSize()
}
ContentFitMode.FIT_INSIDE -> {
println("fit mode fit inside:")
if (uiState.contentRatio < uiState.uiRatio) {
println("fit mode fill max height")
viewBoxModifier
.fillMaxHeight()
.aspectRatio(uiState.contentRatio)
} else if (uiState.uiRatio < uiState.contentRatio) {
println("fit mode fill max width")
viewBoxModifier
.fillMaxWidth()
.aspectRatio(uiState.contentRatio)
}
}
ContentFitMode.ZOOM -> {
println("fit mode zoom:")
if (uiState.uiRatio < uiState.contentRatio) {
viewBoxModifier
.fillMaxHeight()
.aspectRatio(uiState.contentRatio)
} else if (uiState.contentRatio < uiState.uiRatio) {
viewBoxModifier
.fillMaxWidth()
.aspectRatio(uiState.contentRatio)
}
}
}
Box(modifier = viewBoxModifier) {
AndroidView(factory = { context ->
SurfaceView(context).also { view ->
viewModel.player?.setVideoSurfaceView(view)
}
}, update = { view ->
when (lifecycle) {
Lifecycle.Event.ON_RESUME -> {
viewModel.player?.setVideoSurfaceView(view)
}
else -> Unit
}
})
Surface(color = Color.Green, modifier = Modifier.fillMaxSize()) {
}
}
PlaySurface(
player = viewModel.player,
lifecycle = lifecycle,
fitMode = uiState.contentFitMode,
uiRatio = uiState.uiRatio,
contentRatio = uiState.contentRatio
)
}
VideoPlayerControllerUI(
isPlaying = uiState.playing,
@ -176,6 +132,50 @@ fun VideoPlayerUI(
}
}
@Composable
fun PlaySurface(
player: Player?,
lifecycle: Lifecycle.Event,
fitMode: ContentScale,
uiRatio: Float,
contentRatio: Float
) {
val viewBoxModifier = Modifier
viewBoxModifier
.fillMaxWidth()
.aspectRatio(16F / 9F)
Box(
modifier = Modifier
.then(
when (fitMode) {
ContentScale.FILL -> Modifier.fillMaxSize()
ContentScale.FIT_INSIDE -> Modifier.aspectRatio(contentRatio)
ContentScale.CROP -> Modifier
.aspectRatio(contentRatio)
.wrapContentWidth(unbounded = true)
.fillMaxSize()
}
)
) {
AndroidView(factory = { context ->
SurfaceView(context).also { view ->
player?.setVideoSurfaceView(view)
}
}, update = { view ->
when (lifecycle) {
Lifecycle.Event.ON_RESUME -> {
player?.setVideoSurfaceView(view)
}
else -> Unit
}
})
}
}
@Preview(device = "spec:width=1080px,height=700px,dpi=440,orientation=landscape")
@Composable

View File

@ -26,12 +26,12 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.viewmodel.compose.viewModel
import dagger.hilt.android.AndroidEntryPoint
import net.newpipe.newplayer.NewPlayer
import net.newpipe.newplayer.VideoPlayerView
import net.newpipe.newplayer.model.VideoPlayerViewModel
import net.newpipe.newplayer.model.VideoPlayerViewModelImpl
import net.newpipe.newplayer.ui.ContentScale
import javax.inject.Inject
@AndroidEntryPoint
@ -52,6 +52,7 @@ class MainActivity : AppCompatActivity() {
videoPlayerViewModel.newPlayer = newPlayer
videoPlayerViewModel.maxContentRatio = 4F/3F
videoPlayerViewModel.contentFitMode = ContentScale.FIT_INSIDE
/*
video_view.fullScreenToggleListener = object : VideoPlayerView.FullScreenToggleListener {