Row de chat flexible, ChatFlexBoxLayout , positionne ses éléments en fonction du nombre de lignes que le texte du message a, la largeur du parent, la largeur d'état du message et du message. SubcomposeColumn créée à l'aide de SubComposelayout qui réalise ses enfants sur la base des enfants les plus longs. Ceci est utile pour faire correspondre le message de devis et la longueur du message après le calcul de la position. Ces deux composiables créent ensemble des lignes de messages dynamiques qui positionnent les enfants et positionnent le message, la date du message et l'état du message.
Il y a 3 fichiers d'implémentation à essayer ChatFlexBoxLayout , et SubcomposeColumn est DemoFullChat.kt , DemoChatAndWidth.kt et DemoResizableColumn.kt
| Chat complet | Largeur de chat | Redonnable |
|---|---|---|
![]() | ![]() | ![]() |
Cette disposition mesure et positionne le message, et un autre conteneur qui utilise la date du message ou la date du message + le message reçu comme le font les applications de messagerie.
Il y a 4 conditions possibles pour positionner le message et les statistiques
ChatFlexBoxLayout (
modifier : Modifier = Modifier ,
text : String ,
color : Color = Color . Unspecified ,
fontSize : TextUnit = 16 .sp,
fontStyle : FontStyle ? = null ,
fontWeight : FontWeight ? = null ,
fontFamily : FontFamily ? = null ,
letterSpacing : TextUnit = TextUnit . Unspecified ,
textDecoration : TextDecoration ? = null ,
textAlign : TextAlign ? = null ,
lineHeight : TextUnit = TextUnit . Unspecified ,
overflow : TextOverflow = TextOverflow . Clip ,
softWrap : Boolean = true ,
maxLines : Int = Int . MAX_VALUE ,
messageStat : @Composable () -> Unit ,
onMeasure : (( ChatRowData ) -> Unit ) ? = null
) Étant donné que TextLayout est nécessaire pour obtenir la longueur du texte, la dernière largeur de ligne et d'autres propriétés, il est interne à ce composable, mais les propriétés du composable Text peuvent être définies avec la même chose que Text .
onMeasure renvoie les données de mise en page internes de cette ligne, c'est ainsi que je définis les couleurs différemment dans l'échantillon de largeur de chat . messageStat est composable qui contient du texte de message ou du statut si vous en avez besoin.
ChatFlexBoxLayout (
modifier = Modifier
.background(color, shape = RoundedCornerShape ( 8 .dp))
.padding(start = 2 .dp, top = 2 .dp, end = 4 .dp, bottom = 2 .dp),
text = text,
messageStat = {
MessageTimeText (
modifier = Modifier .wrapContentSize(),
messageTime = messageTime,
messageStatus = messageStatus
)
},
onMeasure = { chatRowData ->
color = when (chatRowData.measuredType) {
0 -> Color . Yellow
1 -> Color . Red
2 -> Color . Green
else -> Color . Magenta
}
}
) Une autre surcharge de ChatFlexBoxLayout prend deux composiables comme arguments quels messages personnalisés peuvent être utilisés à la place de chaîne ou annotée.
@Composable
fun ChatFlexBoxLayout (
modifier : Modifier ,
message : @Composable () -> Unit ,
messageStat : @Composable () -> Unit = {},
chatRowData : ChatRowData ,
onMeasure : (( ChatRowData ) -> Unit ) ? = null
) {
// ...
} Utilisez avec remember { ChatRowData() } pour fournir des statistiques et invoquer measureText(chatRowData, it) pour définir les propriétés de texte sur ces données
val chatRowData = remember { ChatRowData () }
ChatFlexBoxLayout (
modifier = Modifier .padding(
start = 2 .dp,
top = 2 .dp,
end = 8 .dp,
bottom = 2 .dp
),
message = {
Text (
modifier = Modifier .padding(horizontal = 6 .dp, vertical = 4 .dp),
text = text,
fontSize = 16 .sp,
onTextLayout = {
// ️ THIS IS REQUIRED TO MEASURE Text size and get line count
measureText(chatRowData, it)
}
)
},
messageStat = {
MessageTimeText (
modifier = Modifier .wrapContentSize(),
messageTime = messageTime,
messageStatus = messageStatus
)
},
chatRowData = chatRowData
)
} Cette mise en page utilise Sub-Composerlayout pour trouver un enfant le plus long, puis remaser ses enfants et mettre chaque enfant à la largeur maximale. Il y a 2 surcharges de ce composable si vous n'avez besoin d'utiliser que 2 enfants directs que vous pouvez utiliser qui renvoie la taille du composant principal en tant IntSize
fun SubcomposeColumn (
modifier : Modifier = Modifier ,
mainContent : @Composable () -> Unit = {},
dependentContent : @Composable ( IntSize ) -> Unit
) {
.. .
}Cette fonction surchargée convient à la mise en page avec un certain nombre d'enfants
@Composable
fun SubcomposeColumn (
modifier : Modifier = Modifier ,
content : @Composable () -> Unit = {},
) {
SubcomposeLayout (modifier = modifier) { constraints ->
var recompositionIndex = 0
var placeables : List < Placeable > = subcompose(recompositionIndex ++ , content).map {
it.measure(constraints)
}
val maxSize =
placeables.fold( IntSize . Zero ) { currentMax : IntSize , placeable : Placeable ->
IntSize (
width = maxOf(currentMax.width, placeable.width),
height = currentMax.height + placeable.height
)
}
// Remeasure every element using width of longest item as minWidth of Constraint
if ( ! placeables.isNullOrEmpty() && placeables.size > 1 ) {
placeables = subcompose(recompositionIndex, content).map { measurable : Measurable ->
measurable.measure( Constraints (maxSize.width, constraints.maxWidth))
}
}
layout(maxSize.width, maxSize.height) {
var yPos = 0
placeables.forEach { placeable : Placeable ->
placeable.placeRelative( 0 , yPos)
yPos + = placeable.height
}
}
}
}