├── LICENSE ├── LemonHello4Android ├── .gitignore ├── .idea │ ├── compiler.xml │ ├── copyright │ │ └── profiles_settings.xml │ ├── gradle.xml │ ├── misc.xml │ ├── modules.xml │ ├── runConfigurations.xml │ └── vcs.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── lemonhello-samples │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── lemonsoft │ │ │ └── net │ │ │ └── lemonhello4android │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── lemonsoft │ │ │ │ └── net │ │ │ │ └── lemonhello4android │ │ │ │ └── MainActivity.java │ │ └── res │ │ │ ├── drawable │ │ │ └── round_function_button.xml │ │ │ ├── layout │ │ │ └── activity_main.xml │ │ │ ├── mipmap │ │ │ ├── icon_bookmark.png │ │ │ ├── icon_error.png │ │ │ ├── icon_information.png │ │ │ ├── icon_messages.png │ │ │ ├── icon_success.png │ │ │ ├── icon_warning.png │ │ │ └── logo.png │ │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── test │ │ └── java │ │ └── lemonsoft │ │ └── net │ │ └── lemonhello4android │ │ └── ExampleUnitTest.java ├── lemonhello │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── net │ │ │ └── lemonsoft │ │ │ └── lemonhello │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── net │ │ │ │ └── lemonsoft │ │ │ │ └── lemonhello │ │ │ │ ├── LemonHello.java │ │ │ │ ├── LemonHelloAction.java │ │ │ │ ├── LemonHelloGlobal.java │ │ │ │ ├── LemonHelloInfo.java │ │ │ │ ├── LemonHelloInfoPack.java │ │ │ │ ├── LemonHelloPanel.java │ │ │ │ ├── LemonHelloPrivateAnimationTool.java │ │ │ │ ├── LemonHelloPrivateSizeTool.java │ │ │ │ ├── LemonHelloView.java │ │ │ │ ├── LemonPaintView.java │ │ │ │ ├── adapter │ │ │ │ └── LemonHelloEventDelegateAdapter.java │ │ │ │ ├── enums │ │ │ │ └── LemonHelloIconLocation.java │ │ │ │ └── interfaces │ │ │ │ ├── LemonHelloActionDelegate.java │ │ │ │ ├── LemonHelloEventDelegate.java │ │ │ │ └── LemonPaintContext.java │ │ └── res │ │ │ └── values │ │ │ └── strings.xml │ │ └── test │ │ └── java │ │ └── net │ │ └── lemonsoft │ │ └── lemonhello │ │ └── ExampleUnitTest.java └── settings.gradle ├── README.md └── Resource ├── LemonHello.gif └── LemonHelloTest01.png /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 1em0nsOft 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. 22 | -------------------------------------------------------------------------------- /LemonHello4Android/.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 | -------------------------------------------------------------------------------- /LemonHello4Android/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /LemonHello4Android/.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /LemonHello4Android/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | -------------------------------------------------------------------------------- /LemonHello4Android/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /LemonHello4Android/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /LemonHello4Android/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /LemonHello4Android/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LemonHello4Android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.2.3' 9 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | maven { url 'https://jitpack.io' } 19 | } 20 | } 21 | 22 | task clean(type: Delete) { 23 | delete rootProject.buildDir 24 | } 25 | -------------------------------------------------------------------------------- /LemonHello4Android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | -------------------------------------------------------------------------------- /LemonHello4Android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LemonITCN/LemonHello4Android/521ce4b1a4ba6f98ddac2cf294d047cb35625b95/LemonHello4Android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /LemonHello4Android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Dec 28 10:00:20 PST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip 7 | -------------------------------------------------------------------------------- /LemonHello4Android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /LemonHello4Android/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 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 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 Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.2" 6 | defaultConfig { 7 | applicationId "lemonsoft.net.lemonhello4android" 8 | minSdkVersion 15 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | testCompile 'junit:junit:4.12' 28 | compile project(':lemonhello') 29 | compile 'com.github.1em0nsOft:LemonBubble4Android:1.0.9' 30 | } 31 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\applications\android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/androidTest/java/lemonsoft/net/lemonhello4android/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package lemonsoft.net.lemonhello4android; 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 | * Instrumentation 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() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("lemonsoft.net.lemonhello4android", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/main/java/lemonsoft/net/lemonhello4android/MainActivity.java: -------------------------------------------------------------------------------- 1 | package lemonsoft.net.lemonhello4android; 2 | 3 | import android.app.Activity; 4 | import android.graphics.BitmapFactory; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | import android.graphics.Path; 9 | import android.graphics.PathMeasure; 10 | import android.graphics.RectF; 11 | import android.os.Bundle; 12 | import android.os.Handler; 13 | import android.view.View; 14 | import android.widget.Button; 15 | import android.widget.LinearLayout; 16 | 17 | import net.lemonsoft.lemonbubble.LemonBubble; 18 | import net.lemonsoft.lemonbubble.LemonBubbleGlobal; 19 | import net.lemonsoft.lemonbubble.enums.LemonBubbleLayoutStyle; 20 | import net.lemonsoft.lemonbubble.enums.LemonBubbleLocationStyle; 21 | import net.lemonsoft.lemonhello.LemonHello; 22 | import net.lemonsoft.lemonhello.LemonHelloAction; 23 | import net.lemonsoft.lemonhello.LemonHelloGlobal; 24 | import net.lemonsoft.lemonhello.LemonHelloInfo; 25 | import net.lemonsoft.lemonhello.LemonHelloView; 26 | import net.lemonsoft.lemonhello.adapter.LemonHelloEventDelegateAdapter; 27 | import net.lemonsoft.lemonhello.enums.LemonHelloIconLocation; 28 | import net.lemonsoft.lemonhello.interfaces.LemonHelloActionDelegate; 29 | import net.lemonsoft.lemonhello.interfaces.LemonPaintContext; 30 | 31 | import java.sql.SQLOutput; 32 | import java.util.ArrayList; 33 | import java.util.List; 34 | 35 | public class MainActivity extends Activity { 36 | 37 | private LinearLayout btn_success; 38 | private LinearLayout btn_error; 39 | private LinearLayout btn_warning; 40 | private LinearLayout btn_information; 41 | private LinearLayout btn_bookmark; 42 | private LinearLayout btn_multiMessages; 43 | 44 | @Override 45 | protected void onCreate(Bundle savedInstanceState) { 46 | super.onCreate(savedInstanceState); 47 | setContentView(R.layout.activity_main); 48 | 49 | LemonHelloGlobal.statusBarColor = Color.parseColor("#3399FF"); 50 | LemonBubbleGlobal.statusBarColor = Color.parseColor("#3399FF"); 51 | 52 | btn_success = (LinearLayout) findViewById(R.id.btn_success); 53 | btn_error = (LinearLayout) findViewById(R.id.btn_error); 54 | btn_warning = (LinearLayout) findViewById(R.id.btn_warning); 55 | btn_information = (LinearLayout) findViewById(R.id.btn_information); 56 | btn_bookmark = (LinearLayout) findViewById(R.id.btn_bookmark); 57 | btn_multiMessages = (LinearLayout) findViewById(R.id.btn_multiMessages); 58 | 59 | initFunctions(); 60 | 61 | // sButton = (Button) findViewById(R.id.sButton); 62 | // sButton.setOnClickListener(new View.OnClickListener() { 63 | // @Override 64 | // public void onClick(View v) { 65 | // LemonHello.getSuccessHello("要删除\"LemonKit\"吗?", "您选择删除后会同时删除应用内的所有数据,确认删除吗?") 66 | // .setIconWidth(80) 67 | // .addAction(new LemonHelloAction("取消", Color.argb(255, 0, 120, 215), new LemonHelloActionDelegate() { 68 | // @Override 69 | // public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 70 | // helloView.hide(); 71 | // } 72 | // })) 73 | // .addAction(new LemonHelloAction("删除", Color.RED, new LemonHelloActionDelegate() { 74 | // @Override 75 | // public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 76 | // helloView.hide(); 77 | // } 78 | // })) 79 | // .show(MainActivity.this); 80 | // } 81 | // }); 82 | } 83 | 84 | private void initFunctions() { 85 | 86 | // 成功按钮被点击 87 | btn_success.setOnClickListener(new View.OnClickListener() { 88 | @Override 89 | public void onClick(View v) { 90 | LemonHello.getSuccessHello("提交成功", "恭喜您,您所填写的数据已经全部提交成功,我们的客服人员将在24小时内进行审核,请耐心等待.") 91 | .setContentFontSize(14) 92 | .addAction(new LemonHelloAction("我知道啦", new LemonHelloActionDelegate() { 93 | @Override 94 | public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 95 | helloView.hide(); 96 | } 97 | })) 98 | .setEventDelegate(new LemonHelloEventDelegateAdapter() { 99 | @Override 100 | public void onMaskTouch(LemonHelloView helloView, LemonHelloInfo helloInfo) { 101 | super.onMaskTouch(helloView, helloInfo); 102 | helloView.hide(); 103 | } 104 | }) 105 | .show(MainActivity.this); 106 | } 107 | }); 108 | 109 | btn_error.setOnClickListener(new View.OnClickListener() { 110 | @Override 111 | public void onClick(View v) { 112 | LemonHello.getErrorHello("发生错误", "对不起,您没有权限删除此数据,请联系系统管理员进行操作,谢谢。") 113 | .addAction(new LemonHelloAction("关闭", new LemonHelloActionDelegate() { 114 | @Override 115 | public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 116 | helloView.hide(); 117 | } 118 | })) 119 | .show(MainActivity.this); 120 | } 121 | }); 122 | 123 | btn_warning.setOnClickListener(new View.OnClickListener() { 124 | @Override 125 | public void onClick(View v) { 126 | LemonHello.getWarningHello("您确认删除这条数据吗?", "删除这条数据后会同时删除其关联的数据,并且无法撤销!") 127 | .addAction(new LemonHelloAction("取消", new LemonHelloActionDelegate() { 128 | @Override 129 | public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 130 | helloView.hide(); 131 | } 132 | })) 133 | .addAction(new LemonHelloAction("确定删除", Color.RED, new LemonHelloActionDelegate() { 134 | @Override 135 | public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 136 | helloView.hide(); 137 | 138 | // 提示框使用了LemonBubble,请您参考:https://github.com/1em0nsOft/LemonBubble4Android 139 | LemonBubble.showRoundProgress(MainActivity.this, "正在删除中..."); 140 | new Handler().postDelayed(new Runnable() { 141 | @Override 142 | public void run() { 143 | LemonBubble.showRight(MainActivity.this, "删除成功", 1000); 144 | } 145 | }, 2000); 146 | } 147 | })) 148 | .show(MainActivity.this); 149 | } 150 | }); 151 | 152 | btn_information.setOnClickListener(new View.OnClickListener() { 153 | @Override 154 | public void onClick(View v) { 155 | LemonHello.getInformationHello("您确定要注销吗?", "注销登录后您将无法接收到当前用户的所有推送消息。") 156 | .addAction(new LemonHelloAction("取消", new LemonHelloActionDelegate() { 157 | @Override 158 | public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 159 | helloView.hide(); 160 | } 161 | })) 162 | .addAction(new LemonHelloAction("我要注销", Color.RED, new LemonHelloActionDelegate() { 163 | @Override 164 | public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 165 | helloView.hide(); 166 | // 提示框使用了LemonBubble,请您参考:https://github.com/1em0nsOft/LemonBubble4Android 167 | LemonBubble.getRoundProgressBubbleInfo() 168 | .setLocationStyle(LemonBubbleLocationStyle.BOTTOM) 169 | .setLayoutStyle(LemonBubbleLayoutStyle.ICON_LEFT_TITLE_RIGHT) 170 | .setBubbleSize(200, 50) 171 | .setProportionOfDeviation(0.1f) 172 | .setTitle("正在请求服务器...") 173 | .show(MainActivity.this); 174 | new Handler().postDelayed(new Runnable() { 175 | @Override 176 | public void run() { 177 | LemonBubble.showRight(MainActivity.this, "注销成功,欢迎您下次登录", 2000); 178 | } 179 | }, 1500); 180 | } 181 | })) 182 | .show(MainActivity.this); 183 | } 184 | }); 185 | btn_bookmark.setOnClickListener(new View.OnClickListener() { 186 | @Override 187 | public void onClick(View v) { 188 | LemonHelloInfo bookMarkInfo = new LemonHelloInfo() 189 | .setTitle("添加书签") 190 | .setContent("确认将《LemonKit》添加到您的书签当中吗?") 191 | .setIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.icon_bookmark)) 192 | .addAction(new LemonHelloAction("取消", Color.RED, new LemonHelloActionDelegate() { 193 | @Override 194 | public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 195 | helloView.hide(); 196 | } 197 | })) 198 | .addAction(new LemonHelloAction("我再想想", new LemonHelloActionDelegate() { 199 | @Override 200 | public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 201 | helloView.hide(); 202 | } 203 | })) 204 | .addAction(new LemonHelloAction("添加", new LemonHelloActionDelegate() { 205 | @Override 206 | public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 207 | helloView.hide(); 208 | LemonBubble.showRight(MainActivity.this, "添加成功", 1500); 209 | } 210 | })); 211 | bookMarkInfo.show(MainActivity.this); 212 | } 213 | }); 214 | 215 | btn_multiMessages.setOnClickListener(new View.OnClickListener() { 216 | @Override 217 | public void onClick(View v) { 218 | LemonHelloInfo info1 = new LemonHelloInfo() 219 | .setTitle("LemonKit想要获取您的位置") 220 | .setContent("LemonKit获取到您的位置之后将会动态记录您的地理信息。") 221 | .addAction(new LemonHelloAction("允许", new LemonHelloActionDelegate() { 222 | @Override 223 | public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 224 | helloView.hide(); 225 | } 226 | })) 227 | .addAction(new LemonHelloAction("拒绝", Color.RED, new LemonHelloActionDelegate() { 228 | @Override 229 | public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 230 | helloView.hide(); 231 | } 232 | })); 233 | LemonHelloInfo info2 = new LemonHelloInfo() 234 | .setTitle("LemonKit想要访问数据") 235 | .setContent("LemonKit希望使用蜂窝网络或者WLAN进行远程数据获取。") 236 | .addAction(new LemonHelloAction("允许", new LemonHelloActionDelegate() { 237 | @Override 238 | public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 239 | helloView.hide(); 240 | } 241 | })) 242 | .addAction(new LemonHelloAction("拒绝", Color.RED, new LemonHelloActionDelegate() { 243 | @Override 244 | public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 245 | helloView.hide(); 246 | } 247 | })); 248 | LemonHelloInfo info3 = new LemonHelloInfo() 249 | .setTitle("LemonKit想要推送通知") 250 | .setContent("LemonKit将要获取通知权限,在适当的时候会向您推送一些通知。") 251 | .addAction(new LemonHelloAction("允许", new LemonHelloActionDelegate() { 252 | @Override 253 | public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 254 | helloView.hide(); 255 | } 256 | })) 257 | .addAction(new LemonHelloAction("拒绝", Color.RED, new LemonHelloActionDelegate() { 258 | @Override 259 | public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 260 | helloView.hide(); 261 | } 262 | })); 263 | info1.show(MainActivity.this); 264 | info2.show(MainActivity.this); 265 | info3.show(MainActivity.this); 266 | } 267 | }); 268 | 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/main/res/drawable/round_function_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 13 | 22 | 23 | 28 | 29 | 36 | 37 | 38 | 47 | 48 | 53 | 54 | 61 | 62 | 63 | 72 | 73 | 78 | 79 | 86 | 87 | 88 | 89 | 90 | 93 | 94 | 103 | 104 | 109 | 110 | 117 | 118 | 119 | 128 | 129 | 134 | 135 | 142 | 143 | 144 | 153 | 154 | 159 | 160 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/main/res/mipmap/icon_bookmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LemonITCN/LemonHello4Android/521ce4b1a4ba6f98ddac2cf294d047cb35625b95/LemonHello4Android/lemonhello-samples/src/main/res/mipmap/icon_bookmark.png -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/main/res/mipmap/icon_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LemonITCN/LemonHello4Android/521ce4b1a4ba6f98ddac2cf294d047cb35625b95/LemonHello4Android/lemonhello-samples/src/main/res/mipmap/icon_error.png -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/main/res/mipmap/icon_information.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LemonITCN/LemonHello4Android/521ce4b1a4ba6f98ddac2cf294d047cb35625b95/LemonHello4Android/lemonhello-samples/src/main/res/mipmap/icon_information.png -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/main/res/mipmap/icon_messages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LemonITCN/LemonHello4Android/521ce4b1a4ba6f98ddac2cf294d047cb35625b95/LemonHello4Android/lemonhello-samples/src/main/res/mipmap/icon_messages.png -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/main/res/mipmap/icon_success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LemonITCN/LemonHello4Android/521ce4b1a4ba6f98ddac2cf294d047cb35625b95/LemonHello4Android/lemonhello-samples/src/main/res/mipmap/icon_success.png -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/main/res/mipmap/icon_warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LemonITCN/LemonHello4Android/521ce4b1a4ba6f98ddac2cf294d047cb35625b95/LemonHello4Android/lemonhello-samples/src/main/res/mipmap/icon_warning.png -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/main/res/mipmap/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LemonITCN/LemonHello4Android/521ce4b1a4ba6f98ddac2cf294d047cb35625b95/LemonHello4Android/lemonhello-samples/src/main/res/mipmap/logo.png -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | LemonHello4Android 3 | 4 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 12 |        13 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello-samples/src/test/java/lemonsoft/net/lemonhello4android/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package lemonsoft.net.lemonhello4android; 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() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'com.github.dcendents.android-maven' 3 | group='com.github.1em0nsOft' 4 | 5 | android { 6 | compileSdkVersion 25 7 | buildToolsVersion "25.0.2" 8 | 9 | defaultConfig { 10 | minSdkVersion 15 11 | targetSdkVersion 25 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 16 | 17 | } 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | } 25 | 26 | dependencies { 27 | compile fileTree(dir: 'libs', include: ['*.jar']) 28 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 29 | exclude group: 'com.android.support', module: 'support-annotations' 30 | }) 31 | compile 'com.android.support:appcompat-v7:25.1.0' 32 | testCompile 'junit:junit:4.12' 33 | } 34 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\applications\android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interfaces 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/androidTest/java/net/lemonsoft/lemonhello/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello; 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 | * Instrumentation 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() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("net.lemonsoft.lemonhello.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/java/net/lemonsoft/lemonhello/LemonHello.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Color; 5 | import android.graphics.Paint; 6 | import android.graphics.Path; 7 | 8 | import net.lemonsoft.lemonhello.enums.LemonHelloIconLocation; 9 | import net.lemonsoft.lemonhello.interfaces.LemonPaintContext; 10 | 11 | /** 12 | * LemonHello 对话框实际应用类 13 | * Created by LiuRi on 2017/1/11. 14 | */ 15 | 16 | public class LemonHello { 17 | 18 | /** 19 | * 获取一个带有橘黄色主题的感叹号!提示框 20 | * 21 | * @param title 提示的标题内容 22 | * @param content 提示的正文内容 23 | * @return 提示框信息描述对象 24 | */ 25 | public static LemonHelloInfo getWarningHello(String title, String content) { 26 | LemonHelloInfo info = new LemonHelloInfo(); 27 | info.setIconLocation(LemonHelloIconLocation.TOP) 28 | .setIconPaintContext(new LemonPaintContext() { 29 | @Override 30 | public void paint(Canvas canvas, float playProgress) { 31 | int color = Color.argb(140, 255, 111, 2); 32 | Paint paint = new Paint(); 33 | paint.setStyle(Paint.Style.FILL); 34 | // 绘制背景圆形 35 | paint.setColor(color); 36 | paint.setStrokeCap(Paint.Cap.ROUND); 37 | paint.setStrokeWidth(8); 38 | paint.setAntiAlias(true); 39 | canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, (canvas.getWidth() / 2 - 4) * playProgress, paint); 40 | // 设置画笔颜色为白色,并绘制感叹号 41 | paint.setColor(Color.WHITE); 42 | Path path = new Path(); 43 | path.moveTo(canvas.getWidth() * 0.45f, canvas.getHeight() * 0.2f); 44 | path.lineTo(canvas.getWidth() * 0.55f, canvas.getHeight() * 0.2f); 45 | path.lineTo(canvas.getWidth() * (0.55f - 0.025f * playProgress), canvas.getHeight() * (0.2f + 0.45f * playProgress)); 46 | path.lineTo(canvas.getWidth() * (0.45f + 0.025f * playProgress), canvas.getHeight() * (0.2f + 0.45f * playProgress)); 47 | path.close(); 48 | 49 | path.addRect(canvas.getWidth() * (0.5f - 0.033f * playProgress), 50 | canvas.getWidth() * (0.75f - 0.033f * playProgress), 51 | canvas.getWidth() * (0.5f + 0.033f * playProgress), 52 | canvas.getWidth() * (0.75f + 0.033f * playProgress), Path.Direction.CW); 53 | canvas.drawPath(path, paint); 54 | } 55 | }) 56 | .setIconWidth(60) 57 | .setTitle(title) 58 | .setContent(content); 59 | return info; 60 | } 61 | 62 | /** 63 | * 获取一个带有蓝色主题的信息i提示框 64 | * 65 | * @param title 提示的标题内容 66 | * @param content 提示的正文内容 67 | * @return 提示框信息描述对象 68 | */ 69 | public static LemonHelloInfo getInformationHello(String title, String content) { 70 | LemonHelloInfo info = new LemonHelloInfo(); 71 | info.setIconLocation(LemonHelloIconLocation.TOP) 72 | .setIconPaintContext(new LemonPaintContext() { 73 | @Override 74 | public void paint(Canvas canvas, float playProgress) { 75 | int color = Color.argb(180, 51, 153, 255); 76 | Paint paint = new Paint(); 77 | paint.setStyle(Paint.Style.FILL); 78 | // 绘制背景圆形 79 | paint.setColor(color); 80 | paint.setStrokeCap(Paint.Cap.ROUND); 81 | paint.setStrokeWidth(8); 82 | paint.setAntiAlias(true); 83 | canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, (canvas.getWidth() / 2 - 4) * playProgress, paint); 84 | // 设置画笔为白色并开始绘制中间的i 85 | paint.setColor(Color.WHITE); 86 | 87 | Path path = new Path(); 88 | path.addCircle(canvas.getWidth() / 2, canvas.getHeight() * 0.3f, canvas.getWidth() * 0.05f * playProgress, Path.Direction.CW); 89 | path.moveTo(canvas.getWidth() * 0.45f, canvas.getHeight() * 0.425f); 90 | path.lineTo(canvas.getWidth() * 0.55f, canvas.getHeight() * 0.425f); 91 | path.lineTo(canvas.getWidth() * (0.55f - 0.025f * playProgress), canvas.getHeight() * (0.2f + 0.55f * playProgress)); 92 | path.lineTo(canvas.getWidth() * (0.45f + 0.025f * playProgress), canvas.getHeight() * (0.2f + 0.55f * playProgress)); 93 | canvas.drawPath(path, paint); 94 | } 95 | }) 96 | .setIconWidth(60) 97 | .setTitle(title) 98 | .setContent(content); 99 | return info; 100 | } 101 | 102 | /** 103 | * 获取一个带有红色主题的错X号提示框 104 | * 105 | * @param title 提示的标题内容 106 | * @param content 提示的正文内容 107 | * @return 提示框信息描述对象 108 | */ 109 | public static LemonHelloInfo getErrorHello(String title, String content) { 110 | LemonHelloInfo info = new LemonHelloInfo(); 111 | info.setIconLocation(LemonHelloIconLocation.TOP) 112 | .setIconPaintContext(new LemonPaintContext() { 113 | @Override 114 | public void paint(Canvas canvas, float playProgress) { 115 | int color = Color.argb(160, 255, 51, 0); 116 | Paint paint = new Paint(); 117 | paint.setStyle(Paint.Style.FILL); 118 | // 绘制背景圆形 119 | paint.setColor(color); 120 | paint.setStrokeCap(Paint.Cap.ROUND); 121 | paint.setStrokeWidth(canvas.getWidth() * 0.05f); 122 | paint.setAntiAlias(true); 123 | canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, (canvas.getWidth() / 2 - 4) * playProgress, paint); 124 | // 设置画笔为白色并开始绘制中间的i 125 | paint.setColor(Color.WHITE); 126 | // 动画旋转画布 127 | canvas.rotate(-270 * playProgress, canvas.getWidth() / 2, canvas.getHeight() / 2); 128 | // 画X 129 | canvas.drawLine(canvas.getWidth() * 0.35f, canvas.getHeight() * 0.35f, canvas.getWidth() * 0.65f, canvas.getHeight() * 0.65f, paint); 130 | canvas.drawLine(canvas.getWidth() * 0.65f, canvas.getHeight() * 0.35f, canvas.getWidth() * 0.35f, canvas.getHeight() * 0.65f, paint); 131 | } 132 | }) 133 | .setIconWidth(60) 134 | .setTitle(title) 135 | .setContent(content); 136 | return info; 137 | } 138 | 139 | /** 140 | * 获取一个带有绿色主题的对号提示框 141 | * 142 | * @param title 提示的标题内容 143 | * @param content 提示的正文内容 144 | * @return 提示框信息描述对象 145 | */ 146 | public static LemonHelloInfo getSuccessHello(String title, String content) { 147 | LemonHelloInfo info = new LemonHelloInfo(); 148 | info.setIconLocation(LemonHelloIconLocation.TOP) 149 | .setIconPaintContext(new LemonPaintContext() { 150 | @Override 151 | public void paint(Canvas canvas, float playProgress) { 152 | int color = Color.argb(120, 0, 153, 0); 153 | Paint paint = new Paint(); 154 | paint.setStyle(Paint.Style.FILL); 155 | // 绘制背景圆形 156 | paint.setColor(color); 157 | paint.setStrokeCap(Paint.Cap.ROUND); 158 | paint.setStrokeWidth(canvas.getWidth() * 0.05f); 159 | paint.setAntiAlias(true); 160 | canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, (canvas.getWidth() / 2 - 4) * playProgress, paint); 161 | // 设置画笔为白色并开始绘制中间的i 162 | paint.setColor(Color.WHITE); 163 | // 动画旋转画布 164 | canvas.rotate(-90 + 90 * playProgress, canvas.getWidth() / 2, canvas.getHeight() / 2); 165 | // 画X 166 | canvas.drawLine(canvas.getWidth() * 0.3f, canvas.getHeight() * 0.5f, canvas.getWidth() * 0.45f, canvas.getHeight() * 0.65f, paint); 167 | canvas.drawLine(canvas.getWidth() * 0.45f, canvas.getHeight() * 0.65f, canvas.getWidth() * 0.7f, canvas.getHeight() * 0.35f, paint); 168 | } 169 | }) 170 | .setIconWidth(60) 171 | .setTitle(title) 172 | .setContent(content); 173 | return info; 174 | } 175 | 176 | } 177 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/java/net/lemonsoft/lemonhello/LemonHelloAction.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello; 2 | 3 | import android.graphics.Color; 4 | import android.graphics.drawable.Drawable; 5 | 6 | import net.lemonsoft.lemonhello.interfaces.LemonHelloActionDelegate; 7 | 8 | /** 9 | * LemonHello - 按钮事件描述类 10 | * 描述事件的功能、按钮文字颜色、 11 | * Created by LiuRi on 2017/1/11. 12 | */ 13 | 14 | public class LemonHelloAction { 15 | 16 | /** 17 | * 按钮的标题 18 | */ 19 | private String title; 20 | /** 21 | * 按钮的背景颜色 22 | */ 23 | private int backgroundColor = Color.argb(200, 255, 255, 255); 24 | /** 25 | * 背景的Drawable 26 | */ 27 | private Drawable backgroundDrawable = null; 28 | /** 29 | * 标题颜色 30 | */ 31 | private int titleColor = Color.argb(255, 69, 121, 212); 32 | /** 33 | * 手指触摸未离开时的按钮背景颜色 34 | */ 35 | private int backgroundHoverColor; 36 | /** 37 | * 手指触摸未离开时的按钮背景Drawable 38 | */ 39 | private Drawable backgroundHoverDrawable; 40 | /** 41 | * 手指触摸未离开时的按钮标题颜色 42 | */ 43 | private int titleHoverColor; 44 | /** 45 | * 触摸的事件 46 | */ 47 | private LemonHelloActionDelegate delegate; 48 | 49 | public LemonHelloAction() { 50 | } 51 | 52 | public LemonHelloAction(String title, LemonHelloActionDelegate delegate) { 53 | this.title = title; 54 | this.delegate = delegate; 55 | } 56 | 57 | public LemonHelloAction(String title, int titleColor, LemonHelloActionDelegate delegate) { 58 | this.title = title; 59 | this.titleColor = titleColor; 60 | this.delegate = delegate; 61 | } 62 | 63 | public LemonHelloAction(String title, int titleColor, int backgroundColor, LemonHelloActionDelegate delegate) { 64 | this.title = title; 65 | this.titleColor = titleColor; 66 | this.backgroundColor = backgroundColor; 67 | this.delegate = delegate; 68 | } 69 | 70 | public LemonHelloAction(String title, int titleColor, Drawable backgroundDrawable, LemonHelloActionDelegate delegate) { 71 | this.title = title; 72 | this.titleColor = titleColor; 73 | this.backgroundDrawable = backgroundDrawable; 74 | this.delegate = delegate; 75 | } 76 | 77 | public String getTitle() { 78 | return title; 79 | } 80 | 81 | public LemonHelloAction setTitle(String title) { 82 | this.title = title; 83 | return this; 84 | } 85 | 86 | public int getBackgroundColor() { 87 | return backgroundColor; 88 | } 89 | 90 | public LemonHelloAction setBackgroundColor(int backgroundColor) { 91 | this.backgroundColor = backgroundColor; 92 | return this; 93 | } 94 | 95 | public Drawable getBackgroundDrawable() { 96 | return backgroundDrawable; 97 | } 98 | 99 | public LemonHelloAction setBackgroundDrawable(Drawable backgroundDrawable) { 100 | this.backgroundDrawable = backgroundDrawable; 101 | return this; 102 | } 103 | 104 | public int getTitleColor() { 105 | return titleColor; 106 | } 107 | 108 | public LemonHelloAction setTitleColor(int titleColor) { 109 | this.titleColor = titleColor; 110 | return this; 111 | } 112 | 113 | public int getBackgroundHoverColor() { 114 | // 先算出原颜色的ARGB值 115 | if (backgroundColor != 0 && backgroundHoverColor == 0) { 116 | final int a = (backgroundColor & 0xff000000) >>> 24; 117 | final int r = Math.max(((backgroundColor & 0x00ff0000) >> 16) - 20, 0); 118 | final int g = Math.max(((backgroundColor & 0x0000ff00) >> 8) - 20, 0); 119 | final int b = Math.max((backgroundColor & 0x000000ff) - 20, 0); 120 | return Color.argb(a, r, g, b); 121 | } 122 | return backgroundHoverColor; 123 | } 124 | 125 | public LemonHelloAction setBackgroundHoverColor(int backgroundHoverColor) { 126 | this.backgroundHoverColor = backgroundHoverColor; 127 | return this; 128 | } 129 | 130 | public Drawable getBackgroundHoverDrawable() { 131 | return backgroundHoverDrawable; 132 | } 133 | 134 | public LemonHelloAction setBackgroundHoverDrawable(Drawable backgroundHoverDrawable) { 135 | this.backgroundHoverDrawable = backgroundHoverDrawable; 136 | return this; 137 | } 138 | 139 | public int getTitleHoverColor() { 140 | return titleHoverColor; 141 | } 142 | 143 | public LemonHelloAction setTitleHoverColor(int titleHoverColor) { 144 | this.titleHoverColor = titleHoverColor; 145 | return this; 146 | } 147 | 148 | public LemonHelloActionDelegate getDelegate() { 149 | return delegate; 150 | } 151 | 152 | public LemonHelloAction setDelegate(LemonHelloActionDelegate delegate) { 153 | this.delegate = delegate; 154 | return this; 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/java/net/lemonsoft/lemonhello/LemonHelloGlobal.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Color; 5 | import android.graphics.drawable.Drawable; 6 | 7 | import net.lemonsoft.lemonhello.enums.LemonHelloIconLocation; 8 | import net.lemonsoft.lemonhello.interfaces.LemonHelloEventDelegate; 9 | import net.lemonsoft.lemonhello.interfaces.LemonPaintContext; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * LemonHello 全局配置类 16 | * Created by LiuRi on 2017/1/12. 17 | */ 18 | 19 | public class LemonHelloGlobal { 20 | 21 | 22 | /** 23 | * 对话框控件的宽度 24 | */ 25 | public static int width = 260; 26 | /** 27 | * 对话框控件的圆角半径 28 | */ 29 | public static int cornerRadius = 8; 30 | /** 31 | * 对话框面板的背景颜色 32 | */ 33 | public static int panelBackgroundColor = Color.argb(245, 255, 255, 255); 34 | /** 35 | * 对话框面板的背景Drawable 36 | */ 37 | public static Drawable panelBackgroundDrawable = null; 38 | /** 39 | * 对话框的背景蒙版颜色 40 | */ 41 | public static int maskColor = Color.argb(180, 0, 0, 0); 42 | /** 43 | * 对话框的图标绘制上下文 44 | * 如果icon属性为空,那么会调用该属性iconPaintContext绘制 45 | * 如果iconPaintContext为空,那么会认为无图标 46 | */ 47 | public static LemonPaintContext iconPaintContext = null; 48 | /** 49 | * 图标动画是否需要重复 50 | */ 51 | public static boolean isIconAnimationRepeat = false; 52 | /** 53 | * 动画的执行的所需时长 54 | */ 55 | public static int animationTime = 400; 56 | /** 57 | * 对话框的图标对象 58 | * 如果该对象为空,那么会调用iconPaintContext绘制 59 | * 如果iconPaintContext为空,那么会认为无图标 60 | */ 61 | public static Bitmap icon = null; 62 | /** 63 | * 图标的宽度 64 | * 图标为正方形,因此宽度也就是高度 65 | */ 66 | public static int iconWidth = 40; 67 | /** 68 | * 图标的位置描述属性 69 | */ 70 | public static LemonHelloIconLocation iconLocation = LemonHelloIconLocation.LEFT; 71 | /** 72 | * 对话框的标题,如果该属性为null或空字符串,那么认为其没有标题 73 | */ 74 | public static String title = "LemonHello"; 75 | /** 76 | * 对话框的正文内容文字 77 | */ 78 | public static String content = "LemonHello Message"; 79 | /** 80 | * 标题文字的颜色 81 | */ 82 | public static int titleColor = Color.BLACK; 83 | /** 84 | * 对话框正文内容文字颜色 85 | */ 86 | public static int contentColor = Color.BLACK; 87 | /** 88 | * 标题文字的字体大小 89 | */ 90 | public static int titleFontSize = 15; 91 | /** 92 | * 对话对征文内容文字字体大小 93 | */ 94 | public static int contentFontSize = 12; 95 | /** 96 | * 标题的按钮文字大小 97 | */ 98 | public static int buttonFontSize = 14; 99 | /** 100 | * 第一行的按钮数量 101 | * 如果超过这个数量,那么每一个Action都会被放到单独的行中 102 | * 如果该数值设置为<1的数字,那么认为该值为1 103 | */ 104 | public static int firstLineButtonCount = 2; 105 | /** 106 | * 是否显示状态栏 107 | */ 108 | public static boolean showStatusBar = true; 109 | /** 110 | * 状态栏的颜色 111 | */ 112 | public static int statusBarColor = Color.BLACK; 113 | /** 114 | * LemonHello的事件代理 115 | */ 116 | public static LemonHelloEventDelegate eventDelegate = null; 117 | /** 118 | * 是否使用消息队列,若您使用了消息队列,那么后通知显示的消息框会在前一个消息框关闭后再显示 119 | */ 120 | public static boolean useMessageQueue = true; 121 | /** 122 | * 控件的内边距 123 | */ 124 | public static int padding = 16; 125 | /** 126 | * 控件的间隙 127 | */ 128 | public static int space = 10; 129 | /** 130 | * action按钮的高度 131 | */ 132 | public static int actionLineHeight = 40; 133 | } 134 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/java/net/lemonsoft/lemonhello/LemonHelloInfo.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.SumPathEffect; 8 | import android.graphics.drawable.Drawable; 9 | import android.text.Layout; 10 | import android.util.TypedValue; 11 | import android.view.Gravity; 12 | import android.view.MotionEvent; 13 | import android.view.View; 14 | import android.view.ViewGroup; 15 | import android.widget.Button; 16 | import android.widget.RelativeLayout; 17 | import android.widget.TextView; 18 | 19 | import net.lemonsoft.lemonhello.enums.LemonHelloIconLocation; 20 | import net.lemonsoft.lemonhello.interfaces.LemonHelloEventDelegate; 21 | import net.lemonsoft.lemonhello.interfaces.LemonPaintContext; 22 | 23 | import java.sql.SQLOutput; 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | import java.util.concurrent.BrokenBarrierException; 27 | 28 | /** 29 | * LemonHello - 样式描述信息模型类 30 | * Created by LiuRi on 2017/1/11. 31 | */ 32 | 33 | public class LemonHelloInfo { 34 | 35 | private LemonHelloPrivateAnimationTool _PAT = LemonHelloPrivateAnimationTool.defaultPrivateAnimationTool(); 36 | private LemonHelloPrivateSizeTool _PST = LemonHelloPrivateSizeTool.getPrivateSizeTool(); 37 | 38 | /** 39 | * 对话框控件的宽度 40 | */ 41 | private int width = LemonHelloGlobal.width; 42 | /** 43 | * 对话框控件的圆角半径 44 | */ 45 | private int cornerRadius = LemonHelloGlobal.cornerRadius; 46 | /** 47 | * 对话框面板的背景颜色 48 | */ 49 | private int panelBackgroundColor = LemonHelloGlobal.panelBackgroundColor; 50 | /** 51 | * 对话框面板的背景Drawable 52 | */ 53 | private Drawable panelBackgroundDrawable = LemonHelloGlobal.panelBackgroundDrawable; 54 | /** 55 | * 对话框的背景蒙版颜色 56 | */ 57 | private int maskColor = LemonHelloGlobal.maskColor; 58 | /** 59 | * 对话框的图标绘制上下文 60 | * 如果icon属性为空,那么会调用该属性iconPaintContext绘制 61 | * 如果iconPaintContext为空,那么会认为无图标 62 | */ 63 | private LemonPaintContext iconPaintContext = LemonHelloGlobal.iconPaintContext; 64 | /** 65 | * 图标动画是否需要重复 66 | */ 67 | private boolean isIconAnimationRepeat = LemonHelloGlobal.isIconAnimationRepeat; 68 | /** 69 | * 动画的执行的所需时长 70 | */ 71 | private int animationTime = LemonHelloGlobal.animationTime; 72 | /** 73 | * 对话框的图标对象 74 | * 如果该对象为空,那么会调用iconPaintContext绘制 75 | * 如果iconPaintContext为空,那么会认为无图标 76 | */ 77 | private Bitmap icon = LemonHelloGlobal.icon; 78 | /** 79 | * 图标的宽度 80 | * 图标为正方形,因此宽度也就是高度 81 | */ 82 | private int iconWidth = LemonHelloGlobal.iconWidth; 83 | /** 84 | * 图标的位置描述属性 85 | */ 86 | private LemonHelloIconLocation iconLocation = LemonHelloGlobal.iconLocation; 87 | /** 88 | * 对话框的标题,如果该属性为null或空字符串,那么认为其没有标题 89 | */ 90 | private String title = LemonHelloGlobal.title; 91 | /** 92 | * 对话框的正文内容文字 93 | */ 94 | private String content = LemonHelloGlobal.content; 95 | /** 96 | * 标题文字的颜色 97 | */ 98 | private int titleColor = LemonHelloGlobal.titleColor; 99 | /** 100 | * 对话框正文内容文字颜色 101 | */ 102 | private int contentColor = LemonHelloGlobal.contentColor; 103 | /** 104 | * 标题文字的字体大小 105 | */ 106 | private int titleFontSize = LemonHelloGlobal.titleFontSize; 107 | /** 108 | * 对话对征文内容文字字体大小 109 | */ 110 | private int contentFontSize = LemonHelloGlobal.contentFontSize; 111 | /** 112 | * 标题的按钮文字大小 113 | */ 114 | private int buttonFontSize = LemonHelloGlobal.buttonFontSize; 115 | /** 116 | * 控件的内边距 117 | */ 118 | private int padding = LemonHelloGlobal.padding; 119 | /** 120 | * 控件的间隙 121 | */ 122 | private int space = LemonHelloGlobal.space; 123 | /** 124 | * action按钮的高度 125 | */ 126 | private int actionLineHeight = LemonHelloGlobal.actionLineHeight; 127 | /** 128 | * 对话框的动画list(按钮说明信息list) 129 | */ 130 | private List actions = new ArrayList<>(); 131 | /** 132 | * 第一行的按钮数量 133 | * 如果超过这个数量,那么每一个Action都会被放到单独的行中 134 | * 如果该数值设置为<1的数字,那么认为该值为1 135 | */ 136 | private int firstLineButtonCount = LemonHelloGlobal.firstLineButtonCount; 137 | /** 138 | * 是否显示状态栏 139 | */ 140 | private boolean showStatusBar = LemonHelloGlobal.showStatusBar; 141 | /** 142 | * 状态栏的颜色 143 | */ 144 | private int statusBarColor = LemonHelloGlobal.statusBarColor; 145 | /** 146 | * LemonHello的事件代理 147 | */ 148 | private LemonHelloEventDelegate eventDelegate = LemonHelloGlobal.eventDelegate; 149 | /** 150 | * 是否使用消息队列,若您使用了消息队列,那么后通知显示的消息框会在前一个消息框关闭后再显示 151 | */ 152 | private boolean useMessageQueue = LemonHelloGlobal.useMessageQueue; 153 | 154 | public int getWidth() { 155 | return width; 156 | } 157 | 158 | public LemonHelloInfo setWidth(int width) { 159 | this.width = width; 160 | return this; 161 | } 162 | 163 | public int getCornerRadius() { 164 | return cornerRadius; 165 | } 166 | 167 | public LemonHelloInfo setCornerRadius(int cornerRadius) { 168 | this.cornerRadius = cornerRadius; 169 | return this; 170 | } 171 | 172 | public int getPanelBackgroundColor() { 173 | return panelBackgroundColor; 174 | } 175 | 176 | public LemonHelloInfo setPanelBackgroundColor(int panelBackgroundColor) { 177 | this.panelBackgroundColor = panelBackgroundColor; 178 | return this; 179 | } 180 | 181 | public Drawable getPanelBackgroundDrawable() { 182 | return panelBackgroundDrawable; 183 | } 184 | 185 | public LemonHelloInfo setPanelBackgroundDrawable(Drawable panelBackgroundDrawable) { 186 | this.panelBackgroundDrawable = panelBackgroundDrawable; 187 | return this; 188 | } 189 | 190 | public int getMaskColor() { 191 | return maskColor; 192 | } 193 | 194 | public LemonHelloInfo setMaskColor(int maskColor) { 195 | this.maskColor = maskColor; 196 | return this; 197 | } 198 | 199 | public LemonPaintContext getIconPaintContext() { 200 | return iconPaintContext; 201 | } 202 | 203 | public LemonHelloInfo setIconPaintContext(LemonPaintContext iconPaintContext) { 204 | this.iconPaintContext = iconPaintContext; 205 | return this; 206 | } 207 | 208 | public boolean isIconAnimationRepeat() { 209 | return isIconAnimationRepeat; 210 | } 211 | 212 | public LemonHelloInfo setIconAnimationRepeat(boolean iconAnimationRepeat) { 213 | isIconAnimationRepeat = iconAnimationRepeat; 214 | return this; 215 | } 216 | 217 | public int getAnimationTime() { 218 | return animationTime; 219 | } 220 | 221 | public LemonHelloInfo setAnimationTime(int animationTime) { 222 | this.animationTime = animationTime; 223 | return this; 224 | } 225 | 226 | public Bitmap getIcon() { 227 | return icon; 228 | } 229 | 230 | public LemonHelloInfo setIcon(Bitmap icon) { 231 | this.icon = icon; 232 | return this; 233 | } 234 | 235 | public int getIconWidth() { 236 | if (icon == null && iconPaintContext == null) 237 | return 0; 238 | return iconWidth; 239 | } 240 | 241 | public LemonHelloInfo setIconWidth(int iconWidth) { 242 | this.iconWidth = iconWidth; 243 | return this; 244 | } 245 | 246 | public LemonHelloIconLocation getIconLocation() { 247 | return iconLocation; 248 | } 249 | 250 | public LemonHelloInfo setIconLocation(LemonHelloIconLocation iconLocation) { 251 | this.iconLocation = iconLocation; 252 | return this; 253 | } 254 | 255 | public String getTitle() { 256 | return title; 257 | } 258 | 259 | public LemonHelloInfo setTitle(String title) { 260 | this.title = title; 261 | return this; 262 | } 263 | 264 | public String getContent() { 265 | return content; 266 | } 267 | 268 | public LemonHelloInfo setContent(String content) { 269 | this.content = content; 270 | return this; 271 | } 272 | 273 | public int getTitleColor() { 274 | return titleColor; 275 | } 276 | 277 | public LemonHelloInfo setTitleColor(int titleColor) { 278 | this.titleColor = titleColor; 279 | return this; 280 | } 281 | 282 | public int getContentColor() { 283 | return contentColor; 284 | } 285 | 286 | public LemonHelloInfo setContentColor(int contentColor) { 287 | this.contentColor = contentColor; 288 | return this; 289 | } 290 | 291 | public int getTitleFontSize() { 292 | return titleFontSize; 293 | } 294 | 295 | public LemonHelloInfo setTitleFontSize(int titleFontSize) { 296 | this.titleFontSize = titleFontSize; 297 | return this; 298 | } 299 | 300 | public int getContentFontSize() { 301 | return contentFontSize; 302 | } 303 | 304 | public LemonHelloInfo setContentFontSize(int contentFontSize) { 305 | this.contentFontSize = contentFontSize; 306 | return this; 307 | } 308 | 309 | public int getButtonFontSize() { 310 | return buttonFontSize; 311 | } 312 | 313 | public LemonHelloInfo setButtonFontSize(int buttonFontSize) { 314 | this.buttonFontSize = buttonFontSize; 315 | return this; 316 | } 317 | 318 | public int getPadding() { 319 | return padding; 320 | } 321 | 322 | public void setPadding(int padding) { 323 | this.padding = padding; 324 | } 325 | 326 | public int getSpace() { 327 | return space; 328 | } 329 | 330 | public LemonHelloInfo setSpace(int space) { 331 | this.space = space; 332 | return this; 333 | } 334 | 335 | public int getActionLineHeight() { 336 | return actionLineHeight; 337 | } 338 | 339 | public LemonHelloInfo setActionLineHeight(int actionLineHeight) { 340 | this.actionLineHeight = actionLineHeight; 341 | return this; 342 | } 343 | 344 | public List getActions() { 345 | return actions; 346 | } 347 | 348 | public LemonHelloInfo setActions(List actions) { 349 | this.actions = actions; 350 | return this; 351 | } 352 | 353 | public LemonHelloInfo addAction(LemonHelloAction... actions) { 354 | for (LemonHelloAction action : actions) 355 | this.actions.add(action); 356 | return this; 357 | } 358 | 359 | public LemonHelloInfo removeAction(LemonHelloAction... actions) { 360 | for (LemonHelloAction action : actions) 361 | if (this.actions.contains(action)) 362 | this.actions.remove(action); 363 | return this; 364 | } 365 | 366 | public LemonHelloInfo removeAllActions() { 367 | this.actions.clear(); 368 | return this; 369 | } 370 | 371 | public int getFirstLineButtonCount() { 372 | return Math.max(firstLineButtonCount, 1); 373 | } 374 | 375 | public LemonHelloInfo setFirstLineButtonCount(int firstLineButtonCount) { 376 | this.firstLineButtonCount = Math.max(firstLineButtonCount, 1); 377 | return this; 378 | } 379 | 380 | public boolean isShowStatusBar() { 381 | return showStatusBar; 382 | } 383 | 384 | public LemonHelloInfo setShowStatusBar(boolean showStatusBar) { 385 | this.showStatusBar = showStatusBar; 386 | return this; 387 | } 388 | 389 | public int getStatusBarColor() { 390 | return statusBarColor; 391 | } 392 | 393 | public LemonHelloInfo setStatusBarColor(int statusBarColor) { 394 | this.statusBarColor = statusBarColor; 395 | return this; 396 | } 397 | 398 | public LemonHelloEventDelegate getEventDelegate() { 399 | return eventDelegate; 400 | } 401 | 402 | public LemonHelloInfo setEventDelegate(LemonHelloEventDelegate eventDelegate) { 403 | this.eventDelegate = eventDelegate; 404 | return this; 405 | } 406 | 407 | public boolean isUseMessageQueue() { 408 | return useMessageQueue; 409 | } 410 | 411 | public LemonHelloInfo setUseMessageQueue(boolean useMessageQueue) { 412 | this.useMessageQueue = useMessageQueue; 413 | return this; 414 | } 415 | 416 | private int getTextViewHeight(TextView textView) { 417 | Paint.FontMetrics fontMetrics = textView.getPaint().getFontMetrics(); 418 | return _PST.pxToDp((int) (fontMetrics.descent - fontMetrics.top)) + 2; 419 | } 420 | 421 | private int measureTextViewHeight(TextView textView, int viewWidth) { 422 | int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(_PST.dpToPx(viewWidth), View.MeasureSpec.AT_MOST); 423 | int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); 424 | textView.measure(widthMeasureSpec, heightMeasureSpec); 425 | return _PST.pxToDp(textView.getMeasuredHeight()); 426 | } 427 | 428 | /** 429 | * 获取textView的文字宽 430 | * 431 | * @param textView 要查询文字宽的标签控件 432 | * @return 获取到的文字宽度数值 433 | */ 434 | private int getTextViewWidth(TextView textView) { 435 | return _PST.pxToDp((int) (textView.getPaint().measureText(textView.getText().toString()))); 436 | } 437 | 438 | /** 439 | * 计算视图的位置等矩形信息 440 | * 441 | * @param helloView 整个对话框HelloView 442 | * @param contentPanel 内容面板 443 | * @param contentLayout 内容面板的布局 444 | * @param paintView 图标显示控件 445 | * @param titleView 标题显示控件 446 | * @param contentView 内容显示控件 447 | * @param actionContainer 事件按钮容器面板 448 | */ 449 | public void calViewsFrame(final LemonHelloView helloView, 450 | LemonHelloPanel contentPanel, 451 | RelativeLayout contentLayout, 452 | LemonPaintView paintView, 453 | TextView titleView, 454 | TextView contentView, 455 | RelativeLayout actionContainer) { 456 | contentPanel.setCornerRadius(cornerRadius); 457 | titleView.setText(title); 458 | contentView.setText(content); 459 | titleView.setTextSize(titleFontSize); 460 | contentView.setTextSize(contentFontSize); 461 | 462 | contentView.setTextSize(contentFontSize); 463 | 464 | int panelHeight, titleWidth, titleHeight, contentWidth, contentHeight, actionsHeight, 465 | titleX, titleY, contentX, contentY, iconX, iconY, actionsY; 466 | panelHeight = titleX = titleY = contentX = iconX = iconY = padding; 467 | 468 | titleWidth = width - padding * 2; 469 | titleHeight = (title == null || title.equals("")) ? 0 : getTextViewHeight(titleView); 470 | contentWidth = width - padding * 2 - (getIconWidth() == 0 ? 0 : space) - getIconWidth(); 471 | 472 | switch (iconLocation) { 473 | case TOP: 474 | iconX = (width - iconWidth) / 2; 475 | contentWidth = width - padding * 2; 476 | titleY += iconWidth + space; 477 | break; 478 | case LEFT: 479 | iconY = titleY + titleHeight + space; 480 | contentX = iconX + iconWidth + space; 481 | break; 482 | case RIGHT: 483 | iconX = width - padding - getIconWidth(); 484 | iconY = titleY + titleHeight + space; 485 | break; 486 | } 487 | 488 | if (getIconWidth() <= 0) 489 | contentX = padding; 490 | 491 | contentHeight = (content == null || content.equals("")) ? 0 : measureTextViewHeight(contentView, contentWidth); 492 | if (contentHeight < getIconWidth() && iconLocation != LemonHelloIconLocation.TOP)// 内容高小于图标的高 493 | contentHeight = getIconWidth(); 494 | contentY = titleY + titleHeight + space; 495 | 496 | actionsY = contentY + contentHeight + space * 2; 497 | actionsHeight = actions.size() <= 0 ? 0 : 498 | actions.size() <= firstLineButtonCount ? 499 | getActionLineHeight() : 500 | getActionLineHeight() * actions.size(); 501 | actionContainer.setBackgroundColor(Color.argb(30, 150, 150, 150)); 502 | panelHeight = actionsY + actionsHeight; 503 | for (int i = 0; i < actions.size(); i++) { 504 | final LemonHelloAction action = actions.get(i); 505 | Button actionView = new Button(actionContainer.getContext()); 506 | actionView.setText(action.getTitle()); 507 | actionView.setTextColor(action.getTitleColor()); 508 | actionView.setBackgroundColor(action.getBackgroundColor()); 509 | actionView.setTextSize(buttonFontSize); 510 | actionView.setGravity(Gravity.CENTER); 511 | actionContainer.addView(actionView); 512 | actionView.setOnClickListener(new View.OnClickListener() { 513 | @Override 514 | public void onClick(View v) { 515 | action.getDelegate().onClick(helloView, LemonHelloInfo.this, action); 516 | } 517 | }); 518 | actionView.setOnTouchListener(new View.OnTouchListener() { 519 | // 设置触摸监听器,设置触摸的颜色变化 520 | @Override 521 | public boolean onTouch(View v, MotionEvent event) { 522 | switch (event.getAction()) { 523 | case MotionEvent.ACTION_DOWN: 524 | v.setBackgroundColor(action.getBackgroundHoverColor()); 525 | break; 526 | case MotionEvent.ACTION_UP: 527 | v.setBackgroundColor(action.getBackgroundColor()); 528 | break; 529 | } 530 | return false; 531 | } 532 | }); 533 | if (actions.size() <= firstLineButtonCount) { 534 | // 横向排列 535 | actionView.setLayoutParams(new RelativeLayout.LayoutParams(_PST.dpToPx(width / actions.size() - 1), _PST.dpToPx(_PST.dpToPx(actionLineHeight - 1)))); 536 | actionView.setX(_PST.dpToPx(i * (width / actions.size()))); 537 | actionView.setY(1); 538 | } else { 539 | // 纵向排列 540 | actionView.setLayoutParams(new RelativeLayout.LayoutParams(_PST.dpToPx(width), _PST.dpToPx(actionLineHeight - 1))); 541 | actionView.setY(_PST.dpToPx(i * actionLineHeight + 1)); 542 | } 543 | } 544 | 545 | contentPanel.setLayoutParams(new RelativeLayout.LayoutParams(_PST.dpToPx((int) (width * 1.1)), _PST.dpToPx((int) (panelHeight * 1.1)))); 546 | contentPanel.setX(_PST.dpToPx((int) (_PST.screenWidthDp() / 2 - width / 2))); 547 | contentPanel.setY(_PST.dpToPx((int) (_PST.screenHeightDp() / 2 - panelHeight / 2))); 548 | 549 | // 使用下面这种特效会让窗口有点颤抖,暂不明原因,待考究 550 | // contentPanel.setX(_PST.dpToPx((int) (_PST.screenWidthDp() / 2 - width * 0.55))); 551 | // contentPanel.setY(_PST.dpToPx((int) (_PST.screenHeightDp() / 2 - panelHeight * 0.55))); 552 | 553 | _PAT.setLocation(contentPanel, (_PST.screenWidthDp() - width) / 2, (_PST.screenHeightDp() - panelHeight) / 2); 554 | 555 | titleView.setX(_PST.dpToPx(titleX)); 556 | titleView.setY(_PST.dpToPx(titleY)); 557 | titleView.setLayoutParams(new RelativeLayout.LayoutParams(_PST.dpToPx(titleWidth), _PST.dpToPx(titleHeight))); 558 | 559 | paintView.setX(_PST.dpToPx(iconX)); 560 | paintView.setY(_PST.dpToPx(iconY)); 561 | paintView.setLayoutParams(new RelativeLayout.LayoutParams(_PST.dpToPx(getIconWidth()), _PST.dpToPx(getIconWidth()))); 562 | 563 | actionContainer.setX(0); 564 | actionContainer.setY(_PST.dpToPx(actionsY)); 565 | actionContainer.setLayoutParams(new RelativeLayout.LayoutParams(_PST.dpToPx(width), _PST.dpToPx(actionsHeight))); 566 | 567 | contentView.setX(_PST.dpToPx(contentX)); 568 | contentView.setY(_PST.dpToPx(contentY)); 569 | contentView.setLayoutParams(new RelativeLayout.LayoutParams(_PST.dpToPx(contentWidth), _PST.dpToPx(contentHeight))); 570 | 571 | contentLayout.setX(_PST.dpToPx((int) (width * 0.05))); 572 | contentLayout.setY(_PST.dpToPx((int) (panelHeight * 0.05))); 573 | contentLayout.setLayoutParams(new RelativeLayout.LayoutParams(_PST.dpToPx(width), _PST.dpToPx(panelHeight))); 574 | 575 | _PAT.setLocation(contentLayout, 0, 0); 576 | 577 | _PAT.setSize(contentPanel, width, panelHeight); 578 | 579 | } 580 | 581 | public void show(Context context) { 582 | LemonHelloView.defaultHelloView().showHelloWithInfo(context, this); 583 | } 584 | 585 | } 586 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/java/net/lemonsoft/lemonhello/LemonHelloInfoPack.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * LemonHello info包 7 | * 在消息队列中使用,包含Context和LemonHelloInfo 8 | * Created by LiuRi on 2017/1/12. 9 | */ 10 | 11 | public class LemonHelloInfoPack { 12 | 13 | private Context context; 14 | private LemonHelloInfo helloInfo; 15 | 16 | public LemonHelloInfoPack(Context context, LemonHelloInfo helloInfo) { 17 | this.context = context; 18 | this.helloInfo = helloInfo; 19 | } 20 | 21 | public Context getContext() { 22 | return context; 23 | } 24 | 25 | public void setContext(Context context) { 26 | this.context = context; 27 | } 28 | 29 | public LemonHelloInfo getHelloInfo() { 30 | return helloInfo; 31 | } 32 | 33 | public void setHelloInfo(LemonHelloInfo helloInfo) { 34 | this.helloInfo = helloInfo; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/java/net/lemonsoft/lemonhello/LemonHelloPanel.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Path; 6 | import android.graphics.RectF; 7 | import android.graphics.Region; 8 | import android.view.MotionEvent; 9 | import android.widget.RelativeLayout; 10 | 11 | /** 12 | * LemonHello 面板控件 13 | * Created by LiuRi on 2017/1/13. 14 | */ 15 | 16 | public class LemonHelloPanel extends RelativeLayout { 17 | 18 | private LemonHelloPrivateSizeTool _PST = LemonHelloPrivateSizeTool.getPrivateSizeTool(); 19 | 20 | public LemonHelloPanel(Context context) { 21 | super(context); 22 | } 23 | 24 | private int cornerRadius = 0; 25 | 26 | public int getCornerRadius() { 27 | return cornerRadius; 28 | } 29 | 30 | public void setCornerRadius(int cornerRadius) { 31 | this.cornerRadius = cornerRadius; 32 | this.postInvalidate(); 33 | } 34 | 35 | @Override 36 | protected void onDraw(Canvas canvas) { 37 | super.onDraw(canvas); 38 | // 需要剪切应显示视图的其余部分 39 | Path path = new Path(); 40 | path.addRoundRect( 41 | new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), 42 | _PST.dpToPx(cornerRadius), 43 | _PST.dpToPx(cornerRadius), 44 | Path.Direction.CW 45 | ); 46 | canvas.clipPath(path, Region.Op.REPLACE); 47 | } 48 | 49 | @Override 50 | public boolean onInterceptHoverEvent(MotionEvent event) { 51 | return super.onInterceptHoverEvent(event); 52 | } 53 | 54 | @Override 55 | public boolean onTouchEvent(MotionEvent event) { 56 | super.onTouchEvent(event); 57 | return true; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/java/net/lemonsoft/lemonhello/LemonHelloPrivateAnimationTool.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello; 2 | 3 | import android.animation.ValueAnimator; 4 | import android.graphics.Color; 5 | import android.graphics.RectF; 6 | import android.graphics.drawable.ColorDrawable; 7 | import android.graphics.drawable.Drawable; 8 | import android.graphics.drawable.ShapeDrawable; 9 | import android.graphics.drawable.shapes.RoundRectShape; 10 | import android.os.Build; 11 | import android.view.View; 12 | import android.widget.RelativeLayout; 13 | 14 | /** 15 | * LemonBubble私有类,该类可以以动画的方式移动控件的位置、大小等外观属性 16 | * 开发者,请你不要在你的项目中尝试调用此类中的方法,你可以在LemonKit中找到更适合你的替代品 17 | * https://github.com/1em0nsOft/LemonKit4Android 18 | * Created by LiuRi on 2016/12/25. 19 | */ 20 | 21 | class LemonHelloPrivateAnimationTool { 22 | 23 | // 私有动画工具类实例变量,单例方法准备 24 | private static LemonHelloPrivateAnimationTool _privateAnimationTool; 25 | // 私有尺寸工具类,该变量仅为了精简代码,代码整洁 26 | private static LemonHelloPrivateSizeTool _PST = LemonHelloPrivateSizeTool.getPrivateSizeTool(); 27 | 28 | // 私有动画工具类的单例方法 29 | static synchronized LemonHelloPrivateAnimationTool defaultPrivateAnimationTool() { 30 | if (_privateAnimationTool == null) 31 | _privateAnimationTool = new LemonHelloPrivateAnimationTool(); 32 | return _privateAnimationTool; 33 | } 34 | 35 | // 根据DP值返回px值,为了简洁易懂代码而写 36 | private int _DP(int value) { 37 | return LemonHelloPrivateSizeTool.getPrivateSizeTool().dpToPx(value); 38 | } 39 | 40 | /** 41 | * 对指定的控件设置尺寸大小 42 | * 43 | * @param view 要设置尺寸的控件 44 | * @param widthDp 宽度,单位dp 45 | * @param heightDp 高度,单位dp 46 | */ 47 | void setSize(final View view, final int widthDp, final int heightDp) { 48 | // 获取整个动画的其实空间宽高 49 | final int startWidth = _PST.pxToDp(view.getLayoutParams() == null ? 0 : view.getLayoutParams().width); 50 | final int startHeight = _PST.pxToDp(view.getLayoutParams() == null ? 0 : view.getLayoutParams().height); 51 | // 计算起始宽高和目标宽高之间的差值 52 | final int subWidth = widthDp - startWidth; 53 | final int subHeight = heightDp - startHeight; 54 | // 创建动画进度处理器,从0-1之间设置动画的进度周期 55 | ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1); 56 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 57 | @Override 58 | public void onAnimationUpdate(ValueAnimator animation) { 59 | // 根据动画执行进度来计算当前进度下宽和高 60 | int currentWidth = (int) ((float) animation.getAnimatedValue() * subWidth + startWidth); 61 | int currentHeight = (int) ((float) animation.getAnimatedValue() * subHeight + startHeight); 62 | // 设置宽和高 63 | view.setLayoutParams( 64 | new RelativeLayout.LayoutParams(_DP(currentWidth), _DP(currentHeight))); 65 | // 刷新界面 66 | view.postInvalidate(); 67 | } 68 | }); 69 | // 启动动画执行器 70 | valueAnimator.start(); 71 | } 72 | 73 | /** 74 | * 设置控件的位置 75 | * 76 | * @param view 要设置位置的控件对象 77 | * @param x 水平x坐标 78 | * @param y 垂直y坐标 79 | */ 80 | void setLocation(final View view, int x, int y) { 81 | // 获取当前控件的初始XY坐标的DP值 82 | final int startX = _PST.pxToDp((int) (view.getX())); 83 | final int startY = _PST.pxToDp((int) (view.getY())); 84 | // 计算起始坐标和结束坐标之间的差值 85 | final int subX = x - startX; 86 | final int subY = y - startY; 87 | // 初始化动画过程处理器 88 | ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1); 89 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 90 | @Override 91 | public void onAnimationUpdate(ValueAnimator animation) { 92 | // 根据动画0-1之间的播放进度计算此时的控件XY坐标位置 93 | view.setX(_DP((int) ((float) animation.getAnimatedValue() * subX + startX))); 94 | view.setY(_DP((int) ((float) animation.getAnimatedValue() * subY + startY))); 95 | view.postInvalidate(); 96 | } 97 | }); 98 | // 开始执行动画 99 | valueAnimator.start(); 100 | } 101 | 102 | /** 103 | * 渐变设置透明度 104 | * 105 | * @param view 设置透明度的控件 106 | * @param alpha 透明度的目标值 107 | */ 108 | void setAlpha(final View view, float alpha) { 109 | // 初始化动画执行器,让值得起始点为当前控件的透明度,目标值为目标透明度 110 | ValueAnimator valueAnimator = ValueAnimator.ofFloat(view.getAlpha(), alpha); 111 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 112 | @Override 113 | public void onAnimationUpdate(ValueAnimator animation) { 114 | // 动态取出当前动画执行器的动画过程值并设置给控件 115 | view.setAlpha((float) animation.getAnimatedValue()); 116 | } 117 | }); 118 | // 启动动画执行器 119 | valueAnimator.start(); 120 | } 121 | 122 | /** 123 | * 动画改变背景颜色 124 | * 125 | * @param view 要改变背景颜色的控件 126 | * @param color 要改变成的目标背景颜色 127 | */ 128 | void setBackgroundColor(final View view, final int cornerRadius, int color) { 129 | int startColor = Color.argb(0, 255, 255, 255); 130 | Drawable drawable = view.getBackground(); 131 | if (drawable instanceof ColorDrawable)// 如果是ColorDrawable,那么通过这种方式取出原始颜色 132 | startColor = ((ColorDrawable) drawable).getColor(); 133 | if (drawable instanceof ShapeDrawable)// 如果是ShapeDrawable,那么通过这种方式取出原始颜色 134 | startColor = ((ShapeDrawable) drawable).getPaint().getColor(); 135 | // 先算出原颜色的ARGB值 136 | final int startA = (startColor & 0xff000000) >>> 24; 137 | final int startR = (startColor & 0x00ff0000) >> 16; 138 | final int startG = (startColor & 0x0000ff00) >> 8; 139 | final int startB = (startColor & 0x000000ff); 140 | // 算出目标颜色的ARGB值 141 | int aimA = (color & 0xff000000) >>> 24; 142 | int aimR = (color & 0x00ff0000) >> 16; 143 | int aimG = (color & 0x0000ff00) >> 8; 144 | int aimB = (color & 0x000000ff); 145 | // 算颜色ARGB的差值 146 | final int subA = aimA - startA; 147 | final int subR = aimR - startR; 148 | final int subG = aimG - startG; 149 | final int subB = aimB - startB; 150 | ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1); 151 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 152 | @Override 153 | public void onAnimationUpdate(ValueAnimator animation) { 154 | // 根据进度来计算当前动画进度下ARGB的四种值并应用修改颜色 155 | int color = Color.argb( 156 | (int) (startA + subA * (float) animation.getAnimatedValue()), 157 | (int) (startR + subR * (float) animation.getAnimatedValue()), 158 | (int) (startG + subG * (float) animation.getAnimatedValue()), 159 | (int) (startB + subB * (float) animation.getAnimatedValue())); 160 | if (cornerRadius == 0)// 如果当前不需要圆角,那么直接设置背景颜色即可 161 | view.setBackgroundColor(color); 162 | else// 如果当前空间设置了圆角,那么还得通过构造圆角背景的方法来创建drawable并设置 163 | setCornerRadius(view, cornerRadius, color); 164 | } 165 | }); 166 | // 开始动画执行器 167 | valueAnimator.start(); 168 | } 169 | 170 | // 设置空间的圆角 171 | void setCornerRadius(View view, int radius, int color) { 172 | radius = _DP(radius); 173 | int borderWidth = 0;// 加边框后会出现空心圆角矩形的效果,所以设置为0 174 | float[] outerRadius = new float[8]; 175 | float[] innerRadius = new float[8]; 176 | for (int i = 0; i < 8; i++) { 177 | outerRadius[i] = radius + borderWidth; 178 | innerRadius[i] = radius; 179 | } 180 | ShapeDrawable shapeDrawable = // 创建图形drawable 181 | new ShapeDrawable( 182 | // 创建圆角矩形 183 | new RoundRectShape(outerRadius, 184 | new RectF(borderWidth, borderWidth, borderWidth, borderWidth), 185 | innerRadius)); 186 | shapeDrawable.getPaint().setColor(color);// 使用指定的颜色绘制,即背景颜色 187 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 188 | // 高版本SDK使用新的API 189 | view.setBackground(shapeDrawable); 190 | } else { 191 | view.setBackgroundDrawable(shapeDrawable); 192 | } 193 | } 194 | 195 | } 196 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/java/net/lemonsoft/lemonhello/LemonHelloPrivateSizeTool.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello; 2 | 3 | import android.content.Context; 4 | import android.util.DisplayMetrics; 5 | import android.view.WindowManager; 6 | 7 | /** 8 | * LemonBubble内私有使用的尺寸工具类 9 | * 开发者,请你不要在你的项目中尝试调用此类中的方法,你可以在LemonKit中找到更适合你的替代品 10 | * https://github.com/1em0nsOft/LemonKit4Android 11 | * Created by LiuRi on 2016/12/23. 12 | */ 13 | 14 | class LemonHelloPrivateSizeTool { 15 | 16 | private float _density; 17 | private DisplayMetrics _metrics; 18 | 19 | private static LemonHelloPrivateSizeTool _privateSizeTool; 20 | 21 | static synchronized LemonHelloPrivateSizeTool getPrivateSizeTool() { 22 | if (_privateSizeTool == null) 23 | _privateSizeTool = new LemonHelloPrivateSizeTool(); 24 | return _privateSizeTool; 25 | } 26 | 27 | void setContext(Context context) { 28 | _density = context.getResources().getDisplayMetrics().density; 29 | _metrics = new DisplayMetrics(); 30 | ((WindowManager) (context.getSystemService(Context.WINDOW_SERVICE))).getDefaultDisplay().getMetrics(_metrics); 31 | } 32 | 33 | /** 34 | * 换算dp到px 35 | * 36 | * @param dpValue dp的数值 37 | * @return 对应的px数值 38 | */ 39 | int dpToPx(int dpValue) { 40 | return (int) (_density * dpValue + 0.5f); 41 | } 42 | 43 | /** 44 | * 换算px到dp 45 | * 46 | * @param pxValue px的数值 47 | * @return 对应的dp数值 48 | */ 49 | int pxToDp(int pxValue) { 50 | return (int) (pxValue / _density + 0.5f); 51 | } 52 | 53 | /** 54 | * 获取屏幕的宽,单位dp 55 | * 56 | * @return 屏幕宽度dp值 57 | */ 58 | int screenWidthDp() { 59 | return pxToDp(_metrics.widthPixels); 60 | } 61 | 62 | /** 63 | * 获取屏幕的高,单位dp 64 | * 65 | * @return 屏幕高度的dp值 66 | */ 67 | int screenHeightDp() { 68 | return pxToDp(_metrics.heightPixels); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/java/net/lemonsoft/lemonhello/LemonHelloView.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.content.DialogInterface; 6 | import android.os.Build; 7 | import android.os.Handler; 8 | import android.view.Gravity; 9 | import android.view.KeyEvent; 10 | import android.view.View; 11 | import android.view.Window; 12 | import android.view.WindowManager; 13 | import android.widget.RelativeLayout; 14 | import android.widget.TableRow; 15 | import android.widget.TextView; 16 | 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | /** 21 | * LemonHello - 容器控件类 22 | * Created by LiuRi on 2017/1/11. 23 | */ 24 | 25 | public class LemonHelloView { 26 | 27 | /** 28 | * 私有Animation工具类 29 | */ 30 | private LemonHelloPrivateAnimationTool _PAT = LemonHelloPrivateAnimationTool.defaultPrivateAnimationTool(); 31 | /** 32 | * 私有Size工具类 33 | */ 34 | private LemonHelloPrivateSizeTool _PST = LemonHelloPrivateSizeTool.getPrivateSizeTool(); 35 | 36 | // 对话框控件的实体控件容器 37 | private Dialog _container; 38 | // 整个dialog全屏的布局容器 39 | private RelativeLayout _rootLayout; 40 | // 对context对象进行存储的变量 41 | private Context _context; 42 | // 当前正在显示的对话框控件的信息对象 43 | private LemonHelloInfo _currentInfo; 44 | // 背景灰色半透明蒙版 45 | private View _backMaskView; 46 | // 包含弹出框真正内容的小布局面板 47 | private LemonHelloPanel _contentPanel; 48 | // 包含弹出框真正内容的小布局面板的内容layout,之所以再套一层是为了动画效果处理起来方便 49 | private RelativeLayout _contentLayout; 50 | // 动画和帧图片显示的控件 51 | private LemonPaintView _paintView; 52 | // 标题显示标签控件 53 | private TextView _titleView; 54 | // 正文内容显示控件 55 | private TextView _contentView; 56 | // action按钮容器布局 57 | private RelativeLayout _actionContainer; 58 | // 当前是否被显示状态 59 | private boolean _isShow; 60 | 61 | // 是否已经初始化过了,避免重新创建控件 62 | private boolean haveInit = false; 63 | 64 | // 用于存储单例对象的变量 65 | private static LemonHelloView _defaultHelloViewObject; 66 | 67 | public boolean isShow() { 68 | return _isShow; 69 | } 70 | 71 | public synchronized void setIsShow(boolean isShow) { 72 | this._isShow = isShow; 73 | } 74 | 75 | /** 76 | * 消息队列,加入消息队列的HelloInfo会陆续的显示,而不是一次性的全部显示在屏幕上 77 | * 当前一个Hello信息框被关闭的时候,下一个信息框才会被弹出 78 | */ 79 | private List queue = new ArrayList<>(); 80 | 81 | /** 82 | * 获取单例Hello控件对象 83 | * 84 | * @return 单例Hello提示框控件实例对象 85 | */ 86 | public static synchronized LemonHelloView defaultHelloView(Context context) { 87 | if (_defaultHelloViewObject == null) 88 | _defaultHelloViewObject = new LemonHelloView(); 89 | return _defaultHelloViewObject; 90 | } 91 | 92 | /** 93 | * 获取单例Hello提示框控件对象 - 调用此方法前提是通过setDefaultContext方法设置了默认的context对象 94 | * 95 | * @return 单例Hello提示框控件实例对象 96 | */ 97 | public static synchronized LemonHelloView defaultHelloView() { 98 | if (_defaultHelloViewObject == null) { 99 | _defaultHelloViewObject = new LemonHelloView(); 100 | } 101 | return _defaultHelloViewObject; 102 | } 103 | 104 | public void showHelloWithInfo(Context context, LemonHelloInfo helloInfo) { 105 | if (isShow() && _currentInfo.isUseMessageQueue()) {// 当前有对话框正在显示中,并且当前HelloInfo支持队列 106 | queue.add(new LemonHelloInfoPack(context, helloInfo)); 107 | return; 108 | } else if (context == null && helloInfo == null && queue.size() > 0) { 109 | // 从队列中读取一个HelloInfo并显示 110 | LemonHelloInfoPack pack = queue.get(0); 111 | queue.remove(0); 112 | if (pack.getContext() != null && !pack.getContext().equals(context)) 113 | haveInit = false; 114 | _context = pack.getContext(); 115 | _currentInfo = pack.getHelloInfo(); 116 | autoInit(_context); 117 | _container.show(); 118 | initContentPanel(_currentInfo);// 根据泡泡信息对象对正文内容面板进行初始化 119 | } else { 120 | // 需要立即将该helloInfo显示出来 121 | if (_context != null && !_context.equals(context)) 122 | haveInit = false; 123 | _context = context; 124 | _currentInfo = helloInfo; 125 | autoInit(_context); 126 | _container.show(); 127 | initContentPanel(_currentInfo);// 根据泡泡信息对象对正文内容面板进行初始化 128 | } 129 | } 130 | 131 | /** 132 | * 自动初始化 133 | * 134 | * @param context 上下文对象 135 | */ 136 | private void autoInit(Context context) { 137 | _context = context; 138 | _PST.setContext(context);// 初始化尺寸工具类 139 | if (!haveInit) { 140 | initContainerAndRootLayout();// 初始化容器和根视图 141 | initCommonView();// 初始化公共的控件 142 | haveInit = true; 143 | } 144 | } 145 | 146 | /** 147 | * 初始化容器与根视图布局 148 | */ 149 | private void initContainerAndRootLayout() { 150 | _container = new Dialog(// 判断是否有状态栏 151 | _context, 152 | _currentInfo.isShowStatusBar() ? 153 | android.R.style.Theme_NoTitleBar : 154 | android.R.style.Theme_NoTitleBar_Fullscreen 155 | );// 创建对话框对象并设置无标题栏主题 156 | if (_currentInfo.isShowStatusBar()) { 157 | Window window = _container.getWindow();// 设置 158 | if (window != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 159 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 160 | window.setStatusBarColor(_currentInfo.getStatusBarColor()); 161 | } 162 | } 163 | _rootLayout = new RelativeLayout(_context);// 实例化根布局对象 164 | Window window = _container.getWindow(); 165 | if (window == null) {// 检测是否成功获取window对象 166 | // 如果为null那么不再继续进行,防止空指针异常 167 | new Exception("Get lemon hello dialog's window error!").printStackTrace(); 168 | return; 169 | } 170 | window.getDecorView().setPadding(0, 0, 0, 0);// 去掉系统默认的与屏幕边缘的内边距 171 | window.setBackgroundDrawableResource(android.R.color.transparent);// 设置背景透明 172 | window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);// 设置窗口全屏 173 | window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);// 防止状态栏更新导致界面卡顿 174 | _container.setContentView(_rootLayout);// 把根视图与对话框相关联 175 | _container.setCanceledOnTouchOutside(false);// 设置背景点击关闭为true 176 | _container.setOnKeyListener(new DialogInterface.OnKeyListener() {// 禁止返回按钮返回 177 | public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { 178 | return keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0; 179 | } 180 | }); 181 | } 182 | 183 | /** 184 | * 初始化公共的控件 185 | */ 186 | private void initCommonView() { 187 | // 实例化灰色半透明蒙版控件 188 | _backMaskView = new View(_context); 189 | _backMaskView.setOnClickListener(new View.OnClickListener() { 190 | @Override 191 | public void onClick(View v) { 192 | if (_currentInfo.getEventDelegate() != null) 193 | _currentInfo.getEventDelegate().onMaskTouch(LemonHelloView.this, _currentInfo); 194 | } 195 | }); 196 | // 设置全屏宽 197 | _backMaskView.setLayoutParams(new RelativeLayout.LayoutParams(_PST.dpToPx(_PST.screenWidthDp()), _PST.dpToPx(_PST.screenHeightDp()))); 198 | _rootLayout.setAlpha(0);// 设置全透明,也就是默认不可见,后期通过动画改变来显示 199 | 200 | // 实例化内容面板控件 201 | _contentPanel = new LemonHelloPanel(_context); 202 | _contentPanel.setX(_PST.dpToPx((int) (_PST.screenWidthDp() / 2.0))); 203 | _contentPanel.setY(_PST.dpToPx((int) (_PST.screenHeightDp() / 2.0))); 204 | 205 | // 实例化内容面板控件的布局 206 | _contentLayout = new RelativeLayout(_context); 207 | 208 | // 实例化绘图动画和帧图片显示的控件 209 | _paintView = new LemonPaintView(_context); 210 | 211 | // 实例化标题显示标签控件 212 | _titleView = new TextView(_context); 213 | _titleView.setX(0); 214 | _titleView.setY(0); 215 | _titleView.setGravity(Gravity.CENTER); 216 | 217 | _contentView = new TextView(_context); 218 | _contentView.setX(0); 219 | _contentView.setY(0); 220 | _contentView.setGravity(Gravity.CENTER); 221 | 222 | _actionContainer = new RelativeLayout(_context); 223 | _actionContainer.setX(0); 224 | _actionContainer.setY(0); 225 | 226 | _contentView.setAlpha(0); 227 | _titleView.setAlpha(0); 228 | _contentPanel.setAlpha(0); 229 | 230 | // 把所有控件添加到根视图上 231 | _rootLayout.addView(_backMaskView);// 半透明灰色背景 232 | _rootLayout.addView(_contentPanel);// 主内容面板 233 | _contentPanel.addView(_contentLayout); 234 | _contentLayout.addView(_paintView);// 动画和帧图标显示控件放置到内容面板上 235 | _contentLayout.addView(_titleView);// 标题显示标签控件放置到内容面板上 236 | _contentLayout.addView(_contentView);// 正文内容显示标签控件放到内容面板上 237 | _contentLayout.addView(_actionContainer);// action事件容器放到内容面板中 238 | } 239 | 240 | /** 241 | * 根据泡泡信息对象初始化内容面板 242 | * 243 | * @param info 泡泡信息对象 244 | */ 245 | private void initContentPanel(final LemonHelloInfo info) { 246 | _paintView.setImageBitmap(null); 247 | _paintView.setHelloInfo(null); 248 | if (info.getIcon() == null) { 249 | // 显示自定义动画 250 | _paintView.setHelloInfo(info); 251 | } else { 252 | // 显示单张图片 253 | _paintView.setImageBitmap(info.getIcon()); 254 | } 255 | // 设置根视图的透明度为1,不透明 256 | _PAT.setAlpha(_rootLayout, 1); 257 | // 动画改变到内容面板的背景颜色到预设值 258 | _PAT.setBackgroundColor(_contentPanel, info.getCornerRadius(), info.getPanelBackgroundColor()); 259 | // 设置内容面板的透明度为1,不透明 260 | _PAT.setAlpha(_contentPanel, 1); 261 | _PAT.setAlpha(_contentView, 1); 262 | _PAT.setAlpha(_titleView, 1); 263 | _titleView.setTextColor(info.getTitleColor()); 264 | // 设置蒙版色 265 | _PAT.setBackgroundColor(_backMaskView, 0, info.getMaskColor()); 266 | // 调用泡泡控件信息对象中的方法来计算面板和图标标题等控件的位置和大小,并动画移动 267 | info.calViewsFrame(LemonHelloView.this, _contentPanel, _contentLayout, _paintView, _titleView, _contentView, _actionContainer); 268 | setIsShow(true); 269 | } 270 | 271 | /** 272 | * 隐藏当前正在显示的泡泡控件 273 | */ 274 | public void hide() { 275 | _PAT.setAlpha(_rootLayout, 0);// 动画设置根视图不透明 276 | _PAT.setAlpha(_contentPanel, 0);// 动画设置内容面板不透明 277 | _PAT.setSize(_contentPanel, _PST.pxToDp((int) (_contentPanel.getMeasuredWidth() * 1.1f)), _PST.pxToDp((int) (_contentPanel.getMeasuredHeight() * 1.1)));// 动画设置面板的大小为0,0 278 | // _PAT.setSize(_paintView, 0, 0);// 动画设置图标动画控件的大小为0,0 279 | // _PAT.setSize(_titleView, 0, 0);// 动画设置标题控件的大小为0,0 280 | // _PAT.setSize(_contentView, 0, 0); 281 | _PAT.setAlpha(_contentView, -5); 282 | _PAT.setAlpha(_paintView, -5); 283 | _PAT.setAlpha(_titleView, -5); 284 | // _PAT.setLocation(_paintView, 0, 0);// 动画设置图标动画控件的坐标为0,0,可以让动画看起来更像是整体缩小 285 | // _PAT.setLocation(_titleView, 0, 0);// 动画设置标题控件的坐标为0,0,可以让动画看起来更像是整体缩小 286 | // _PAT.setLocation(_contentView, 0, 0); 287 | // 把内容面板缩小至屏幕中间 288 | // _PAT.setLocation(_contentPanel, _PST.screenWidthDp() / 2, _PST.screenHeightDp() / 2); 289 | _PAT.setLocation(_contentPanel, _PST.pxToDp((int) (_contentPanel.getX() - _contentPanel.getMeasuredWidth() * 0.05)), _PST.pxToDp((int) (_contentPanel.getY() - _contentPanel.getMeasuredHeight() * 0.05))); 290 | _PAT.setLocation(_contentLayout, _PST.pxToDp((int) (_contentPanel.getMeasuredWidth() * 0.05)), _PST.pxToDp((int) (_contentPanel.getMeasuredHeight() * 0.05))); 291 | setIsShow(false);// 设置当前的状态为不显示状态 292 | new Handler().postDelayed(new Runnable() { 293 | @Override 294 | public void run() { 295 | _container.dismiss(); 296 | setIsShow(false); 297 | if (queue.size() > 0)// 展示队列中的下一个提示框 298 | showHelloWithInfo(null, null); 299 | haveInit = false;// 让其每次彻底关闭后在开启都重新创建对象,防止部分手机按返回键后再次弹出时候闪退 300 | // 如果哪位大神有更好的办法请联系我 liuri@lemonsoft.net 301 | } 302 | }, 300);// 待所有动画处理完毕后关闭根Dialog 303 | } 304 | 305 | /** 306 | * 强制关闭当前正在显示的泡泡控件 307 | */ 308 | public void forceHide() { 309 | _container.dismiss(); 310 | this.haveInit = false; 311 | } 312 | } 313 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/java/net/lemonsoft/lemonhello/LemonPaintView.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello; 2 | 3 | import android.animation.ValueAnimator; 4 | import android.content.Context; 5 | import android.graphics.Canvas; 6 | import android.widget.ImageView; 7 | 8 | /** 9 | * hello中的动画与帧图片展示控件 10 | * Created by LiuRi on 2016/12/24. 11 | */ 12 | 13 | public class LemonPaintView extends ImageView { 14 | 15 | // 保存hello信息对象 16 | private LemonHelloInfo _helloInfo; 17 | // 控制动画播放进度的数值动画器 18 | private ValueAnimator _playProgressValueAnimator; 19 | // 动画播放进度存储变量,0-1之间的浮点数 20 | private float _playProgressValue; 21 | 22 | public LemonPaintView(final Context context) { 23 | super(context); 24 | if (_playProgressValueAnimator != null) // 如果动画执行器变量不是null 25 | _playProgressValueAnimator.end(); // 那么有可能上一次动画执行器的还没执行完,先停止上一次的 26 | else // 如果执行到这里,说明动画执行器对象还为null, 27 | _playProgressValueAnimator = ValueAnimator.ofFloat(0, 1);// 那么创建动画执行器 28 | _playProgressValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 29 | @Override 30 | public void onAnimationUpdate(ValueAnimator valueAnimator) { 31 | _playProgressValue = (float) valueAnimator.getAnimatedValue();// 保存当前的动画进度值 32 | postInvalidate();// 刷新界面(重新调用onDraw方法重绘) 33 | } 34 | }); 35 | } 36 | 37 | public void setHelloInfo(LemonHelloInfo bubbleInfo) { 38 | if (_playProgressValueAnimator != null) 39 | _playProgressValueAnimator.end();// 为了保险起见,先尝试停止上一次的动画执行器 40 | _helloInfo = bubbleInfo;// 保存hello信息对象 41 | if (bubbleInfo != null) {// 如果传进来的不是null,那么开始调用动画执行器,开始播放动画,因为防止在非自定义动画模式下显示自定义动画的最后一帧,所以在这里进行一次判断 42 | 43 | // 这里之所以没用Integer.MAX_VALUE,是因为在Android7.0中有时候有问题,如果谁能知道原因麻烦告诉我一下 44 | // ⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️⤵️ 45 | _playProgressValueAnimator.setRepeatCount(_helloInfo.isIconAnimationRepeat() ? 99999999 : 0);// 根据hello信息对象中设置的是否重复来设置重复次数 46 | _playProgressValueAnimator.start();// 开始播放动画 47 | _playProgressValueAnimator.setDuration(bubbleInfo.getAnimationTime());// 设置单次动画的总执行时间 48 | } 49 | } 50 | 51 | @Override 52 | protected void onDraw(Canvas canvas) { 53 | super.onDraw(canvas); 54 | if (_helloInfo != null && 55 | _helloInfo.getIconPaintContext() != null && 56 | _helloInfo.getIcon() == null)// 判断非空指针才进行操作 57 | _helloInfo.getIconPaintContext().paint(canvas, _playProgressValue);// 调用hello信息对象中的预先设置的绘制函数开始绘制 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/java/net/lemonsoft/lemonhello/adapter/LemonHelloEventDelegateAdapter.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello.adapter; 2 | 3 | import net.lemonsoft.lemonhello.LemonHelloAction; 4 | import net.lemonsoft.lemonhello.LemonHelloInfo; 5 | import net.lemonsoft.lemonhello.LemonHelloView; 6 | import net.lemonsoft.lemonhello.interfaces.LemonHelloEventDelegate; 7 | 8 | /** 9 | * LemonHello 事件代理适配器 10 | * Created by LiuRi on 2017/1/11. 11 | */ 12 | 13 | public abstract class LemonHelloEventDelegateAdapter implements LemonHelloEventDelegate { 14 | 15 | @Override 16 | public void onActionDispatch(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 17 | 18 | } 19 | 20 | @Override 21 | public void onMaskTouch(LemonHelloView helloView, LemonHelloInfo helloInfo) { 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/java/net/lemonsoft/lemonhello/enums/LemonHelloIconLocation.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello.enums; 2 | 3 | /** 4 | * LemonHello - 图标摆放位置枚举 5 | * Created by LiuRi on 2017/1/11. 6 | */ 7 | 8 | public enum LemonHelloIconLocation { 9 | 10 | LEFT(0), 11 | TOP(1), 12 | RIGHT(2); 13 | 14 | private int code; 15 | 16 | LemonHelloIconLocation(int code) { 17 | this.code = code; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/java/net/lemonsoft/lemonhello/interfaces/LemonHelloActionDelegate.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello.interfaces; 2 | 3 | import net.lemonsoft.lemonhello.LemonHelloAction; 4 | import net.lemonsoft.lemonhello.LemonHelloInfo; 5 | import net.lemonsoft.lemonhello.LemonHelloView; 6 | 7 | /** 8 | * LemonHello - 事件回调代理 9 | * Created by LiuRi on 2017/1/11. 10 | */ 11 | 12 | public interface LemonHelloActionDelegate { 13 | 14 | void onClick( 15 | LemonHelloView helloView, 16 | LemonHelloInfo helloInfo, 17 | LemonHelloAction helloAction 18 | ); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/java/net/lemonsoft/lemonhello/interfaces/LemonHelloEventDelegate.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello.interfaces; 2 | 3 | import net.lemonsoft.lemonhello.LemonHello; 4 | import net.lemonsoft.lemonhello.LemonHelloAction; 5 | import net.lemonsoft.lemonhello.LemonHelloInfo; 6 | import net.lemonsoft.lemonhello.LemonHelloView; 7 | 8 | /** 9 | * LemonHello 事件代理 10 | * 处理Action、取消等事件 11 | * Created by LiuRi on 2017/1/11. 12 | */ 13 | 14 | public interface LemonHelloEventDelegate { 15 | 16 | /** 17 | * 事件被触发的回调代理 18 | * 19 | * @param helloView 触发的对话框控件 20 | * @param helloInfo 触发时显示的信息描对象 21 | * @param helloAction 触发的Action 22 | */ 23 | void onActionDispatch( 24 | LemonHelloView helloView, 25 | LemonHelloInfo helloInfo, 26 | LemonHelloAction helloAction 27 | ); 28 | 29 | /** 30 | * 对话框背景蒙版被触摸的回调代理 31 | * 32 | * @param helloView 触发的对话框控件 33 | * @param helloInfo 出发时显示的信息描述对象 34 | */ 35 | void onMaskTouch( 36 | LemonHelloView helloView, 37 | LemonHelloInfo helloInfo 38 | ); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/java/net/lemonsoft/lemonhello/interfaces/LemonPaintContext.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello.interfaces; 2 | 3 | import android.graphics.Canvas; 4 | 5 | /** 6 | * 正式绘制动画的接口 7 | */ 8 | public interface LemonPaintContext { 9 | /** 10 | * 绘制方法 11 | * 12 | * @param canvas 要绘制图形的画布 13 | * @param playProgress 当前动画播放的进度 14 | */ 15 | void paint(Canvas canvas, float playProgress); 16 | } 17 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | LemonHello 3 | 4 | -------------------------------------------------------------------------------- /LemonHello4Android/lemonhello/src/test/java/net/lemonsoft/lemonhello/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package net.lemonsoft.lemonhello; 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() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /LemonHello4Android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':lemonhello-samples', ':lemonhello' 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LemonHello4Android 2 | 妈妈说,问人问题要先说你好,那么咱这个全平台的理论上做的最牛逼的对话框(只是理论上)就叫LemonHello吧~ 3 | 完全可以自定义的UI,内置多种主题提示框。 4 | 5 | > 作者:1em0nsOft - LiuRi 6 | > 7 | > 版本号:1.0.1 8 | > 9 | > 简介:这是一个完全Made in China的炫酷弹出指示层Android版本(-_-#意思就是还有iOS的),他能让你快速的自定义任何样式的弹出框。 10 | > 11 | > **意见建议反馈QQ群:370157608 (还寻思啥呢,赶紧加啊!)** 12 | 13 | 14 | 15 | ![效果图](https://raw.githubusercontent.com/1em0nsOft/LemonHello4Android/master/Resource/LemonHello.gif) 16 | 17 | 18 | 19 | - 怎么样,别光看,我们不妨试试看哦!把LemonHello集成到你的项目中很简单,使用Gradle,首先在你的Project build.gradle文件中(allprojects ->repositories节点)加入如下代码: 20 | 21 | ``` 22 | allprojects { 23 | repositories { 24 | jcenter() 25 | // 加入下面这行 26 | maven { url 'https://jitpack.io' } 27 | } 28 | } 29 | ``` 30 | 31 | 接下来,在你的项目中的Module(xxx e.g:app) build.gradle中(dependencies节点)加入如下代码: 32 | 33 | ``` 34 | dependencies { 35 | // ... 你的其他依赖 36 | // 然后加入下面这行 37 | compile 'com.github.1em0nsOft:LemonHello4Android:1.0.1' 38 | } 39 | ``` 40 | 41 | 最后重新build一下就可以啦。 42 | 43 | 接下来,我们验证一下我们是否集成成功,随便找一个Activity,在onCreate方法里面我们加上如下一段代码来弹出一个对话框试试: 44 | 45 | ``` 46 | LemonHello.getSuccessHello("提示", "恭喜您,集成成功!") 47 | .addAction(new LemonHelloAction("我知道啦", new LemonHelloActionDelegate() { 48 | @Override 49 | public void onClick(LemonHelloView helloView, LemonHelloInfo helloInfo, LemonHelloAction helloAction) { 50 | helloView.hide(); 51 | } 52 | })) 53 | .show(MainActivity.this); 54 | ``` 55 | 56 | 运行一下,你就可以看到你使用LemonHello弹出的第一个对话框咯~集成成功! 57 | 58 | ![集成成功截图](https://raw.githubusercontent.com/1em0nsOft/LemonHello4Android/master/Resource/LemonHelloTest01.png) 59 | 60 | LemonBubble默认带了四中样式,就如我们开头展示的动画里面的前四种,不过呢,你可以自定义其他样式,都可以自定义什么属性呢?给大家列一个列表: 61 | 62 | ``` 63 | // 对话框控件的宽度 64 | width; 65 | 66 | // 对话框控件的圆角半径 67 | cornerRadius; 68 | 69 | // 对话框面板的背景颜色 70 | panelBackgroundColor; 71 | 72 | // 对话框面板的背景Drawable 73 | panelBackgroundDrawable; 74 | 75 | // 对话框的背景蒙版颜色 76 | maskColor; 77 | 78 | // 对话框的图标绘制上下文 79 | // 如果icon属性为空,那么会调用该属性iconPaintContext绘制 80 | // 如果iconPaintContext为空,那么会认为无图标 81 | iconPaintContext; 82 | 83 | // 图标动画是否需要重复 84 | isIconAnimationRepeat; 85 | 86 | // 动画的执行的所需时长 87 | animationTime; 88 | 89 | // 对话框的图标对象 90 | // 如果该对象为空,那么会调用iconPaintContext绘制 91 | // 如果iconPaintContext为空,那么会认为无图标 92 | icon; 93 | 94 | // 图标的宽度 95 | // 图标为正方形,因此宽度也就是高度 96 | iconWidth; 97 | 98 | // 图标的位置描述属性 99 | iconLocation; 100 | 101 | // 对话框的标题,如果该属性为null或空字符串,那么认为其没有标题 102 | title; 103 | 104 | // 对话框的正文内容文字 105 | content; 106 | 107 | // 标题文字的颜色 108 | titleColor; 109 | 110 | // 对话框正文内容文字颜色 111 | contentColor; 112 | 113 | // 标题文字的字体大小 114 | titleFontSize; 115 | 116 | // 对话对征文内容文字字体大小 117 | contentFontSize; 118 | 119 | // 标题的按钮文字大小 120 | buttonFontSize; 121 | 122 | // 控件的内边距 123 | padding; 124 | 125 | // 控件的间隙 126 | space; 127 | 128 | // action按钮的高度 129 | actionLineHeight; 130 | 131 | // 对话框的动画list(按钮说明信息list) 132 | actions 133 | 134 | // 第一行的按钮数量 135 | // 如果超过这个数量,那么每一个Action都会被放到单独的行中 136 | // 如果该数值设置为<1的数字,那么认为该值为1 137 | firstLineButtonCount; 138 | 139 | // 是否显示状态栏 140 | isShowStatusBar; 141 | 142 | // 状态栏的颜色 143 | statusBarColor; 144 | 145 | // LemonHello的事件代理 146 | eventDelegate; 147 | 148 | // 是否使用消息队列,若您使用了消息队列,那么后通知显示的消息框会在前一个消息框关闭后再显示 149 | useMessageQueue 150 | ``` 151 | 152 | 153 | 154 | - 怎么样,够你用吗?我屮艸芔茻,**还不够吗?那你赶紧告诉我,还需要什么场景,我给你加上!!!!** 155 | 156 | ### LemonBubble是一款纯国产、开源、且有售后的提示框控件!有bug,我来改!有需求,我来加!你负责用就行~ 对了,你还有个职责,别忘了点一个star~ 157 | 158 | 159 | 160 | ### **我的废话说完了,你也是不是该来体验一下啦!** -------------------------------------------------------------------------------- /Resource/LemonHello.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LemonITCN/LemonHello4Android/521ce4b1a4ba6f98ddac2cf294d047cb35625b95/Resource/LemonHello.gif -------------------------------------------------------------------------------- /Resource/LemonHelloTest01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LemonITCN/LemonHello4Android/521ce4b1a4ba6f98ddac2cf294d047cb35625b95/Resource/LemonHelloTest01.png --------------------------------------------------------------------------------