├── app ├── .gitignore ├── release │ ├── app-release.apk │ └── output.json ├── src │ ├── main │ │ ├── res │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.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 │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── layout │ │ │ │ └── activity_main.xml │ │ │ └── drawable │ │ │ │ └── ic_launcher_background.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── king │ │ │ │ └── waveview │ │ │ │ └── MainActivity.java │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── king │ │ │ └── waveview │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── king │ │ └── waveview │ │ └── ExampleInstrumentedTest.java ├── proguard-rules.pro └── build.gradle ├── lib ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ └── values │ │ │ │ ├── strings.xml │ │ │ │ └── attrs.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── king │ │ │ └── view │ │ │ └── waveview │ │ │ └── WaveView.java │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── king │ │ │ └── view │ │ │ └── waveview │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── king │ │ └── view │ │ └── waveview │ │ └── ExampleInstrumentedTest.java ├── bintray.gradle ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── GIF.gif ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .idea ├── markdown-navigator │ └── profiles_settings.xml ├── encodings.xml ├── vcs.xml ├── compiler.xml ├── runConfigurations.xml ├── gradle.xml ├── misc.xml ├── markdown-navigator.xml ├── codeStyles │ └── Project.xml └── dbnavigator.xml ├── .gitignore ├── .travis.yml ├── gradle.properties ├── LICENSE ├── versions.gradle ├── gradlew.bat ├── README.md └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /lib/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':lib' 2 | -------------------------------------------------------------------------------- /GIF.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WaveView/HEAD/GIF.gif -------------------------------------------------------------------------------- /app/release/app-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WaveView/HEAD/app/release/app-release.apk -------------------------------------------------------------------------------- /lib/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | lib 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | WaveView 3 | 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WaveView/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WaveView/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WaveView/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WaveView/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WaveView/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WaveView/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WaveView/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WaveView/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WaveView/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WaveView/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /lib/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenly1314/WaveView/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1dp 4 | 4dp 5 | 5dp 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches/build_file_checksums.ser 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | .DS_Store 9 | /build 10 | /captures 11 | .externalNativeBuild 12 | -------------------------------------------------------------------------------- /app/release/output.json: -------------------------------------------------------------------------------- 1 | [{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":2,"versionName":"1.0.1","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase = GRADLE_USER_HOME 2 | distributionPath = wrapper/dists 3 | distributionUrl = https\://services.gradle.org/distributions/gradle-4.6-all.zip 4 | zipStoreBase = GRADLE_USER_HOME 5 | zipStorePath = wrapper/dists 6 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | #3F008577 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /lib/bintray.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.novoda.bintray-release' 2 | 3 | //添加 4 | publish { 5 | userOrg = 'jenly'//bintray.com用户名 6 | groupId = 'com.king.view'//jcenter上的路径s 7 | artifactId = 'waveview'//项目名称 8 | publishVersion = app_version.versionName//版本号 9 | desc = 'WaveView for Android'//描述 10 | website = 'https://github.com/jenly1314/WaveView'//网站 11 | licences = ['MIT']//开源协议 12 | } -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/king/waveview/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.king.waveview; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /lib/src/test/java/com/king/view/waveview/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.king.view.waveview; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/king/waveview/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.king.waveview; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | 6 | import com.king.view.waveview.WaveView; 7 | 8 | public class MainActivity extends AppCompatActivity { 9 | 10 | WaveView waveView; 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | setContentView(R.layout.activity_main); 16 | 17 | } 18 | 19 | @Override 20 | protected void onResume() { 21 | super.onResume(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | jdk: oraclejdk8 3 | before_install: 4 | - yes | sdkmanager "platforms;android-28" 5 | 6 | env: 7 | global: 8 | - ANDROID_API_LEVEL=28 9 | - ANDROID_BUILD_TOOLS_VERSION=28.0.3 10 | - TRAVIS_SECURE_ENV_VARS=true 11 | 12 | android: 13 | components: 14 | # The BuildTools version used by your project 15 | - tools 16 | - platform-tools 17 | - build-tools-$ANDROID_BUILD_TOOLS_VERSION 18 | - extra-android-m2repository 19 | - extra-google-android-support 20 | 21 | # The SDK version used to compile your project 22 | - android-$ANDROID_API_LEVEL 23 | licenses: 24 | - '.+' 25 | 26 | script: 27 | - ./gradlew clean 28 | - ./gradlew assembleDebug -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs = -Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib/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 | -------------------------------------------------------------------------------- /lib/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/king/waveview/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.king.waveview; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.king.waveview", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/src/androidTest/java/com/king/view/waveview/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.king.view.waveview; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.king.view.waveview.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply from: 'bintray.gradle' 3 | 4 | android { 5 | compileSdkVersion build_versions.compileSdk 6 | buildToolsVersion build_versions.buildTools 7 | 8 | defaultConfig { 9 | minSdkVersion build_versions.minSdk 10 | targetSdkVersion build_versions.targetSdk 11 | versionCode app_version.versionCode 12 | versionName app_version.versionName 13 | 14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 15 | 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | 24 | lintOptions { 25 | abortOnError false 26 | } 27 | } 28 | 29 | dependencies { 30 | implementation fileTree(include: ['*.jar'], dir: 'libs') 31 | testImplementation deps.test.junit 32 | androidTestImplementation deps.test.runner 33 | androidTestImplementation deps.test.espresso 34 | 35 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Jenly Yu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion build_versions.compileSdk 5 | buildToolsVersion build_versions.buildTools 6 | 7 | defaultConfig { 8 | applicationId "com.king.waveview" 9 | minSdkVersion build_versions.minSdk 10 | targetSdkVersion build_versions.targetSdk 11 | versionCode app_version.versionCode 12 | versionName app_version.versionName 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | } 23 | 24 | dependencies { 25 | implementation fileTree(include: ['*.jar'], dir: 'libs') 26 | testImplementation deps.test.junit 27 | androidTestImplementation deps.test.runner 28 | androidTestImplementation deps.test.espresso 29 | 30 | implementation deps.support.appcompat 31 | implementation deps.support.constraintlayout 32 | 33 | implementation project(':lib') 34 | } -------------------------------------------------------------------------------- /versions.gradle: -------------------------------------------------------------------------------- 1 | //App 2 | def app_version = [:] 3 | app_version.versionCode = 2 4 | app_version.versionName = "1.0.1" 5 | ext.app_version = app_version 6 | 7 | //build version 8 | def build_versions = [:] 9 | build_versions.minSdk = 16 10 | build_versions.targetSdk = 28 11 | build_versions.compileSdk = 28 12 | build_versions.buildTools = "28.0.3" 13 | ext.build_versions = build_versions 14 | 15 | ext.deps = [:] 16 | 17 | // App dependencies 18 | def versions = [:] 19 | //support 20 | versions.supportLibrary = "28.0.0" 21 | versions.constraintLayout = "1.1.3" 22 | 23 | //test 24 | versions.junit = "4.12" 25 | versions.runner = "1.0.2" 26 | versions.espresso = "3.0.2" 27 | 28 | 29 | //support 30 | def support = [:] 31 | support.design = "com.android.support:design:$versions.supportLibrary" 32 | support.appcompat = "com.android.support:appcompat-v7:$versions.supportLibrary" 33 | support.constraintlayout = "com.android.support.constraint:constraint-layout:$versions.constraintLayout" 34 | deps.support = support 35 | 36 | //test 37 | def test = [:] 38 | test.junit = "junit:junit:$versions.junit" 39 | test.runner = "com.android.support.test:runner:$versions.runner" 40 | test.espresso = "com.android.support.test.espresso:espresso-core:$versions.espresso" 41 | deps.test = test 42 | 43 | ext.deps = deps 44 | 45 | def addRepos(RepositoryHandler handler) { 46 | handler.google() 47 | handler.jcenter() 48 | } 49 | ext.addRepos = this.&addRepos -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 17 | 22 | 29 | 37 | 45 | 46 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 24 | 41 | 42 | 43 | 44 | 45 | 46 | 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WaveView 2 | 3 | [![JitPack](https://img.shields.io/jitpack/v/github/jenly1314/WaveView?logo=jitpack)](https://jitpack.io/#jenly1314/WaveView) 4 | [![Download](https://img.shields.io/badge/download-APK-brightgreen?logo=github)](https://raw.githubusercontent.com/jenly1314/WaveView/master/app/release/app-release.apk) 5 | [![API](https://img.shields.io/badge/API-16%2B-brightgreen?logo=android)](https://developer.android.com/guide/topics/manifest/uses-sdk-element#ApiLevels) 6 | [![License](https://img.shields.io/github/license/jenly1314/WaveView?logo=open-source-initiative)](https://opensource.org/licenses/mit) 7 | 8 | 9 | WaveView for Android 是一个水波纹动画控件视图,支持波纹数,波纹振幅,波纹颜色,波纹速度,波纹方向等属性完全可配。 10 | 11 | ## 效果展示 12 | ![Image](GIF.gif) 13 | 14 | > 你也可以直接下载 [演示App](https://raw.githubusercontent.com/jenly1314/WaveView/master/app/release/app-release.apk) 体验效果 15 | 16 | ## 引入 17 | 18 | ### Gradle: 19 | 20 | 1. 在Project的 **build.gradle** 或 **setting.gradle** 中添加远程仓库 21 | 22 | ```gradle 23 | repositories { 24 | //... 25 | mavenCentral() 26 | maven { url 'https://jitpack.io' } 27 | } 28 | ``` 29 | 30 | 2. 在Module的 **build.gradle** 中添加依赖项 31 | 32 | ```gradle 33 | implementation 'com.github.jenly1314:WaveView:1.0.1' 34 | ``` 35 | 36 | ## 使用 37 | 38 | ### WaveView自定义属性说明 39 | | 属性 | 值类型 | 默认值 | 说明 | 40 | | :------| :------ | :------ | :------ | 41 | | waveCount | integer |2| 波纹数量 | 42 | | waveColor | color |#3F00B9D2| 波纹颜色 | 43 | | waveAmplitude | dimension | 20dp | 波纹振幅 | 44 | | waveMaxSpeed | dimension | 4dp | 波纹最大速度 | 45 | | waveMinSpeed | dimension | 2dp | 波纹最小速度 | 46 | | waveRefreshInterval | integer | 15 | 刷新频率时间间隔,单位:毫秒 | 47 | | waveAutoAnim | boolean | true | 是否自动播放动画 | 48 | | waveInverted | boolean | false | 是否倒置 | 49 | | waveDirection | enum | DIRECTION.LEFT_TO_RIGHT | 波纹方向,默认从左到右 | 50 | | waveVertical | boolean | false | 是否垂直 | 51 | 52 | 53 | ### 示例 54 | 55 | 布局示例 56 | ```Xml 57 | 61 | ``` 62 | 63 | 代码示例 64 | ```Java 65 | //开始动画 66 | waveView.start(); 67 | //停止动画 68 | waveView.stop(); 69 | 70 | ``` 71 | 更多使用详情,请查看[app](app)中的源码使用示例或直接查看 [API帮助文档](https://jitpack.io/com/github/jenly1314/WaveView/latest/javadoc/) 72 | 73 | 74 | ## 相关推荐 75 | - [LoadingView](https://github.com/jenly1314/LoadingView) 一个圆弧加载过渡动画,圆弧个数,大小,弧度,渐变颜色,完全可配。 76 | - [SpinCounterView](https://github.com/jenly1314/SpinCounterView) 一个类似码表变化的旋转计数器动画控件。 77 | - [CounterView](https://github.com/jenly1314/CounterView) 一个数字变化效果的计数器视图控件。 78 | - [RadarView](https://github.com/jenly1314/RadarView) 一个雷达扫描动画后,然后展示得分效果的控件。 79 | - [SuperTextView](https://github.com/jenly1314/SuperTextView) 一个在TextView的基础上扩展了几种动画效果的控件。 80 | - [GiftSurfaceView](https://github.com/jenly1314/GiftSurfaceView) 一个适用于直播间送礼物拼图案的动画控件。 81 | - [FlutteringLayout](https://github.com/jenly1314/FlutteringLayout) 一个适用于直播间点赞桃心飘动效果的控件。 82 | - [DragPolygonView](https://github.com/jenly1314/DragPolygonView) 一个支持可拖动多边形,支持通过拖拽多边形的角改变其形状的任意多边形控件。 83 | - [CircleProgressView](https://github.com/jenly1314/CircleProgressView) 一个圆形的进度动画控件,动画效果纵享丝滑。 84 | - [ArcSeekBar](https://github.com/jenly1314/ArcSeekBar) 一个弧形的拖动条进度控件,配置参数完全可定制化。 85 | - [DrawBoard](https://github.com/jenly1314/DrawBoard) 一个自定义View实现的画板;方便对图片进行编辑和各种涂鸦相关操作。 86 | - [compose-component](https://github.com/jenly1314/compose-component) 一个Jetpack Compose的组件库;主要提供了一些小组件,便于快速使用。 87 | 88 | 89 | ## 版本日志 90 | 91 | #### v1.0.1:2019-11-8 92 | * 移除Support.appcompat-v7依赖 93 | 94 | #### v1.0.0:2019-2-23 95 | * WaveView初始版本 96 | 97 | --- 98 | 99 | ![footer](https://jenly1314.github.io/page/footer.svg) 100 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 36 | 37 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 21 | 22 | 26 | 27 | 28 | 29 | 35 | 36 | 37 | 38 | 39 | 45 | 46 | 50 | 51 | 52 | 53 | 54 |
55 | 56 | 57 | 58 | xmlns:android 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | xmlns:.* 70 | 71 | ^$ 72 | 73 | 74 | BY_NAME 75 | 76 |
77 |
78 | 79 | 80 | 81 | .*:id 82 | 83 | http://schemas.android.com/apk/res/android 84 | 85 | 86 | 87 |
88 |
89 | 90 | 91 | 92 | .*:name 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | 98 |
99 |
100 | 101 | 102 | 103 | name 104 | 105 | ^$ 106 | 107 | 108 | 109 |
110 |
111 | 112 | 113 | 114 | style 115 | 116 | ^$ 117 | 118 | 119 | 120 |
121 |
122 | 123 | 124 | 125 | .* 126 | 127 | ^$ 128 | 129 | 130 | BY_NAME 131 | 132 |
133 |
134 | 135 | 136 | 137 | .* 138 | 139 | http://schemas.android.com/apk/res/android 140 | 141 | 142 | ANDROID_ATTRIBUTE_ORDER 143 | 144 |
145 |
146 | 147 | 148 | 149 | .* 150 | 151 | .* 152 | 153 | 154 | BY_NAME 155 | 156 |
157 |
158 |
159 |
160 |
161 |
-------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 11 | 16 | 21 | 26 | 31 | 36 | 41 | 46 | 51 | 56 | 61 | 66 | 71 | 76 | 81 | 86 | 91 | 96 | 101 | 106 | 111 | 116 | 121 | 126 | 131 | 136 | 141 | 146 | 151 | 156 | 161 | 166 | 171 | 172 | -------------------------------------------------------------------------------- /lib/src/main/java/com/king/view/waveview/WaveView.java: -------------------------------------------------------------------------------- 1 | package com.king.view.waveview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.graphics.Shader; 8 | import android.os.Handler; 9 | import android.os.Message; 10 | import android.util.AttributeSet; 11 | import android.util.DisplayMetrics; 12 | import android.util.Log; 13 | import android.util.TypedValue; 14 | import android.view.View; 15 | 16 | import java.util.Random; 17 | 18 | /** 19 | * @author Jenly 20 | */ 21 | public class WaveView extends View { 22 | 23 | /** 24 | * 画笔 25 | */ 26 | private Paint mPaint; 27 | 28 | /** 29 | * 波纹数 30 | */ 31 | private int mWaveCount = 2; 32 | 33 | /** 34 | * 波纹颜色 35 | */ 36 | private int mWaveColor = 0x3F00B9D2; 37 | /** 38 | * 着色器 39 | */ 40 | private Shader mShader; 41 | 42 | /** 43 | * 波纹振幅 44 | */ 45 | private float mWaveAmplitude; 46 | 47 | /** 48 | * 波纹宽 49 | */ 50 | private int mWaveWidth; 51 | /** 52 | * 波纹高 53 | */ 54 | private int mWaveHeight; 55 | 56 | /** 57 | * 波纹X轴偏移最大速度 58 | */ 59 | private float mMaxSpeed; 60 | /** 61 | * 波纹X轴偏移最小速度 62 | */ 63 | private float mMinSpeed; 64 | 65 | /** 66 | * 波纹X轴偏移速度 67 | */ 68 | private float[] mOffsetSpeeds; 69 | 70 | /** 71 | * 波纹X轴起始偏移量 72 | */ 73 | private int[] mOffsets; 74 | 75 | /** 76 | * 波纹Y轴位置 77 | */ 78 | private float[] mPositions; 79 | 80 | /** 81 | * 波纹周期因素ω, 最小正周期:T=2π/ω(其中ω必须>0) 82 | */ 83 | private float mWaveCycleW; 84 | 85 | /** 86 | * 是否执行动画 87 | */ 88 | private boolean isAnim = true; 89 | 90 | /** 91 | * 刷新间隔时间 92 | */ 93 | private int mRefreshInterval = 15; 94 | 95 | /** 96 | * 随机 97 | */ 98 | private Random mRandom; 99 | 100 | /** 101 | * 刷新视图 102 | */ 103 | private final int REFRESH_VIEW = 1; 104 | 105 | /** 106 | * 是否倒置 107 | */ 108 | private boolean mIsInverted = false; 109 | 110 | /** 111 | * 是否竖立 112 | */ 113 | private boolean mIsVertical = false; 114 | 115 | /** 116 | * 波纹方向,默认从右到左 117 | */ 118 | private DIRECTION mDirection = DIRECTION.LEFT_TO_RIGHT; 119 | 120 | public enum DIRECTION{ 121 | LEFT_TO_RIGHT(1), 122 | RIGHT_TO_LEFT(2); 123 | 124 | private int mValue; 125 | 126 | DIRECTION(int value){ 127 | this.mValue = value; 128 | } 129 | 130 | private static DIRECTION getFromInt(int value){ 131 | for(DIRECTION direction : DIRECTION.values()){ 132 | if(direction.mValue == value){ 133 | return direction; 134 | } 135 | } 136 | return LEFT_TO_RIGHT; 137 | } 138 | 139 | } 140 | 141 | public WaveView(Context context) { 142 | this(context,null); 143 | } 144 | 145 | public WaveView(Context context, AttributeSet attrs) { 146 | this(context, attrs,0); 147 | } 148 | 149 | public WaveView(Context context, AttributeSet attrs, int defStyleAttr) { 150 | super(context, attrs, defStyleAttr); 151 | init(context,attrs); 152 | } 153 | 154 | private void init(Context context, AttributeSet attrs){ 155 | 156 | mRandom = new Random(); 157 | 158 | DisplayMetrics displayMetrics = getDisplayMetrics(); 159 | mWaveAmplitude = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,20,displayMetrics); 160 | float maxSpeed = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,4,displayMetrics); 161 | float minSpeed = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,2,displayMetrics); 162 | 163 | TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.WaveView); 164 | final int n = a.getIndexCount(); 165 | for(int i = 0;i < n;i++){ 166 | int attr = a.getIndex(i); 167 | if (attr == R.styleable.WaveView_waveCount) { 168 | mWaveCount = a.getInt(attr,mWaveCount); 169 | }else if(attr == R.styleable.WaveView_waveColor){ 170 | mWaveColor = a.getColor(attr,mWaveColor); 171 | }else if(attr == R.styleable.WaveView_waveAmplitude){ 172 | mWaveAmplitude = a.getDimension(attr,mWaveAmplitude); 173 | }else if(attr == R.styleable.WaveView_waveMaxSpeed){ 174 | maxSpeed = a.getDimension(attr,mMaxSpeed); 175 | }else if(attr == R.styleable.WaveView_waveMinSpeed){ 176 | maxSpeed = a.getDimension(attr,mMinSpeed); 177 | }else if(attr == R.styleable.WaveView_waveRefreshInterval){ 178 | mRefreshInterval = a.getInt(attr,mRefreshInterval); 179 | }else if(attr == R.styleable.WaveView_waveAutoAnim){ 180 | isAnim = a.getBoolean(attr,isAnim); 181 | }else if(attr == R.styleable.WaveView_waveInverted){ 182 | mIsInverted = a.getBoolean(attr,mIsInverted); 183 | }else if(attr == R.styleable.WaveView_waveDirection){ 184 | mDirection = DIRECTION.getFromInt(a.getInt(attr,mDirection.mValue)); 185 | }else if(attr == R.styleable.WaveView_waveVertical){ 186 | mIsVertical = a.getBoolean(attr,mIsVertical); 187 | } 188 | } 189 | 190 | a.recycle(); 191 | 192 | mMaxSpeed = maxSpeed; 193 | mMinSpeed = minSpeed; 194 | 195 | mPaint = new Paint(); 196 | updatePaint(); 197 | mOffsetSpeeds = new float[mWaveCount]; 198 | //初始化速度 199 | for (int i = 0; i < mWaveCount; i++) { 200 | mOffsetSpeeds[i] = randomSpeed(); 201 | } 202 | 203 | mOffsets = new int[mWaveCount]; 204 | 205 | } 206 | 207 | 208 | private DisplayMetrics getDisplayMetrics(){ 209 | return getResources().getDisplayMetrics(); 210 | } 211 | 212 | 213 | @Override 214 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 215 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 216 | 217 | int defaultWidth = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,300,getDisplayMetrics()); 218 | int defaultHeight = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,60,getDisplayMetrics()); 219 | 220 | int width = measureHandler(widthMeasureSpec,mIsVertical ? defaultHeight : defaultWidth); 221 | int height = measureHandler(heightMeasureSpec,mIsVertical ? defaultWidth : defaultHeight); 222 | 223 | setMeasuredDimension(width,height); 224 | 225 | } 226 | 227 | /** 228 | * 测量处理 229 | * @param measureSpec 230 | * @param defaultSize 231 | * @return 232 | */ 233 | private int measureHandler(int measureSpec,int defaultSize){ 234 | 235 | int result = defaultSize; 236 | int measureMode = MeasureSpec.getMode(measureSpec); 237 | int measureSize = MeasureSpec.getSize(measureSpec); 238 | if(measureMode == MeasureSpec.EXACTLY){ 239 | result = measureSize; 240 | }else if(measureMode == MeasureSpec.AT_MOST){ 241 | result = Math.min(defaultSize,measureSize); 242 | } 243 | return result; 244 | } 245 | 246 | @Override 247 | protected void onSizeChanged(int w, int h, int oldw, int oldh) { 248 | super.onSizeChanged(w, h, oldw, oldh); 249 | 250 | mWaveWidth = w; 251 | mWaveHeight = h; 252 | //波长为总宽度或高度 253 | int waveLength = mIsVertical ? mWaveHeight : mWaveWidth; 254 | //根据波纹数初始化波纹的偏移量 255 | for (int i = 0; i < mWaveCount ; i++) { 256 | mOffsets[i] = waveLength / mWaveCount * i; 257 | } 258 | 259 | //Sin函数周期 ω = 2π/T 260 | mWaveCycleW = (float) (2 * Math.PI / waveLength); 261 | 262 | mPositions = new float[waveLength]; 263 | 264 | //正弦曲线 y = Asin(ωx + φ) 265 | 266 | for (int i = 0; i < waveLength; i++) { 267 | mPositions[i] = (float)(mWaveAmplitude * Math.sin(mWaveCycleW * i)); 268 | } 269 | } 270 | 271 | /** 272 | * 更新画笔 273 | */ 274 | private void updatePaint(){ 275 | mPaint.reset(); 276 | // 去除画笔锯齿 277 | mPaint.setAntiAlias(true); 278 | // 设置风格为实线 279 | mPaint.setStyle(Paint.Style.FILL); 280 | 281 | if(mShader!=null){//不为空则设置着色器支持渐变 282 | mPaint.setShader(mShader); 283 | }else{//设置纯色 284 | mPaint.setColor(mWaveColor); 285 | } 286 | } 287 | 288 | @Override 289 | protected void onDraw(Canvas canvas) { 290 | super.onDraw(canvas); 291 | drawWave(canvas); 292 | } 293 | 294 | /** 295 | * 绘制波纹 296 | * @param canvas 297 | */ 298 | private void drawWave(Canvas canvas){ 299 | if(mWaveCount>0){ 300 | 301 | int waveLength = mIsVertical ? mWaveHeight : mWaveWidth; 302 | //遍历波纹数 303 | for (int i = 0; i < mWaveCount; i++) { 304 | 305 | for (int j = 0; j < waveLength; j++) { 306 | int offset = mOffsets[i]; 307 | //根据偏移量绘制波纹线 308 | 309 | if(mIsVertical){//纵向 310 | if(mIsInverted){//是否倒置 311 | canvas.drawLine(0,j, mWaveWidth - mWaveAmplitude - mPositions[(offset + j)%waveLength],j,mPaint); 312 | }else { 313 | canvas.drawLine(mWaveAmplitude - mPositions[(offset + j)%waveLength] ,j,mWaveWidth,j,mPaint); 314 | } 315 | }else{//横向 316 | if(mIsInverted){//是否倒置 317 | canvas.drawLine(j, 0 ,j,mWaveHeight - mWaveAmplitude - mPositions[(offset + j)%waveLength],mPaint); 318 | }else { 319 | canvas.drawLine(j, mWaveAmplitude - mPositions[(offset + j)%waveLength] ,j,mWaveHeight,mPaint); 320 | } 321 | } 322 | 323 | } 324 | //根据方向来进行偏移 325 | if(mDirection == DIRECTION.LEFT_TO_RIGHT){ 326 | //偏移 327 | mOffsets[i] -= mOffsetSpeeds[i]; 328 | //超过周期宽度则重置 329 | if(mOffsets[i] <= 0){ 330 | mOffsets[i] = waveLength; 331 | //一个周期后,随机一个速度 332 | mOffsetSpeeds[i] = randomSpeed(); 333 | 334 | } 335 | }else{ 336 | //偏移 337 | mOffsets[i] += mOffsetSpeeds[i]; 338 | //超过周期宽度则重置 339 | if(mOffsets[i] >= waveLength){ 340 | mOffsets[i] = 0; 341 | //一个周期后,随机一个速度 342 | mOffsetSpeeds[i] = randomSpeed(); 343 | 344 | } 345 | } 346 | 347 | } 348 | 349 | if(isAnim){//是否显示动画,延迟刷新视图 350 | mHandler.removeMessages(REFRESH_VIEW); 351 | mHandler.sendEmptyMessageDelayed(REFRESH_VIEW,mRefreshInterval); 352 | // postInvalidateDelayed(mRefreshInterval); 353 | } 354 | 355 | } 356 | } 357 | 358 | private Handler mHandler = new Handler(new Handler.Callback() { 359 | @Override 360 | public boolean handleMessage(Message msg) { 361 | switch (msg.what){ 362 | case REFRESH_VIEW: 363 | invalidate(); 364 | return true; 365 | } 366 | return false; 367 | } 368 | }); 369 | 370 | 371 | /** 372 | * 随机一个速度 373 | * @return 374 | */ 375 | private float randomSpeed(){ 376 | if(mMinSpeed!= mMaxSpeed){ 377 | return random(mMinSpeed,mMaxSpeed); 378 | } 379 | 380 | return mMaxSpeed; 381 | } 382 | 383 | /** 384 | * 随机一个范围内的数 385 | * @param min 386 | * @param max 387 | * @return 388 | */ 389 | private float random(float min,float max){ 390 | return mRandom.nextFloat() * (max - min) + min; 391 | } 392 | 393 | 394 | /** 395 | * 开始动画 396 | */ 397 | public void start(){ 398 | if(!isAnim){ 399 | isAnim = true; 400 | invalidate(); 401 | } 402 | } 403 | 404 | /** 405 | * 停止动画 406 | */ 407 | public void stop(){ 408 | if(isAnim){ 409 | isAnim = false; 410 | invalidate(); 411 | } 412 | } 413 | 414 | @Override 415 | protected void onDetachedFromWindow() { 416 | mHandler.removeMessages(1); 417 | isAnim = false; 418 | super.onDetachedFromWindow(); 419 | } 420 | 421 | /** 422 | * 设置波纹颜色 423 | * @param waveColor 424 | */ 425 | public void setWaveColor(int waveColor) { 426 | this.mWaveColor = waveColor; 427 | this.mShader = null; 428 | updatePaint(); 429 | invalidate(); 430 | } 431 | 432 | /** 433 | * 设置波纹颜色 434 | * @param resId 435 | */ 436 | public void setWaveColorResource(int resId){ 437 | int color = getResources().getColor(resId); 438 | setWaveColor(color); 439 | } 440 | 441 | /** 442 | * 设置波纹着色器 443 | * @param shader 444 | */ 445 | public void setWaveShader(Shader shader){ 446 | this.mShader = shader; 447 | updatePaint(); 448 | invalidate(); 449 | } 450 | 451 | /** 452 | * 设置波纹最大速度 453 | * @param maxSpeed 454 | */ 455 | public void setMaxSpeed(float maxSpeed) { 456 | this.mMaxSpeed = maxSpeed; 457 | } 458 | 459 | /** 460 | * 设置波纹最大速度 461 | * @param minSpeed 462 | */ 463 | public void setMinSpeed(float minSpeed) { 464 | this.mMinSpeed = minSpeed; 465 | } 466 | 467 | /** 468 | * 设置波纹最大速度 469 | * @param maxSpeed 470 | */ 471 | public void setMaxSpeedDP(float maxSpeed) { 472 | this.mMinSpeed = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,maxSpeed,getDisplayMetrics()); 473 | } 474 | 475 | /** 476 | * 设置波纹最大速度 477 | * @param minSpeed 478 | */ 479 | public void setMinSpeedDp(float minSpeed) { 480 | this.mMinSpeed = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,minSpeed,getDisplayMetrics()); 481 | } 482 | 483 | /** 484 | * 设置波纹最大速度 485 | * @param resIds 486 | */ 487 | public void setMaxSpeedResource(int resIds) { 488 | this.mMaxSpeed = getResources().getDimension(resIds); 489 | } 490 | 491 | /** 492 | * 设置波纹最小速度 493 | * @param resIds 494 | */ 495 | public void setMinSpeedResource(int resIds) { 496 | this.mMinSpeed = getResources().getDimension(resIds); 497 | } 498 | 499 | /** 500 | * 设置刷新间隔时间(保证每秒刷新超过60帧,让肉眼无感知卡顿现象) 501 | * @param refreshInterval 默认15ms 帧率(fps) = 1秒钟/刷新间隔时间 502 | */ 503 | public void setRefreshInterval(int refreshInterval) { 504 | this.mRefreshInterval = refreshInterval; 505 | } 506 | } 507 | -------------------------------------------------------------------------------- /.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 | 455 | 456 | --------------------------------------------------------------------------------