-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from lemoncloud-io/feature/raine-compose-util
compose-util 모듈 업데이트
- Loading branch information
Showing
9 changed files
with
208 additions
and
1 deletion.
There are no files selected for viewing
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion
2
...va/io/lemon/core/compose/util/Modifier.kt → ...n/core/compose/util/modifier/Clickable.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 104 additions & 0 deletions
104
compose-util/src/main/java/io/lemon/core/compose/util/modifier/Shadow.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package io.lemon.core.compose.util.modifier | ||
|
||
import android.graphics.BlurMaskFilter | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.draw.drawBehind | ||
import androidx.compose.ui.geometry.Size | ||
import androidx.compose.ui.graphics.Color | ||
import androidx.compose.ui.graphics.Paint | ||
import androidx.compose.ui.graphics.Shape | ||
import androidx.compose.ui.graphics.drawOutline | ||
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas | ||
import androidx.compose.ui.unit.Dp | ||
import androidx.compose.ui.unit.DpOffset | ||
import androidx.compose.ui.unit.dp | ||
|
||
/** | ||
* @param shape 그림자에 적용할 모양 | ||
* @param color 그림자 색상 | ||
* @param offset 그림자의 위치 | ||
* @param blur 그림자 흐림 효과 (번짐의 정도) | ||
* @param spread 그림자의 확산효과이며, 그림자의 크기; | ||
* 음수로 할 경우 그림자의 크기가 기존 도형보다 줄어듭니다. | ||
*/ | ||
fun Modifier.dropShadow( | ||
shape: Shape, | ||
color: Color, | ||
offset: DpOffset, | ||
blur: Dp = 1.dp, | ||
spread: Dp = 0.dp | ||
) = drawBehind { | ||
|
||
drawIntoCanvas { canvas -> | ||
canvas.save() | ||
canvas.translate(dx = offset.x.toPx(), dy = offset.y.toPx()) // 캔버스 위치 이동 | ||
canvas.drawOutline( | ||
outline = shape.createOutline( | ||
size = Size( | ||
width = size.width + spread.toPx(), | ||
height = size.height + spread.toPx() | ||
), | ||
layoutDirection = layoutDirection, | ||
density = this | ||
), // 그림자 사이즈 구성 | ||
paint = Paint().apply { | ||
this.color = color | ||
blur.toPx().takeIf { it > 0f }?.let { radius -> | ||
asFrameworkPaint().apply { | ||
maskFilter = BlurMaskFilter( | ||
/* radius = */ radius, | ||
/* style = */ BlurMaskFilter.Blur.NORMAL | ||
) | ||
} | ||
} | ||
} // 그림자 스타일 구성 | ||
) // 그림자 생성 | ||
canvas.restore() | ||
} | ||
} | ||
|
||
/** | ||
* @param shape 그림자에 적용할 모양 | ||
* @param color 그림자 색상 | ||
* @param yOffset 그림자의 y 오프셋 | ||
* @param xOffset 그림자의 x 오프셋 | ||
* @param blur 그림자 흐림 효과 (번짐의 정도) | ||
* @param spread 그림자의 확산효과이며, 그림자의 크기; | ||
* 음수로 할 경우 그림자의 크기가 기존 도형보다 줄어듭니다. | ||
*/ | ||
fun Modifier.dropShadow( | ||
shape: Shape, | ||
color: Color, | ||
yOffset: Dp = 0.dp, | ||
xOffset: Dp = 0.dp, | ||
blur: Dp = 1.dp, | ||
spread: Dp = 0.dp | ||
) = drawBehind { | ||
|
||
drawIntoCanvas { canvas -> | ||
canvas.save() | ||
canvas.translate(dx = xOffset.toPx(), dy = yOffset.toPx()) // 캔버스 위치 이동 | ||
canvas.drawOutline( | ||
outline = shape.createOutline( | ||
size = Size( | ||
width = size.width + spread.toPx(), | ||
height = size.height + spread.toPx() | ||
), | ||
layoutDirection = layoutDirection, | ||
density = this | ||
), // 그림자 사이즈 구성 | ||
paint = Paint().apply { | ||
this.color = color | ||
blur.toPx().takeIf { it > 0f }?.let { radius -> | ||
asFrameworkPaint().apply { | ||
maskFilter = BlurMaskFilter( | ||
/* radius = */ radius, | ||
/* style = */ BlurMaskFilter.Blur.NORMAL | ||
) | ||
} | ||
} | ||
} // 그림자 스타일 구성 | ||
) // 그림자 생성 | ||
canvas.restore() | ||
} | ||
} |
103 changes: 103 additions & 0 deletions
103
compose-util/src/main/java/io/lemon/core/compose/util/modifier/Toggleable.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package io.lemon.core.compose.util.modifier | ||
|
||
import androidx.compose.foundation.Indication | ||
import androidx.compose.foundation.interaction.MutableInteractionSource | ||
import androidx.compose.foundation.selection.toggleable | ||
import androidx.compose.runtime.getValue | ||
import androidx.compose.runtime.mutableLongStateOf | ||
import androidx.compose.runtime.remember | ||
import androidx.compose.runtime.rememberCoroutineScope | ||
import androidx.compose.runtime.setValue | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.composed | ||
import androidx.compose.ui.semantics.Role | ||
import kotlinx.coroutines.CoroutineDispatcher | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.launch | ||
|
||
/** | ||
* Toggle interaction 이 연속적으로 발생하는 것을 방지하는 확장자 | ||
*/ | ||
fun Modifier.throttleToggleable( | ||
value: Boolean, | ||
onValueChange: (Boolean) -> Unit, | ||
enabled: Boolean = true, | ||
role: Role? = null, | ||
coroutineDispatcher: CoroutineDispatcher = Dispatchers.Main, | ||
throttleTime: Long = 250L, | ||
) = composed { | ||
val coroutineScope = rememberCoroutineScope { coroutineDispatcher } | ||
var lastEmissionTime: Long by remember { mutableLongStateOf(0L) } | ||
|
||
toggleable( | ||
value = value, | ||
onValueChange = { | ||
val currentTime = System.currentTimeMillis() | ||
if (currentTime - lastEmissionTime >= throttleTime) { | ||
coroutineScope.launch { | ||
lastEmissionTime = currentTime | ||
onValueChange(it) | ||
} | ||
} | ||
lastEmissionTime = currentTime | ||
}, | ||
enabled = enabled, | ||
role = role, | ||
) | ||
} | ||
|
||
/** | ||
* Toggle interaction 이 연속적으로 발생하는 것을 방지하는 확장자 | ||
*/ | ||
fun Modifier.throttleToggleable( | ||
value: Boolean, | ||
onValueChange: (Boolean) -> Unit, | ||
interactionSource: MutableInteractionSource = MutableInteractionSource(), | ||
indication: Indication? = null, | ||
enabled: Boolean = true, | ||
role: Role? = null, | ||
coroutineDispatcher: CoroutineDispatcher = Dispatchers.Main, | ||
throttleTime: Long = 250L, | ||
) = composed { | ||
val coroutineScope = rememberCoroutineScope { coroutineDispatcher } | ||
var lastEmissionTime: Long by remember { mutableLongStateOf(0L) } | ||
|
||
noRippleToggleable( | ||
value = value, | ||
onValueChange = { | ||
val currentTime = System.currentTimeMillis() | ||
if (currentTime - lastEmissionTime >= throttleTime) { | ||
coroutineScope.launch { | ||
lastEmissionTime = currentTime | ||
onValueChange(it) | ||
} | ||
} | ||
lastEmissionTime = currentTime | ||
}, | ||
interactionSource = remember { interactionSource }, | ||
indication = indication, | ||
enabled = enabled, | ||
role = role | ||
) | ||
} | ||
|
||
/** | ||
* Toggle interaction 중 발생하는 시각 이펙트를 제거하는 확장자 | ||
*/ | ||
fun Modifier.noRippleToggleable( | ||
value: Boolean, | ||
onValueChange: (Boolean) -> Unit, | ||
interactionSource: MutableInteractionSource = MutableInteractionSource(), | ||
indication: Indication? = null, | ||
enabled: Boolean = true, | ||
role: Role? = null, | ||
) = composed { | ||
toggleable( | ||
value = value, | ||
interactionSource = remember { interactionSource }, | ||
indication = indication, | ||
enabled = enabled, | ||
onValueChange = onValueChange, | ||
role = role | ||
) | ||
} |