Flexible Chat Box
1.0.0
靈活的聊天行, ChatFlexBoxLayout ,基於線條消息的數量,將其元素定位為“郵件”文本,父寬度,消息和消息狀態寬度。 SubcomposeColumn是使用子專業人口創建的,該子雜誌是根據最長的孩子重新評估其子女的。這對於在位置計算後匹配報價消息和消息長度很有用。這兩個組合共同創建了定位孩子的動態消息行,以及位置消息,消息日期和消息狀態。
有3個實現文件可以嘗試ChatFlexBoxLayout , SubcomposeColumn是DemoFullChat.kt , DemoChatAndWidth.kt和DemoResizableColumn.kt
| 完整的聊天 | 聊天寬度 | 可解析 |
|---|---|---|
![]() | ![]() | ![]() |
此佈局衡量和位置消息,以及另一個使用消息日期或消息日期 +消息接收狀態(例如消息傳遞應用程序)的容器。
有4個可能的條件來定位消息和統計
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
)由於要獲得文本長度,需要TextLayout ,因此可以在此組合的內部寬度和其他屬性,但可以以與使用Text相同的方式設置Text合併的屬性。
onMeasure返回此行的內部佈局數據,這就是我在聊天寬度樣本中以不同的方式設置顏色的方式。 messageStat是合併的,如果需要,則包含消息文本或狀態。
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
}
}
) ChatFlexBoxLayout的另一個過載需要兩個組合物作為參數,可以使用自定義消息組合代替字符串或註釋串。
@Composable
fun ChatFlexBoxLayout (
modifier : Modifier ,
message : @Composable () -> Unit ,
messageStat : @Composable () -> Unit = {},
chatRowData : ChatRowData ,
onMeasure : (( ChatRowData ) -> Unit ) ? = null
) {
// ...
}與remember { ChatRowData() }一起使用以提供統計信息並Invoke measureText(chatRowData, it)將文本屬性設置為此數據
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
)
}該佈局使用子專輯來查找最長的孩子,然後再生其孩子,並將每個孩子設置為最大寬度。如果您只需要使用直接的2個孩子,則可以使用2個IntSize的超載
fun SubcomposeColumn (
modifier : Modifier = Modifier ,
mainContent : @Composable () -> Unit = {},
dependentContent : @Composable ( IntSize ) -> Unit
) {
.. .
}此超載功能適用於任何數量的孩子的佈局
@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
}
}
}
}