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() { private fun initGrid() {
Log.d(TAG, "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 { binding!!.composeParticipantGrid.setContent {
MaterialTheme { MaterialTheme {
ParticipantGrid( ParticipantGrid(
participants = participantUiStates.toList(), participants = participantUiStates.toList()
columns = columns
) { ) {
animateCallControls(true, 0) animateCallControls(true, 0)
} }

View File

@ -7,36 +7,159 @@
package com.nextcloud.talk.call.components package com.nextcloud.talk.call.components
import android.content.res.Configuration
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement 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.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.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.lazy.grid.items
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier 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 androidx.compose.ui.unit.dp
import com.nextcloud.talk.call.ParticipantUiState import com.nextcloud.talk.call.ParticipantUiState
@Composable @Composable
fun ParticipantGrid( fun ParticipantGrid(modifier: Modifier = Modifier, participants: List<ParticipantUiState>, onClick: () -> Unit) {
participants: List<ParticipantUiState>, val configuration = LocalConfiguration.current
columns: Int = 2, val isPortrait = configuration.orientation == Configuration.ORIENTATION_PORTRAIT
modifier: Modifier = Modifier,
onClick: () -> Unit when (participants.size) {
) { 0 -> {}
LazyVerticalGrid( 1 -> {
columns = GridCells.Fixed(columns), Box(
modifier = modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.clickable { onClick() }, ) {
contentPadding = PaddingValues(8.dp), ParticipantTile(
verticalArrangement = Arrangement.spacedBy(8.dp), participant = participants[0],
horizontalArrangement = Arrangement.spacedBy(8.dp) modifier = Modifier
) { .fillMaxSize()
items(participants, key = { it.sessionKey }) { participant -> .clickable { onClick() }
ParticipantTile(participant) )
}
}
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.background
import androidx.compose.foundation.layout.Box 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.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
@ -29,10 +29,9 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.call.ParticipantUiState import com.nextcloud.talk.call.ParticipantUiState
@Composable @Composable
fun ParticipantTile(participant: ParticipantUiState) { fun ParticipantTile(participant: ParticipantUiState, modifier: Modifier = Modifier) {
Box( Box(
modifier = Modifier modifier = modifier
.aspectRatio(3f / 4f)
.clip(RoundedCornerShape(12.dp)) .clip(RoundedCornerShape(12.dp))
.background(Color.DarkGray) .background(Color.DarkGray)
) { ) {
@ -97,5 +96,9 @@ fun ParticipantTilePreview() {
avatarUrl = "", avatarUrl = "",
surfaceViewRenderer = null surfaceViewRenderer = null
) )
ParticipantTile(participant) ParticipantTile(
participant = participant,
modifier = Modifier
.fillMaxWidth()
)
} }