Skip to content

Commit 34e62e6

Browse files
author
zhujiang2
committed
为一些特定天气添加背景动画
比如晴天、下雨、下雪及多云,别的极端天气,类似雾霾等等没有做
1 parent 50702bd commit 34e62e6

File tree

24 files changed

+601
-9
lines changed

24 files changed

+601
-9
lines changed

.idea/gradle.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

animate/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

animate/build.gradle.kts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
plugins {
2+
id("com.android.library")
3+
id("org.jetbrains.kotlin.android")
4+
}
5+
6+
android {
7+
namespace = "com.zui.animate"
8+
val sdkVersion = rootProject.extra["sdkVersion"] as Int?
9+
val minSdkVersion = rootProject.extra["minSdkVersion"] as Int?
10+
compileSdk = sdkVersion
11+
12+
defaultConfig {
13+
minSdk = minSdkVersion
14+
targetSdk = sdkVersion
15+
16+
testInstrumentationRunner = rootProject.extra["testInstrumentationRunner"] as String?
17+
rootProject.extra["consumerProguardFiles"]?.let { consumerProguardFiles(it) }
18+
resourceConfigurations += listOf("en", "zh", "zh-rCN", "zh-rHK", "zh-rTW")
19+
}
20+
21+
buildTypes {
22+
release {
23+
// 开启混淆
24+
isMinifyEnabled = true
25+
proguardFiles(
26+
getDefaultProguardFile("proguard-android-optimize.txt"),
27+
"proguard-rules.pro"
28+
)
29+
}
30+
}
31+
val javaVersion = rootProject.extra["javaVersion"] as JavaVersion
32+
val javaVersionName = javaVersion.toString()
33+
34+
kotlin {
35+
jvmToolchain {
36+
languageVersion.set(JavaLanguageVersion.of(javaVersionName))
37+
}
38+
}
39+
40+
compileOptions {
41+
sourceCompatibility = javaVersion
42+
targetCompatibility = javaVersion
43+
}
44+
buildFeatures {
45+
compose = true
46+
viewBinding = true
47+
}
48+
49+
composeOptions {
50+
kotlinCompilerExtensionVersion = rootProject.extra["kotlinCompiler"] as String?
51+
}
52+
}
53+
54+
dependencies {
55+
56+
implementation("${rootProject.extra["coreKtx"] as String?}")
57+
implementation("${rootProject.extra["appcompat"] as String?}")
58+
59+
val composeVersion = rootProject.extra["composeVersion"] as String?
60+
implementation("androidx.compose.ui:ui:$composeVersion")
61+
implementation("androidx.compose.ui:ui-tooling-preview:$composeVersion")
62+
implementation("androidx.compose.runtime:runtime-livedata:$composeVersion")
63+
implementation("androidx.compose.material:material:$composeVersion")
64+
testImplementation("${rootProject.extra["junit"] as String?}")
65+
androidTestImplementation("${rootProject.extra["extJunit"] as String?}")
66+
androidTestImplementation("${rootProject.extra["espressoCore"] as String?}")
67+
}

animate/consumer-rules.pro

Whitespace-only changes.

animate/proguard-rules.pro

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Add project specific ProGuard rules here.
2+
# You can control the set of applied configuration files using the
3+
# proguardFiles setting in build.gradle.
4+
#
5+
# For more details, see
6+
# http://developer.android.com/guide/developing/tools/proguard.html
7+
8+
# If your project uses WebView with JS, uncomment the following
9+
# and specify the fully qualified class name to the JavaScript interface
10+
# class:
11+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12+
# public *;
13+
#}
14+
15+
# Uncomment this to preserve the line number information for
16+
# debugging stack traces.
17+
#-keepattributes SourceFile,LineNumberTable
18+
19+
# If you keep the line number information, uncomment this to
20+
# hide the original source file name.
21+
#-renamesourcefileattribute SourceFile
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.zui.animate
2+
3+
import androidx.test.platform.app.InstrumentationRegistry
4+
import androidx.test.ext.junit.runners.AndroidJUnit4
5+
6+
import org.junit.Test
7+
import org.junit.runner.RunWith
8+
9+
import org.junit.Assert.*
10+
11+
/**
12+
* Instrumented test, which will execute on an Android device.
13+
*
14+
* See [testing documentation](http://d.android.com/tools/testing).
15+
*/
16+
@RunWith(AndroidJUnit4::class)
17+
class ExampleInstrumentedTest {
18+
@Test
19+
fun useAppContext() {
20+
// Context of the app under test.
21+
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22+
assertEquals("com.zui.animate.test", appContext.packageName)
23+
}
24+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3+
4+
</manifest>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.zui.animate
2+
3+
import androidx.compose.animation.core.LinearEasing
4+
import androidx.compose.animation.core.RepeatMode
5+
import androidx.compose.animation.core.animateFloat
6+
import androidx.compose.animation.core.infiniteRepeatable
7+
import androidx.compose.animation.core.rememberInfiniteTransition
8+
import androidx.compose.animation.core.tween
9+
import androidx.compose.foundation.Image
10+
import androidx.compose.foundation.layout.Box
11+
import androidx.compose.foundation.layout.offset
12+
import androidx.compose.runtime.Composable
13+
import androidx.compose.runtime.getValue
14+
import androidx.compose.ui.Modifier
15+
import androidx.compose.ui.draw.rotate
16+
import androidx.compose.ui.platform.LocalConfiguration
17+
import androidx.compose.ui.res.painterResource
18+
import androidx.compose.ui.unit.dp
19+
20+
@Composable
21+
fun Cloudy(modifier: Modifier = Modifier, durationMillis: Int = 20000) {
22+
val screenWidthDp = LocalConfiguration.current.screenWidthDp
23+
val transition = rememberInfiniteTransition(label = "")
24+
val rotate by transition.animateFloat(
25+
initialValue = 0f,
26+
targetValue = 40f,
27+
animationSpec = infiniteRepeatable(
28+
tween(durationMillis, easing = LinearEasing),
29+
RepeatMode.Reverse
30+
), label = ""
31+
)
32+
val offset by transition.animateFloat(
33+
initialValue = 0f,
34+
targetValue = screenWidthDp.toFloat(),
35+
animationSpec = infiniteRepeatable(
36+
tween(durationMillis, easing = LinearEasing),
37+
RepeatMode.Reverse
38+
), label = ""
39+
)
40+
Box(modifier = modifier) {
41+
Image(
42+
modifier = Modifier
43+
.rotate(rotate),
44+
painter = painterResource(id = R.drawable.ic_yun1), contentDescription = ""
45+
)
46+
Image(
47+
modifier = Modifier
48+
.offset(offset.dp),
49+
painter = painterResource(id = R.drawable.ic_yun2), contentDescription = ""
50+
)
51+
}
52+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package com.zui.animate
2+
3+
import androidx.annotation.IntDef
4+
import androidx.compose.animation.core.FastOutLinearInEasing
5+
import androidx.compose.animation.core.RepeatMode
6+
import androidx.compose.animation.core.animateFloat
7+
import androidx.compose.animation.core.infiniteRepeatable
8+
import androidx.compose.animation.core.rememberInfiniteTransition
9+
import androidx.compose.animation.core.tween
10+
import androidx.compose.foundation.Canvas
11+
import androidx.compose.foundation.layout.size
12+
import androidx.compose.runtime.Composable
13+
import androidx.compose.runtime.getValue
14+
import androidx.compose.ui.Modifier
15+
import androidx.compose.ui.geometry.Offset
16+
import androidx.compose.ui.graphics.Color
17+
import androidx.compose.ui.graphics.ImageBitmap
18+
import androidx.compose.ui.graphics.StrokeCap
19+
import androidx.compose.ui.layout.Layout
20+
import androidx.compose.ui.res.imageResource
21+
import androidx.compose.ui.unit.dp
22+
import kotlin.math.roundToInt
23+
import kotlin.random.Random
24+
25+
/**
26+
* 定制四种雨,分别对应不同数量的雨滴,数值直接表示雨滴数量
27+
*/
28+
@IntDef(
29+
value = [
30+
Rains.LIGHT_RAIN,
31+
Rains.MODERATE_RAIN,
32+
Rains.HEAVY_RAIN,
33+
Rains.RAINSTORM,
34+
],
35+
)
36+
annotation class RainsValue
37+
38+
object Rains {
39+
// 小雨
40+
const val LIGHT_RAIN = 100
41+
42+
// 中雨
43+
const val MODERATE_RAIN = 150
44+
45+
// 大雨
46+
const val HEAVY_RAIN = 200
47+
48+
// 暴雨
49+
const val RAINSTORM = 300
50+
}
51+
52+
@Composable
53+
fun Rain(modifier: Modifier = Modifier, @RainsValue rainType: Int = Rains.LIGHT_RAIN) {
54+
val bitmap = ImageBitmap.imageResource(id = R.drawable.ic_rain)
55+
56+
Layout(
57+
modifier = modifier,
58+
content = {
59+
// 摆放雪花,分别设置不同duration,增加随机性
60+
repeat(rainType) {
61+
RainDrop(
62+
modifier.size(1.dp, Random.nextInt(8, 20).dp),
63+
bitmap,
64+
Random.nextInt(1000, 2500)
65+
)
66+
}
67+
}
68+
) { measures, constraints ->
69+
val placeableList = measures.mapIndexed { _, measurable ->
70+
constraints.maxHeight * Random.nextFloat()
71+
val height = constraints.maxHeight * Random.nextFloat()
72+
measurable.measure(
73+
constraints.copy(
74+
minWidth = 0,
75+
minHeight = 0,
76+
maxWidth = 10.dp.toPx().toInt(), // snowdrop width
77+
maxHeight = height.roundToInt(),
78+
)
79+
)
80+
}
81+
82+
layout(constraints.maxWidth, constraints.maxHeight) {
83+
var xPosition = constraints.maxWidth / ((placeableList.size + 1))
84+
85+
placeableList.forEachIndexed { _, placeable ->
86+
placeable.place(x = xPosition, y = -(constraints.maxHeight * 0.2).roundToInt())
87+
88+
xPosition += (constraints.maxWidth / ((placeableList.size + 1) * 0.9f)).roundToInt()
89+
}
90+
}
91+
}
92+
}
93+
94+
@Composable
95+
fun RainDrop(modifier: Modifier = Modifier, bitmap: ImageBitmap, durationMillis: Int = 100) {
96+
// 循环播放
97+
val transition = rememberInfiniteTransition(label = "")
98+
99+
// 下降动画:restart动画
100+
val animateY by transition.animateFloat(
101+
initialValue = 0f,
102+
targetValue = 18f,
103+
animationSpec = infiniteRepeatable(
104+
tween(durationMillis, easing = FastOutLinearInEasing),
105+
RepeatMode.Restart
106+
), label = ""
107+
)
108+
109+
Canvas(modifier) {
110+
// 位置随AnimationState改变,实现雪花飘落的效果
111+
val topLeft = center.copy(
112+
x = center.x,
113+
y = center.y + center.y * animateY
114+
)
115+
drawImage(bitmap, topLeft = topLeft)
116+
}
117+
}

0 commit comments

Comments
 (0)