improve call participants layout

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
Marcel Hibbe 2025-05-06 14:30:45 +02:00
parent 42a8afded8
commit aacc013485
No known key found for this signature in database
GPG Key ID: C793F8B59F43CE7B
3 changed files with 150 additions and 41 deletions

View File

@ -956,27 +956,10 @@ class CallActivity : CallBaseActivity() {
private fun initGrid() {
Log.d(TAG, "initGrid")
val participantsInGrid = participantUiStates.size
val columns = when {
resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT -> {
if (participantsInGrid > 2) GRID_MAX_COLUMN_COUNT_PORTRAIT else GRID_MIN_COLUMN_COUNT_PORTRAIT
}
else -> {
if (participantsInGrid > 2) {
GRID_MAX_COLUMN_COUNT_LANDSCAPE
} else if (participantsInGrid > 1) {
GRID_MIN_GROUP_COLUMN_COUNT_LANDSCAPE
} else {
GRID_MIN_COLUMN_COUNT_LANDSCAPE
}
}
}
binding!!.composeParticipantGrid.setContent {
MaterialTheme {
ParticipantGrid(
participants = participantUiStates.toList(),
columns = columns
participants = participantUiStates.toList()
) {
animateCallControls(true, 0)
}

View File

@ -7,36 +7,159 @@
package com.nextcloud.talk.call.components
import android.content.res.Configuration
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
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.padding
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.nextcloud.talk.call.ParticipantUiState
@Composable
fun ParticipantGrid(
participants: List<ParticipantUiState>,
columns: Int = 2,
modifier: Modifier = Modifier,
onClick: () -> Unit
) {
LazyVerticalGrid(
columns = GridCells.Fixed(columns),
modifier = modifier
.fillMaxSize()
.clickable { onClick() },
contentPadding = PaddingValues(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
items(participants, key = { it.sessionKey }) { participant ->
ParticipantTile(participant)
fun ParticipantGrid(modifier: Modifier = Modifier, participants: List<ParticipantUiState>, onClick: () -> Unit) {
val configuration = LocalConfiguration.current
val isPortrait = configuration.orientation == Configuration.ORIENTATION_PORTRAIT
when (participants.size) {
0 -> {}
1 -> {
Box(
modifier = Modifier
.fillMaxSize()
) {
ParticipantTile(
participant = participants[0],
modifier = Modifier
.fillMaxSize()
.clickable { onClick() }
)
}
}
2, 3 -> {
if (isPortrait) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(vertical = 4.dp)
.clickable { onClick() },
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
participants.forEach {
ParticipantTile(
participant = it,
modifier = Modifier
.weight(1f)
.fillMaxWidth()
)
}
}
} else {
Row(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 4.dp)
.clickable { onClick() },
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
participants.forEach {
ParticipantTile(
participant = it,
modifier = Modifier
.weight(1f)
.fillMaxHeight()
)
}
}
}
}
else -> {
LazyVerticalGrid(
columns = GridCells.Fixed(if (isPortrait) 2 else 3),
modifier = Modifier
.fillMaxSize()
.padding(8.dp)
.clickable { onClick() },
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
items(participants) { participant ->
ParticipantTile(
participant = participant,
modifier = Modifier
.fillMaxWidth()
.aspectRatio(1.5f)
)
}
}
}
}
}
const val numberOfParticipants = 4
@Preview(
showBackground = false
)
@Composable
fun ParticipantGridPreview() {
ParticipantGrid(
participants = getTestParticipants(numberOfParticipants)
) {}
}
@Preview(
showBackground = false,
heightDp = 902,
widthDp = 434
)
@Composable
fun ParticipantGridPreviewPortrait2() {
ParticipantGrid(
participants = getTestParticipants(numberOfParticipants)
) {}
}
@Preview(
showBackground = false,
heightDp = 360,
widthDp = 800
)
@Composable
fun ParticipantGridPreviewLandscape1() {
ParticipantGrid(
participants = getTestParticipants(numberOfParticipants)
) {}
}
fun getTestParticipants(numberOfParticipants: Int): List<ParticipantUiState> {
val participantList = mutableListOf<ParticipantUiState>()
for (i: Int in 1..numberOfParticipants) {
val participant = ParticipantUiState(
sessionKey = i.toString(),
nick = "testuser$i",
isConnected = true,
isAudioEnabled = if (i == 3) true else false,
isStreamEnabled = true,
raisedHand = true,
avatarUrl = "",
surfaceViewRenderer = null
)
participantList.add(participant)
}
return participantList
}

View File

@ -9,7 +9,7 @@ package com.nextcloud.talk.call.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
@ -29,10 +29,9 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.call.ParticipantUiState
@Composable
fun ParticipantTile(participant: ParticipantUiState) {
fun ParticipantTile(participant: ParticipantUiState, modifier: Modifier = Modifier) {
Box(
modifier = Modifier
.aspectRatio(3f / 4f)
modifier = modifier
.clip(RoundedCornerShape(12.dp))
.background(Color.DarkGray)
) {
@ -97,5 +96,9 @@ fun ParticipantTilePreview() {
avatarUrl = "",
surfaceViewRenderer = null
)
ParticipantTile(participant)
ParticipantTile(
participant = participant,
modifier = Modifier
.fillMaxWidth()
)
}