Skip to content

Commit

Permalink
feat:新增Skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
yangqi1024 committed May 5, 2022
1 parent 85fb2cf commit 55a044f
Show file tree
Hide file tree
Showing 11 changed files with 552 additions and 150 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
- [SearchBar](#SearchBar)
- [Segmented](#Segmented)
- [SelectCity](#SelectCity)
- [Skeleton](#Skeleton)
- [StatefulLayout](#StatefulLayout)
- [Stepper](#Stepper)
- [Steps](#Steps)
Expand Down Expand Up @@ -133,6 +134,12 @@ Name | 截图
--- | ---
SelectCity| <img src="https://cdn.jsdelivr.net/gh/yangqi1024/pic-repo/Cui/selectcity/screenshot.jpg" width="324" height="702">

Skeleton
======================
Name | 截图
--- | ---
Skeleton| <img src="https://cdn.jsdelivr.net/gh/yangqi1024/pic-repo/Cui/skeleton/screenshot.jpg" width="324" height="702">

StatefulLayout
======================
Name | 截图
Expand Down
11 changes: 11 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,17 @@
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="cn.idesign.cui.testclient.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity
android:name="cn.idesign.cui.testclient.skeleton.SkeletonActivity"
android:exported="true"
android:label="Skeleton示例"
android:theme="@style/Theme.CUI">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="cn.idesign.cui.testclient.SAMPLE_CODE" />
</intent-filter>
</activity>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cn.idesign.cui.testclient.skeleton

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.ui.Modifier
import cn.idesign.cui.testclient.ui.theme.CUITestTheme

class SkeletonActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
CUITestTheme {
Scaffold(
topBar = {
TopAppBar(
title = {
Text(
text = "Skeleton示例",
color = MaterialTheme.colors.onPrimary
)
},
backgroundColor = MaterialTheme.colors.primary,
)
},
modifier = Modifier.fillMaxSize()
) {
SkeletonTest()
}
}
}
}
}
115 changes: 115 additions & 0 deletions app/src/main/java/cn/idesign/cui/testclient/skeleton/SkeletonTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package cn.idesign.cui.testclient.skeleton

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.ContentAlpha
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Switch
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import cn.idesign.cui.image.NetworkImage
import cn.idesign.cui.skeleton.Skeleton
import cn.idesign.cui.skeleton.SkeletonImage
import cn.idesign.cui.skeleton.SkeletonParagraph

@Composable
fun SkeletonTest() {
var loading by remember {
mutableStateOf(true)
}
LazyColumn(Modifier.padding(10.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) {
item {
Text(
text = "基础用法",
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 5.dp),
color = MaterialTheme.colors.onSurface.copy(ContentAlpha.high),
style = MaterialTheme.typography.subtitle1.copy(fontWeight = FontWeight.Medium)
)
Skeleton()
}
item {
Text(
text = "复杂组合",
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 5.dp),
color = MaterialTheme.colors.onSurface.copy(ContentAlpha.high),
style = MaterialTheme.typography.subtitle1.copy(fontWeight = FontWeight.Medium)
)
Skeleton(avatar = true, rows = 4)
}

item {
Text(
text = "动画效果",
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 5.dp),
color = MaterialTheme.colors.onSurface.copy(ContentAlpha.high),
style = MaterialTheme.typography.subtitle1.copy(fontWeight = FontWeight.Medium)
)
Skeleton(avatar = true, rows = 4, animated = true)
}
item {
Text(
text = "自定义样式",
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 5.dp),
color = MaterialTheme.colors.onSurface.copy(ContentAlpha.high),
style = MaterialTheme.typography.subtitle1.copy(fontWeight = FontWeight.Medium)
)
Skeleton(defaultContent = {
Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
SkeletonImage(animated = true, modifier = Modifier.size(100.dp))
SkeletonParagraph(animated = true)
}
})
}
item {
Text(
text = "Loading状态",
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 5.dp),
color = MaterialTheme.colors.onSurface.copy(ContentAlpha.high),
style = MaterialTheme.typography.subtitle1.copy(fontWeight = FontWeight.Medium)
)

Column() {
Switch(checked = loading, onCheckedChange = { loading = it })
Skeleton(loading = loading, defaultContent = {
Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
SkeletonImage(animated = true, modifier = Modifier.size(100.dp))
SkeletonParagraph(animated = true)
}
}) {
Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
NetworkImage(
data = "https://image.uisdc.com/wp-content/uploads/2018/12/uisdc-jl-20181224-36.jpg",
modifier = Modifier.size(100.dp)
)
Column {
Text(text = "标题")
Text(text = "这是一个描述")
}
}
}
}
}
}
}
99 changes: 99 additions & 0 deletions cui/src/main/java/cn/idesign/cui/skeleton/Skeleton.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package cn.idesign.cui.skeleton

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp


@Composable
fun Skeleton(
modifier: Modifier = Modifier,
loading: Boolean = true,
animated: Boolean = false,
avatar: Boolean = false,
brushColorList: List<Color> = Skeleton.brushColorList,
rows: Int = 3,
content: (@Composable () -> Unit)? = null,
) {
Skeleton(
modifier = modifier,
loading = loading,
animated = animated,
content = content,
defaultContent = {
Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
if (avatar) {
SkeletonAvatar(
brushColorList = brushColorList,
animated = animated,
)
}
SkeletonParagraph(rows = rows, brushColorList = brushColorList, animated = animated)
}
}
)

}

@Composable
fun Skeleton(
modifier: Modifier = Modifier,
loading: Boolean = true,
animated: Boolean = false,
defaultContent: @Composable () -> Unit,
content: (@Composable () -> Unit)? = null,
) {
// var width by remember {
// mutableStateOf(0)
// }
// val transition = rememberInfiniteTransition()
// val translateAnim by transition.animateFloat(
// initialValue = 0f,
// targetValue = width.toFloat(),
// animationSpec = infiniteRepeatable(
// tween(durationMillis = 1400, easing = FastOutSlowInEasing),
// RepeatMode.Restart
// )
// )
// val color = Color(190, 190, 190).copy(0.2f)
// val shimmerColorShades = listOf(
// color.copy(0.25f),
// color.copy(0.37f),
// color.copy(0.63f)
// )
// val brush = Brush.linearGradient(
// colors = shimmerColorShades,
// start = Offset(0f, 0f),
// end = Offset(translateAnim, 0f)
// )
// Spacer(
// modifier = Modifier
// .fillMaxWidth()
// .size(250.dp)
// .onSizeChanged { size ->
// width = size.width * 4
// }
// .background(brush = brush)
// )

// val skeletonScopeImpl = SkeletonScopeImpl().apply(defaultContent)
if (loading) {
defaultContent()
} else {
content?.invoke()
}
}


object Skeleton {
val color = Color(190, 190, 190).copy(0.2f)
val iconColor = Color(0xffdcdde0)
val brushColorList: List<Color> = listOf(
color.copy(0.25f),
color.copy(0.37f),
color.copy(0.63f)
)
}
70 changes: 70 additions & 0 deletions cui/src/main/java/cn/idesign/cui/skeleton/SkeletonAvatar.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package cn.idesign.cui.skeleton

import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.unit.dp

@Composable
fun SkeletonAvatar(
modifier: Modifier = Modifier,
animated: Boolean = false,
brushColorList: List<Color> = Skeleton.brushColorList,
) {
if (animated) {
var width by remember {
mutableStateOf(0)
}
val transition = rememberInfiniteTransition()
val translateAnim by transition.animateFloat(
initialValue = 0f,
targetValue = width.toFloat(),
animationSpec = infiniteRepeatable(
tween(durationMillis = 1400, easing = LinearEasing),
RepeatMode.Restart
)
)
val brush = Brush.linearGradient(
colors = brushColorList,
start = Offset(0f, 0f),
end = Offset(translateAnim, 0f)
)
Box(
modifier = Modifier
.size(40.dp)
.onSizeChanged { size ->
width = size.width * 4
}
.clip(CircleShape)
.background(brush = brush)
.then(modifier)
)
} else {
Box(
modifier = Modifier
.size(40.dp)
.clip(CircleShape)
.background(Skeleton.color)
.then(modifier)
)
}

}
Loading

0 comments on commit 55a044f

Please sign in to comment.