├── .github └── workflows │ └── release.yml ├── .gitignore ├── .idea ├── caches │ └── build_file_checksums.ser ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── dbnavigator.xml ├── encodings.xml ├── gradle.xml ├── markdown-navigator-enh.xml ├── markdown-navigator.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── me │ │ └── xuexuan │ │ └── rain │ │ └── MainActivity.java │ └── res │ ├── drawable │ └── ic_launcher_background.xml │ ├── layout │ └── activity_main.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ ├── ic_launcher_round.png │ ├── star.png │ └── sun.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gif └── rain_sun.gif ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── me │ │ └── xuexuan │ │ ├── ItemEmoje.kt │ │ └── RainViewGroup.kt │ └── res │ └── drawable-xxhdpi │ └── star.png └── settings.gradle /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: RELEASE_CI 2 | 3 | on: 4 | push: 5 | # Sequence of patterns matched against refs/tags 6 | tags: 7 | - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 8 | jobs: 9 | 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v1 14 | - name: set up JDK 1.8 15 | uses: actions/setup-java@v1 16 | with: 17 | java-version: 1.8 18 | # 打包apk 19 | - name: Build with Gradle 20 | run: chmod +x gradlew &&./gradlew assembleRelease 21 | 22 | 23 | # 上传apk 到action,在右上角查看 24 | # - name: Upload APK 25 | # uses: actions/upload-artifact@v1 26 | # with: 27 | # name: app 28 | # path: app/build/outputs/apk/release/emoji-rain.apk 29 | 30 | # apk 签名 31 | - name: Sign Apk 32 | id: sign 33 | uses: r0adkll/sign-android-release@v1 34 | with: 35 | releaseDirectory: app/build/outputs/apk/release/ 36 | signingKeyBase64: ${{ secrets.SIGNING_KEY }} 37 | alias: ${{ secrets.ALIAS }} 38 | keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }} 39 | keyPassword: ${{ secrets.KEY_PASSWORD }} 40 | 41 | - name: Create Release 42 | id: create_release 43 | uses: actions/create-release@v1.0.0 44 | env: 45 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 46 | with: 47 | tag_name: ${{ github.ref }} 48 | release_name: Release ${{ github.ref }} 49 | draft: false 50 | prerelease: false 51 | 52 | - name: Upload Release Asset 53 | id: upload-release-asset 54 | uses: actions/upload-release-asset@v1.0.1 55 | env: 56 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 57 | with: 58 | upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 59 | asset_path: ${{ steps.sign.outputs.signedReleaseFile }} 60 | asset_name: emoji-rain.apk 61 | asset_content_type: application/zip -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JantHsueh/EmojiRain/9b9b70e1e984119baf0a12c8ce207620a55f125d/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 18 | 24 | 25 | 29 | 30 | 31 | 33 | 34 | 35 | 41 | 42 | 43 | 44 | 45 | 51 | 52 | 56 | 57 | 58 | 59 | 61 | 62 | 63 |
64 | 65 | 66 | 67 | xmlns:android 68 | 69 | ^$ 70 | 71 | 72 | 73 |
74 |
75 | 76 | 77 | 78 | xmlns:.* 79 | 80 | ^$ 81 | 82 | 83 | BY_NAME 84 | 85 |
86 |
87 | 88 | 89 | 90 | .*:id 91 | 92 | http://schemas.android.com/apk/res/android 93 | 94 | 95 | 96 |
97 |
98 | 99 | 100 | 101 | .*:name 102 | 103 | http://schemas.android.com/apk/res/android 104 | 105 | 106 | 107 |
108 |
109 | 110 | 111 | 112 | name 113 | 114 | ^$ 115 | 116 | 117 | 118 |
119 |
120 | 121 | 122 | 123 | style 124 | 125 | ^$ 126 | 127 | 128 | 129 |
130 |
131 | 132 | 133 | 134 | .* 135 | 136 | ^$ 137 | 138 | 139 | BY_NAME 140 | 141 |
142 |
143 | 144 | 145 | 146 | .* 147 | 148 | http://schemas.android.com/apk/res/android 149 | 150 | 151 | ANDROID_ATTRIBUTE_ORDER 152 | 153 |
154 |
155 | 156 | 157 | 158 | .* 159 | 160 | .* 161 | 162 | 163 | BY_NAME 164 | 165 |
166 |
167 |
168 |
169 | 170 | 172 |
173 |
-------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/dbnavigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/markdown-navigator-enh.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 29 | 30 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Android 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [![Build Status](https://github.com/JantHsueh/EmojiRain/workflows/RELEASE_CI/badge.svg)](https://github.com/JantHsueh/EmojiRain/workflows/RELEASE_CI/badge.svg) 4 | [![Download](https://api.bintray.com/packages/jantxue/maven/Emoji-Rain/images/download.svg) ](https://bintray.com/jantxue/maven/Emoji-Rain/_latestVersion) 5 | [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](https://www.apache.org/licenses/LICENSE-2.0) 6 | 7 | # 表情雨 ViewGroup 8 | 9 | 微信聊天中的表情雨效果一样。内部使用了资源缓存复用机制,在无限循环中,不会出现占用内存增长的问题,所以不会GC(除非),更流畅 10 | 11 | 先来看下效果,太阳雨。(gif有点卡顿,因为录制屏幕时的帧率不够,在项目中是很流畅的) 12 | 13 | 14 | 15 | # 使用教程 16 | 17 | 18 | 在项目的build.gradle 添加引用 19 | 20 | ``` 21 | implementation 'me.xuexuan:emoji-rain:1.0.0' 22 | //为了减少版本冲突问题,库中没有引用constraintlayout,所以在自己的项目添加引用 23 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 24 | ``` 25 | 26 | 27 | 28 | 例如:在布局文件中使用 29 | 30 | ```xml 31 | 35 | 36 | 37 | 38 | ``` 39 | 它是一个viewGroup,继承ConstraintLayout。所以可以把它当做ConstraintLayout来使用 40 | 41 | 42 | 43 | ## 使用 44 | 45 | 获取到RainViewGroup的对象实例(例如:在java代码中,通过findViewById 获取) 46 | 47 | 调用start(),开启表情雨 48 | ```java 49 | rainViewGroup = findViewById(R.id.testView); 50 | rainViewGroup.start(); 51 | ``` 52 | 调用stop(),关闭表情雨 53 | ```java 54 | rainViewGroup.stop(); 55 | ``` 56 | 57 | 58 | 59 | ## 高级使用 60 | 61 | 项目提供了一些函数来实现自定义的效果 62 | 63 | ### 设置表情雨资源 64 | 65 | `setImgResId(mImgResId: Int)` 66 | 67 | ### 设置表情缩放比例 68 | 69 | `setScale(scaleRandom: Int, scaleOffset: Int)` 默认值是 `setScale(30, 70)` 70 | 71 | 72 | 在代码的实现`var i = (mRandom.nextInt(xxxRandom) + xxxOffset).toFloat() / 100f` 73 | 74 | 例如:`setScale(30, 70)` 那么i的取值范围就是[0.7,1) 75 | 76 | 77 | ### 设置屏幕最多显示的表情数量 78 | 屏幕最多的表情数量,以下简称单屏数量,可以理解为,表情雨的密度 79 | 80 | `setAmount(num: Int = mAmount)` 默认值是 20 81 | 82 | 83 | ### 设置表情雨次数 84 | 这里的次数,是指上面设置的表情数量的次数。在保持密度不变的情况下,设置下落数量。 85 | 86 | 87 | 88 | `setTimes(times: Int = INFINITE)` 默认值是 1 89 | 90 | 91 | 例如: 92 | - A:单屏数量(密度) = 50,次数 = 3,总共数量150。 93 | - B:单屏数量(密度) = 50,次数 = 1,总共数量50。 94 | - c:单屏数量(密度) = 150,次数 = 1,总共数量150。 95 | 96 | 97 | 98 | | | 表情密度 | 表情数量 | 下落时间 99 | | ------------ | ------------ |------------ |------------ | 100 | | A B | 相同 | A = 3\*B | A = 3\*B 101 | | A C | C = 3\*A | 相同 | A = 3\*B 102 | | B C | C = 3\*B | C = 3\*B| 相同 103 | 104 | 105 | 106 | ### 设置x,y轴偏移方向 107 | 108 | 设置x/y轴的偏移,每一次onDraw(),在上一次位置的基础上,在x/y轴上增加的偏移量。 109 | 110 | ```java 111 | setX(xRandom: Int, xOffset: Int) 112 | setY(yRandom: Int, yOffset: Int) 113 | ``` 114 | 115 | 默认值是`setX(6,-3)` `setY(5,10)` 116 | 117 | 118 | 在代码中的实现`var i = mRandom.nextInt(xxxRandom) + xxxOffset` 119 | 120 | 例如:`setX(6,-3)`, i的取值范围就是 [-3,3) 121 | 122 | 123 | ### 设置初始的横坐标位置 124 | 125 | 设置表情初始位置,x值的范围,也就在屏幕宽度指定的范围内落下。避免表情x = 0(x = 屏幕宽度)时,xOffset为负值(正值),落下很小的距离,表情就划出屏幕的问题。 126 | 127 | `setWidth(widthRandom: Int, widthOffset: Int)` 默认值是`setWidth(200,100)` 128 | 129 | 在代码中的实现`var i = mRandom.nextInt(getWidth() - xxxRandom) + xxxOffset`, 130 | 例如:屏幕宽度是1080,`setWidth(200,100)`, i的取值范围就是 [980,100) 131 | 132 | # LICENSE 133 | ```` 134 | Copyright 2020 XueXuan 135 | 136 | Licensed under the Apache License, Version 2.0 (the "License"); 137 | you may not use this file except in compliance with the License. 138 | You may obtain a copy of the License at 139 | 140 | http://www.apache.org/licenses/LICENSE-2.0 141 | 142 | Unless required by applicable law or agreed to in writing, software 143 | distributed under the License is distributed on an "AS IS" BASIS, 144 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 145 | See the License for the specific language governing permissions and 146 | limitations under the License. 147 | ```` 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | android { 5 | compileSdkVersion 28 6 | defaultConfig { 7 | applicationId "me.xuexuan.rain" 8 | minSdkVersion 19 9 | targetSdkVersion 28 10 | 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | 22 | android.applicationVariants.all { variant -> 23 | variant.outputs.all { 24 | if (variant.buildType.name == 'release') { 25 | outputFileName = "emoji-rain.apk" 26 | } 27 | } 28 | } 29 | } 30 | 31 | dependencies { 32 | implementation fileTree(dir: 'libs', include: ['*.jar']) 33 | implementation "androidx.appcompat:appcompat:1.1.0" 34 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 35 | // implementation 'me.xuexuan:emoji-rain:1.0.0' 36 | api project(':library') 37 | 38 | } 39 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 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 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/me/xuexuan/rain/MainActivity.java: -------------------------------------------------------------------------------- 1 | package me.xuexuan.rain; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | import android.widget.Button; 6 | 7 | import androidx.appcompat.app.AppCompatActivity; 8 | 9 | import me.xuexuan.RainViewGroup; 10 | 11 | public class MainActivity extends AppCompatActivity { 12 | 13 | private RainViewGroup rainView; 14 | private Button btnStar; 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_main); 20 | rainView = findViewById(R.id.testView); 21 | btnStar = findViewById(R.id.btn_sun); 22 | 23 | 24 | //屏幕中最多显示item的数量 25 | rainView.setAmount(50); 26 | //设置下落的次数。在保持密度不变的情况下,设置下落数量。例如:数量 = 50,下落次数 = 3,总共数量150。 27 | // rainView.setTimes(2); 28 | //设置无效循环 29 | rainView.setTimes(RainViewGroup.INFINITE); 30 | rainView.start(); 31 | 32 | btnStar.setOnClickListener(new View.OnClickListener() { 33 | @Override 34 | public void onClick(View v) { 35 | rainView.stop(); 36 | rainView.setImgResId(R.mipmap.sun); 37 | rainView.start(); 38 | } 39 | }); 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 |