11package co.yml.coreui.core.ui.ytag
22
33import android.R
4+ import android.annotation.SuppressLint
5+ import android.util.Log
6+ import androidx.compose.animation.AnimatedVisibility
7+ import androidx.compose.animation.core.*
8+ import androidx.compose.animation.fadeIn
9+ import androidx.compose.animation.fadeOut
410import androidx.compose.foundation.background
511import androidx.compose.foundation.border
612import androidx.compose.foundation.clickable
@@ -11,8 +17,9 @@ import androidx.compose.material3.Icon
1117import androidx.compose.material3.IconButton
1218import androidx.compose.material3.Surface
1319import androidx.compose.material3.Text
14- import androidx.compose.runtime.Composable
20+ import androidx.compose.runtime.*
1521import androidx.compose.ui.Modifier
22+ import androidx.compose.ui.draw.alpha
1623import androidx.compose.ui.graphics.Color
1724import androidx.compose.ui.graphics.RectangleShape
1825import androidx.compose.ui.platform.testTag
@@ -25,6 +32,7 @@ import androidx.compose.ui.unit.dp
2532import androidx.compose.ui.unit.sp
2633import androidx.constraintlayout.compose.ConstraintLayout
2734import androidx.constraintlayout.compose.Dimension
35+ import co.yml.coreui.core.ui.ytag.model.TagViewData
2836import co.yml.coreui.core.ui.ytag.model.TagViewModifiers
2937
3038/* *
@@ -36,105 +44,151 @@ import co.yml.coreui.core.ui.ytag.model.TagViewModifiers
3644 * @param enabled controls the enabled state of the TagView
3745 * @param tagViewModifiers collection of modifier elements that decorate or add behavior to TagView elements
3846 */
47+ @SuppressLint(" UnrememberedMutableState" )
3948@Composable
4049fun TagView (
4150 text : String ,
42- leadingIcon : @Composable ((enable : Boolean ) -> Unit )? = null,
43- trailingIcon : @Composable ((enable : Boolean ) -> Unit )? = null,
51+ leadingIcon : @Composable ((tagViewData : TagViewData ) -> Unit )? = null,
52+ trailingIcon : @Composable ((tagViewData : TagViewData ) -> Unit )? = null,
4453 enabled : Boolean = true,
4554 tagViewModifiers : TagViewModifiers = TagViewModifiers .Builder ().build(),
46- overFlowText : String = "",
47- onClick : () -> Unit = {}
55+ overFlowText : String = ""
4856) {
57+ val tagViewData = TagViewData (
58+ text = text,
59+ leadingIcon = leadingIcon,
60+ trailingIcon = trailingIcon,
61+ enabled = enabled,
62+ tagViewModifiers = tagViewModifiers,
63+ overFlowText = { overFlowText })
64+
65+ // used for visibility animation
66+ val state = remember {
67+ MutableTransitionState (false ).apply {
68+ targetState = true
69+ }
70+ }
71+
72+ // used for alpha animation
73+ var tagVisible by remember {
74+ mutableStateOf(true )
75+ }
76+
77+ val tagAlpha: Float by animateFloatAsState(
78+ targetValue = if (tagVisible) 1f else 0f ,
79+ animationSpec = tween(
80+ durationMillis = tagViewModifiers.alphaAnimation.durationMillis,
81+ easing = LinearEasing ,
82+ ),
83+ finishedListener = {
84+ // execute once remove animation is performed
85+ tagViewModifiers.onClick.invoke(tagViewData)
86+ }
87+ )
88+
4989 with (tagViewModifiers) {
50- Surface (
51- shadowElevation = shadowElevation,
52- tonalElevation = tonalElevation,
53- shape = shape,
54- modifier = Modifier
55- .testTag(" tag_view" )
56- .width(width = width ? : Dp .Unspecified )
57- .height(height = height)
90+ AnimatedVisibility (
91+ visibleState = state,
92+ enter = fadeIn(animationSpec = tween(alphaAnimation.durationMillis)),
93+ exit = fadeOut(animationSpec = tween(alphaAnimation.durationMillis))
5894 ) {
59- ConstraintLayout (
95+ Surface (
96+ shadowElevation = shadowElevation,
97+ tonalElevation = tonalElevation,
98+ shape = shape,
6099 modifier = Modifier
61- .width(width = width ? : Dp .Unspecified )
62- .height(height)
63- .run {
64- if (enableBorder) {
65- border(
66- width = borderWidth,
67- color = borderColor,
68- shape = shape
69- )
70- } else {
71- background(color = backgroundColor, shape = shape)
100+ .testTag(" tag_view" )
101+ .width(width = width)
102+ .height(height = height)
103+ .alpha(tagAlpha)
104+ ) {
105+ ConstraintLayout (
106+ modifier = Modifier
107+
108+ .width(width = width)
109+ .height(height)
110+ .run {
111+ if (enableBorder) {
112+ border(
113+ width = borderWidth,
114+ color = borderColor,
115+ shape = shape
116+ )
117+ } else {
118+ background(color = backgroundColor, shape = shape)
119+ }
72120 }
73- }
74- .clickable {
75- if (enabled) {
76- onClick.invoke()
77- tagViewModifiers.onClick.invoke()
121+ .clickable {
122+ if (enabled) {
123+ if (tagViewModifiers.alphaAnimation.enabled){
124+ tagVisible = false
125+ state.targetState = false
126+ }else {
127+ tagViewModifiers.onClick.invoke(tagViewData)
128+ }
129+ }
78130 }
79- }
80- .defaultMinSize(minWidth = minWidth, minHeight = minHeight)
81- .padding(containerPaddingValues)
82- .background(
83- color = backgroundColor,
84- shape = shape
85- )
86- ) {
87- val (leading_icon, text_view, trailing_icon) = createRefs()
131+ .defaultMinSize(minWidth = minWidth, minHeight = minHeight)
132+ .padding(containerPaddingValues)
133+ .background(
134+ color = backgroundColor,
135+ shape = shape
136+ )
137+
88138
89- Box (modifier = Modifier .constrainAs(leading_icon) {
90- start.linkTo(parent.start)
91- top.linkTo(parent.top)
92- bottom.linkTo(parent.bottom)
93- }
94139 ) {
95- leadingIcon?.invoke(enabled)
96- }
140+ val (leading_icon, text_view, trailing_icon) = createRefs()
97141
98- Text (
99- text = overFlowText.ifEmpty { text },
100- color = textColor,
101- fontSize = fontSize,
102- fontWeight = fontWeight,
103- fontFamily = fontFamily,
104- fontStyle = fontStyle,
105- letterSpacing = letterSpacing,
106- modifier = Modifier
107- .constrainAs(text_view) {
108- start.linkTo(leading_icon.end)
109- end.linkTo(trailing_icon.start)
142+ Box (modifier = Modifier
143+ .constrainAs(leading_icon) {
144+ start.linkTo(parent.start)
110145 top.linkTo(parent.top)
111146 bottom.linkTo(parent.bottom)
112- width = Dimension .fillToConstraints
113147 }
114- .padding(
115- textPadding
116- )
117- .semantics {
118- this .contentDescription = semantics
119- },
120- style = style,
121- textDecoration = textDecoration,
122- textAlign = textAlign,
123- lineHeight = lineHeight,
124- overflow = overflow,
125- softWrap = softWrap,
126- maxLines = maxLines,
127- onTextLayout = onTextLayout
128- )
129- Box (modifier = Modifier .constrainAs(trailing_icon) {
130- end.linkTo(parent.end)
131- top.linkTo(parent.top)
132- bottom.linkTo(parent.bottom)
133- }
134- ) {
135- trailingIcon?.invoke(enabled)
136- }
148+ ) {
149+ leadingIcon?.invoke(tagViewData)
150+ }
137151
152+ Text (
153+ text = overFlowText.ifEmpty { text },
154+ color = textColor,
155+ fontSize = fontSize,
156+ fontWeight = fontWeight,
157+ fontFamily = fontFamily,
158+ fontStyle = fontStyle,
159+ letterSpacing = letterSpacing,
160+ modifier = Modifier
161+ .constrainAs(text_view) {
162+ start.linkTo(leading_icon.end)
163+ end.linkTo(trailing_icon.start)
164+ top.linkTo(parent.top)
165+ bottom.linkTo(parent.bottom)
166+ width = Dimension .fillToConstraints
167+ }
168+ .padding(
169+ textPadding
170+ )
171+ .semantics {
172+ this .contentDescription = semantics
173+ },
174+ style = style,
175+ textDecoration = textDecoration,
176+ textAlign = textAlign,
177+ lineHeight = lineHeight,
178+ overflow = overflow,
179+ softWrap = softWrap,
180+ maxLines = maxLines,
181+ onTextLayout = onTextLayout
182+ )
183+ Box (modifier = Modifier .constrainAs(trailing_icon) {
184+ end.linkTo(parent.end)
185+ top.linkTo(parent.top)
186+ bottom.linkTo(parent.bottom)
187+ }
188+ ) {
189+ trailingIcon?.invoke(tagViewData)
190+ }
191+ }
138192 }
139193 }
140194 }
0 commit comments