Hey guys, I am trying to stack Composables that co...
# compose
s
Hey guys, I am trying to stack Composables that contain
AndroidView
. However they seem to not respect the
zIndex
in a
Box
Layout. The newest composable associated with lowest zIndex always renders at the top even though it should be at the bottom. Here’s the code. 🧵
Copy code
var movieList = remember { mutableStateListOf(mock4.get(0), mock4.get(1), mock4.get(2), mock4.get(3), mock4.get(4), mock4.get(5),) }

fun onClick() {
  movieList.removeLast()
}

Column {
  // I only pass the last two elements from the above list to be rendered
  ContentList(movieList.takeLast(2))

// Clicking the button removes the last element from the list
  Button( onClick = ::onClick) {
    Text(text = "remove last")
  }
}
Copy code
@Composable
private fun ContentList(movieList: List<GameEntry>) {
  Box {
    LogCompositions(tag = "", msg = "ContentList Box ")
      movieList.forEachIndexed { index, movie ->
       // I do not want to rerender composables based on the id field, which is unique
        key(movie.id) {
          ContentView(
            Modifier.fillMaxWidth(), movie, index == 1
          )
        }
      }
  }
}
Copy code
@Composable
private fun ContentView(modifier: Modifier, movie: GameEntry, isActive: Boolean) {
  Card(
    modifier
      .height(400.dp)
      .padding(horizontal = 30.dp)
  ) {
    MediaPlayer(videoUri = movie.media?.url.toString(), id = movie.id, isActive)
    
// The below text Composable works as expected but the ^^ Media player does not
    Text(
      text = movie.id.toString(),
      textAlign = TextAlign.Center,
      modifier = Modifier.fillMaxWidth()
    )
  }
  DisposableEffect(Unit) {
    onDispose {
      Log.e("", "Disposed Card id -> ${movie.id}")
    }
  }
}
Copy code
@Composable
fun MediaPlayer(videoUri: String, id: Long, isActive:Boolean) {
  val exoPlayer = remember {... }

  DisposableEffect(
    AndroidView(
      factory = {
        PlayerView(context).apply {
          hideController()
          useController = false
          resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM
          player = exoPlayer
          layoutParams = FrameLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT
          )
        }
      },
    )
  ) {
    onDispose {
      exoPlayer.release()
    }
  }
}
for more context, the idea is to render two videos stacked on top of each other.For eg lets say video with ids
[4, 5].
At first video on top
[5]
is visible. On pressing the button , this video is removed from movieList and last 2 videos
[3,4]
are passed to ContentList . Now instead of seeing video
[4]
on top, somehow video
[3]
is visible at the top of Box. I have verified that the rendering sequence is correct, yet somehow i see preview for video
[3]
on top
c
Are you still working on this problem? https://kotlinlang.slack.com/archives/CJLTWPH7S/p1678626822355719 How is your PlayerView configured? Specifically the surface type
Assuming you’re using the default (SurfaceView) you should look at this docs for details about z-ordering https://developer.android.com/reference/android/view/SurfaceView
s
@Chris Fillmore I am using the default Surface View, provided by PlayerView (media 3 lib) and did play around
setZOrderMediaOverlay
and
setZOrderOnTop
with no success 😞 . Here’s the repo,.
c
Have you tried configuring PlayerView to use a TextureView? https://developer.android.com/reference/androidx/media3/ui/PlayerView
s
I was going to try that next. ^^ Here’s quick preview of the problem. • The video [4,5] get loaded. [5] is at top of box. • The first video gets removed. —> [3,4] • The second video in line plays/is visible for a quick second. • The third video [3] which is freshly added to the bottom of the Box starts playing over video [4].
c
I can’t tell what that video shows, it just looks like you’re playing a single video. Fwiw I don’t think your problem is Compose-related. I suspect you would have the same issue using Views/XML, until you identified the root of the problem
s
probably, i’ll try building the same thing in xml and see if that works. here’s a better example btw. On clicking the button, you see a video of a road for a quick second. That should be at the top, But it quickly goes under video 3 [the shaky footage of my desk setup
I also tried putting the MediaPlayer() in a Lazy Column and got ^^ same result
for everyone stuck at this, exo player was the problem. https://github.com/fengdai/compose-media use this with TextView surface type to fix ^ this.