Skip to content

Commit

Permalink
Merge pull request #7 from lemoncloud-io/feature/raine-compose-util
Browse files Browse the repository at this point in the history
compose-util 모듈 업데이트
  • Loading branch information
raine-lemon authored Sep 3, 2024
2 parents c49c240 + 39debf5 commit d46a110
Show file tree
Hide file tree
Showing 9 changed files with 208 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.lemon.core.compose.util
package io.lemon.core.compose.util.modifier

import androidx.compose.foundation.Indication
import androidx.compose.foundation.clickable
Expand Down
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()
}
}
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
)
}

0 comments on commit d46a110

Please sign in to comment.