Benoit Marty
6 months ago
1 changed files with 0 additions and 107 deletions
@ -1,107 +0,0 @@
@@ -1,107 +0,0 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package io.element.android.libraries.designsystem.modifiers |
||||
|
||||
import androidx.compose.animation.core.animateFloat |
||||
import androidx.compose.animation.core.updateTransition |
||||
import androidx.compose.runtime.State |
||||
import androidx.compose.ui.Modifier |
||||
import androidx.compose.ui.composed |
||||
import androidx.compose.ui.draw.drawWithCache |
||||
import androidx.compose.ui.geometry.Offset |
||||
import androidx.compose.ui.geometry.Rect |
||||
import androidx.compose.ui.geometry.Size |
||||
import androidx.compose.ui.graphics.Color |
||||
import androidx.compose.ui.graphics.Path |
||||
import androidx.compose.ui.graphics.drawscope.clipPath |
||||
import androidx.compose.ui.platform.debugInspectorInfo |
||||
import kotlin.math.sqrt |
||||
|
||||
// Note: these modifiers come from https://gist.github.com/darvld/eb3844474baf2f3fc6d3ab44a4b4b5f8 |
||||
|
||||
/** |
||||
* A modifier that clips the composable content using an animated circle. The circle will |
||||
* expand/shrink with an animation whenever [visible] changes. |
||||
* |
||||
* For more fine-grained control over the transition, see this method's overload, which allows passing |
||||
* a [State] object to control the progress of the reveal animation. |
||||
* |
||||
* By default, the circle is centered in the content, but custom positions may be specified using |
||||
* [revealFrom]. Specified offsets should be between 0 (left/top) and 1 (right/bottom).*/ |
||||
fun Modifier.circularReveal( |
||||
visible: Boolean, |
||||
showScrim: Boolean = false, |
||||
revealFrom: Offset = Offset(0.5f, 0.5f), |
||||
): Modifier = composed( |
||||
factory = { |
||||
val factor = updateTransition(visible, label = "Visibility") |
||||
.animateFloat(label = "revealFactor") { if (it) 1f else 0f } |
||||
|
||||
circularReveal(factor, showScrim, revealFrom) |
||||
}, |
||||
inspectorInfo = debugInspectorInfo { |
||||
name = "circularReveal" |
||||
properties["visible"] = visible |
||||
properties["revealFrom"] = revealFrom |
||||
} |
||||
) |
||||
|
||||
/** |
||||
* A modifier that clips the composable content using a circular shape. The radius of the circle |
||||
* will be determined by the [transitionProgress]. |
||||
* |
||||
* The values of the progress should be between 0 and 1. |
||||
* |
||||
* By default, the circle is centered in the content, but custom positions may be specified using |
||||
* [revealFrom]. Specified offsets should be between 0 (left/top) and 1 (right/bottom). |
||||
* */ |
||||
fun Modifier.circularReveal( |
||||
transitionProgress: State<Float>, |
||||
showScrim: Boolean = false, |
||||
revealFrom: Offset = Offset(0.5f, 0.5f) |
||||
): Modifier { |
||||
return drawWithCache { |
||||
val path = Path() |
||||
val center = revealFrom.mapTo(size) |
||||
val radius = calculateRadius(revealFrom, size) |
||||
val scrimColor = if (showScrim) { |
||||
Color.Gray |
||||
} else { |
||||
Color.Transparent |
||||
} |
||||
|
||||
path.addOval(Rect(center, radius * transitionProgress.value)) |
||||
|
||||
onDrawWithContent { |
||||
if (showScrim) { |
||||
drawRect(scrimColor, alpha = transitionProgress.value * 0.75f) |
||||
} |
||||
clipPath(path) { this@onDrawWithContent.drawContent() } |
||||
} |
||||
} |
||||
} |
||||
|
||||
private fun Offset.mapTo(size: Size): Offset { |
||||
return Offset(x * size.width, y * size.height) |
||||
} |
||||
|
||||
private fun calculateRadius(normalizedOrigin: Offset, size: Size) = with(normalizedOrigin) { |
||||
val x = (if (x > 0.5f) x else 1 - x) * size.width |
||||
val y = (if (y > 0.5f) y else 1 - y) * size.height |
||||
|
||||
sqrt(x * x + y * y) |
||||
} |
Loading…
Reference in new issue