feat: Compose Widgets

This commit is contained in:
HuanCheng65 2023-07-13 18:34:13 +08:00
parent 9be00b177a
commit f1b5c083ef
No known key found for this signature in database
GPG Key ID: 5EC9DD60A32C7360
9 changed files with 193 additions and 44 deletions

View File

@ -132,8 +132,6 @@ import kotlinx.coroutines.launch
import kotlin.math.max
import kotlin.math.min
private val TabWidth = 100.dp
fun getSortType(
context: Context,
forumName: String

View File

@ -126,8 +126,8 @@ fun HotPage(
item(key = "TopicList") {
VerticalGrid(
column = 2,
horizontalArrangement = Arrangement.spacedBy(16.dp),
modifier = Modifier.padding(horizontal = 16.dp)
modifier = Modifier.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
itemsIndexed(
items = topicList,

View File

@ -107,8 +107,8 @@ fun Dislike(
bottom.linkTo(parent.bottom)
}
.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.spacedBy(4.dp),
verticalArrangement = Arrangement.spacedBy(4.dp),
horizontalArrangement = Arrangement.spacedBy(4.dp),
) {
items(
items = dislikeResource,

View File

@ -60,6 +60,7 @@ import com.huanchengfly.tieba.post.ui.page.destinations.SettingsPageDestination
import com.huanchengfly.tieba.post.ui.page.destinations.ThreadStorePageDestination
import com.huanchengfly.tieba.post.ui.widgets.compose.Avatar
import com.huanchengfly.tieba.post.ui.widgets.compose.HorizontalDivider
import com.huanchengfly.tieba.post.ui.widgets.compose.ListMenuItem
import com.huanchengfly.tieba.post.ui.widgets.compose.Sizes
import com.huanchengfly.tieba.post.ui.widgets.compose.Switch
import com.huanchengfly.tieba.post.ui.widgets.compose.VerticalDivider
@ -377,36 +378,3 @@ fun UserPage(
}
}
}
@Composable
private fun ListMenuItem(
icon: ImageVector,
text: String,
modifier: Modifier = Modifier,
onClick: (() -> Unit)? = null,
customContent: @Composable (RowScope.() -> Unit)? = null,
) {
val menuModifier = if (onClick != null) {
Modifier.clickable(onClick = onClick)
} else {
Modifier
}
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.then(menuModifier)
.padding(horizontal = 16.dp, vertical = 12.dp),
) {
Icon(imageVector = icon, contentDescription = text, tint = ExtendedTheme.colors.accent)
Spacer(modifier = Modifier.width(16.dp))
Text(
text = text,
fontSize = 14.sp,
fontWeight = FontWeight.Bold,
maxLines = 1,
modifier = Modifier.weight(1f),
)
Spacer(modifier = Modifier.width(16.dp))
customContent?.invoke(this)
}
}

View File

@ -108,6 +108,7 @@ private fun calcRows(column: Int, items: List<GridScopeImpl.Item>): List<List<Gr
fun VerticalGrid(
column: Int,
modifier: Modifier = Modifier,
rowModifier: Modifier = Modifier,
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
content: GridScope.() -> Unit
@ -118,7 +119,8 @@ fun VerticalGrid(
rows.forEach {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = horizontalArrangement
horizontalArrangement = horizontalArrangement,
modifier = rowModifier
) {
it.forEach {
Box(

View File

@ -0,0 +1,53 @@
package com.huanchengfly.tieba.post.ui.widgets.compose
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme
@Composable
fun ListMenuItem(
icon: ImageVector,
text: String,
modifier: Modifier = Modifier,
iconColor: Color = ExtendedTheme.colors.accent,
onClick: (() -> Unit)? = null,
customContent: @Composable (RowScope.() -> Unit)? = null,
) {
val menuModifier = if (onClick != null) {
Modifier.clickable(onClick = onClick)
} else {
Modifier
}
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.then(menuModifier)
.padding(horizontal = 16.dp, vertical = 12.dp),
) {
Icon(imageVector = icon, contentDescription = text, tint = iconColor)
Spacer(modifier = Modifier.width(16.dp))
Text(
text = text,
fontSize = 14.sp,
fontWeight = FontWeight.Bold,
maxLines = 1,
modifier = Modifier.weight(1f),
)
Spacer(modifier = Modifier.width(16.dp))
customContent?.invoke(this)
}
}

View File

@ -1,5 +1,6 @@
package com.huanchengfly.tieba.post.ui.widgets.compose
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.material.Icon
@ -10,6 +11,7 @@ import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.AccountCircle
import androidx.compose.material.icons.rounded.Link
import androidx.compose.material.icons.rounded.SlowMotionVideo
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
@ -17,6 +19,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.takeOrElse
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.ExperimentalTextApi
import androidx.compose.ui.text.Placeholder
import androidx.compose.ui.text.PlaceholderVerticalAlign
import androidx.compose.ui.text.TextLayoutResult
@ -24,6 +27,7 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
@ -38,7 +42,6 @@ import com.huanchengfly.tieba.post.utils.EmoticonManager
import com.huanchengfly.tieba.post.utils.EmoticonUtil.emoticonString
import com.huanchengfly.tieba.post.utils.getEmoticonHeightPx
@Composable
fun EmoticonText(
text: String,
@ -100,6 +103,7 @@ fun EmoticonText(
softWrap: Boolean = true,
maxLines: Int = Int.MAX_VALUE,
minLines: Int = 1,
emoticonSize: Float = 0.9f,
inlineContent: Map<String, InlineTextContent> = emptyMap(),
onTextLayout: (TextLayoutResult) -> Unit = {},
style: TextStyle = LocalTextStyle.current
@ -122,7 +126,7 @@ fun EmoticonText(
letterSpacing = letterSpacing
)
)
val sizePx = getEmoticonHeightPx(mergedStyle)
val sizePx = getEmoticonHeightPx(mergedStyle) * emoticonSize
val emoticonInlineContent =
remember(sizePx) { EmoticonManager.getEmoticonInlineContent(sizePx) }
IconText(
@ -203,7 +207,22 @@ fun IconText(
Icons.Rounded.Link,
contentDescription = stringResource(id = R.string.link),
modifier = Modifier.size(sizeDp),
tint = ExtendedTheme.colors.accent,
tint = ExtendedTheme.colors.primary,
)
}
),
"video_icon" to InlineTextContent(
placeholder = Placeholder(
width = sizeSp,
height = sizeSp,
placeholderVerticalAlign = PlaceholderVerticalAlign.TextCenter
),
children = {
Icon(
Icons.Rounded.SlowMotionVideo,
contentDescription = stringResource(id = R.string.desc_video),
modifier = Modifier.size(sizeDp),
tint = ExtendedTheme.colors.primary,
)
}
),
@ -218,7 +237,7 @@ fun IconText(
Icons.Rounded.AccountCircle,
contentDescription = stringResource(id = R.string.user),
modifier = Modifier.size(sizeDp),
tint = ExtendedTheme.colors.accent,
tint = ExtendedTheme.colors.primary,
)
}
),
@ -245,3 +264,60 @@ fun IconText(
style
)
}
/**
* A [Text] composable that supports setting its minimum width to width of the specified number of Chinese characters
*/
@OptIn(ExperimentalTextApi::class)
@Composable
fun TextWithMinWidth(
text: String,
modifier: Modifier = Modifier,
color: Color = Color.Unspecified,
fontSize: TextUnit = TextUnit.Unspecified,
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,
minLines: Int = 1,
minLength: Int = 0,
onTextLayout: (TextLayoutResult) -> Unit = {},
style: TextStyle = LocalTextStyle.current,
) {
val textMeasurer = rememberTextMeasurer()
val singleChar = stringResource(id = R.string.single_chinese_char)
val singleCharWidth = remember(style) {
textMeasurer.measure(
text = singleChar,
style = style
).size.width.pxToDp().dp
}
Text(
text = text,
modifier = Modifier
.defaultMinSize(minWidth = singleCharWidth * minLength)
.then(modifier),
color = color,
fontSize = fontSize,
fontStyle = fontStyle,
fontWeight = fontWeight,
fontFamily = fontFamily,
letterSpacing = letterSpacing,
textDecoration = textDecoration,
textAlign = textAlign,
lineHeight = lineHeight,
overflow = overflow,
softWrap = softWrap,
maxLines = maxLines,
minLines = minLines,
onTextLayout = onTextLayout,
style = style
)
}

View File

@ -231,6 +231,58 @@ fun TitleCentredToolbar(
}
}
@Composable
fun TitleCentredToolbar(
title: @Composable () -> Unit,
modifier: Modifier = Modifier,
navigationIcon: @Composable (() -> Unit)? = null,
actions: @Composable (RowScope.() -> Unit) = {},
content: @Composable (ColumnScope.() -> Unit) = {},
) {
Column(
modifier = Modifier
.background(ExtendedTheme.colors.topBar)
.then(modifier)
) {
TopAppBar(
backgroundColor = ExtendedTheme.colors.topBar,
contentColor = ExtendedTheme.colors.onTopBar,
elevation = 0.dp
) {
Box(modifier = Modifier.fillMaxSize()) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxHeight()
) {
navigationIcon?.invoke()
Spacer(modifier = Modifier.weight(1f))
actions()
}
Row(
Modifier
.fillMaxHeight()
.align(Alignment.Center),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
title()
}
}
}
Column(
modifier = Modifier
.fillMaxWidth()
.background(color = ExtendedTheme.colors.topBar)
) {
content()
}
}
}
@Composable
fun Toolbar(
title: String,

View File

@ -118,7 +118,7 @@ object EmoticonManager {
private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.IO)
fun getEmoticonInlineContent(
sizePx: Int
sizePx: Float
): Map<String, InlineTextContent> {
return emoticonIds.associate { id ->
"Emoticon#$id" to InlineTextContent(