From 861101d2e6352b1e4e544a2f1cf5b1da45f05321 Mon Sep 17 00:00:00 2001 From: william Date: Sat, 5 Aug 2023 13:02:59 +0800 Subject: [PATCH 1/5] update gradle --- app/build.gradle | 2 - app/src/main/AndroidManifest.xml | 3 +- .../SampleApplication.java | 4 +- build.gradle | 18 +- gradle.properties | 3 +- gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 282 +++++++++++------- gradlew.bat | 43 +-- taptargetview/build.gradle | 46 ++- 9 files changed, 249 insertions(+), 155 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 98f2293..f1e5eba 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -20,7 +20,5 @@ android { dependencies { implementation project(':taptargetview') - implementation "androidx.appcompat:appcompat:$defAppCompatVersion" implementation "com.google.android.material:material:$defMaterialVersion" - implementation 'com.facebook.stetho:stetho:1.5.0' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index da29f72..57fb085 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,7 +9,8 @@ android:supportsRtl="true" android:theme="@style/AppTheme" android:name=".SampleApplication"> - + diff --git a/app/src/main/java/com/getkeepsafe/taptargetviewsample/SampleApplication.java b/app/src/main/java/com/getkeepsafe/taptargetviewsample/SampleApplication.java index 8df680c..07641a9 100644 --- a/app/src/main/java/com/getkeepsafe/taptargetviewsample/SampleApplication.java +++ b/app/src/main/java/com/getkeepsafe/taptargetviewsample/SampleApplication.java @@ -2,12 +2,12 @@ import android.app.Application; -import com.facebook.stetho.Stetho; +//import com.facebook.stetho.Stetho; public class SampleApplication extends Application { @Override public void onCreate() { super.onCreate(); - Stetho.initializeWithDefaults(this); +// Stetho.initializeWithDefaults(this); } } diff --git a/build.gradle b/build.gradle index 00806cc..f474b23 100644 --- a/build.gradle +++ b/build.gradle @@ -4,18 +4,18 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.2.2' - classpath 'com.vanniktech:gradle-maven-publish-plugin:0.17.0' + classpath 'com.android.tools.build:gradle:7.4.2' + classpath 'com.vanniktech:gradle-maven-publish-plugin:0.25.3' + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.22' } } ext { - defAndroidXCoreVersion = '1.6.0' - defAndroidAnnotationVersion = '1.2.0' - defAppCompatVersion = '1.3.0' - defMaterialVersion = '1.4.0' - defCompileSdkVersion = 30 - defMinSdkVersion = 14 + defAndroidXCoreVersion = '1.10.1' + defAppCompatVersion = '1.6.1' + defMaterialVersion = '1.9.0' + defCompileSdkVersion = 33 + defMinSdkVersion = 21 } allprojects { @@ -25,6 +25,6 @@ allprojects { } } -task clean(type: Delete) { +tasks.register('clean', Delete) { delete rootProject.buildDir } diff --git a/gradle.properties b/gradle.properties index 3902f0f..2be6570 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,4 +22,5 @@ POM_LICENCE_DIST=repo POM_DEVELOPER_ID=keepsafe POM_DEVELOPER_NAME=KeepSafe Software, Inc. -POM_DEVELOPER_URL=https://github.com/KeepSafe/ \ No newline at end of file +POM_DEVELOPER_URL=https://github.com/KeepSafe/ +android.disableAutomaticComponentCreation=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9fe8d05..01ad3fb 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Sat Aug 05 11:39:16 CST 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip diff --git a/gradlew b/gradlew index cccdd3d..3da45c1 100755 --- a/gradlew +++ b/gradlew @@ -1,78 +1,129 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright ? 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions ?$var?, ?${var}?, ?${var:-default}?, ?${var+SET}?, +# ?${var#prefix}?, ?${var%suffix}?, and ?$( cmd )?; +# * compound commands having a testable exit status, especially ?case?; +# * various built-in commands including ?command?, ?set?, and ?ulimit?. +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index e95643d..ac1b06f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/taptargetview/build.gradle b/taptargetview/build.gradle index 85a0f5c..b05c00e 100644 --- a/taptargetview/build.gradle +++ b/taptargetview/build.gradle @@ -1,35 +1,49 @@ -apply plugin: 'com.android.library' -apply plugin: 'com.vanniktech.maven.publish' +plugins { + id 'com.vanniktech.maven.publish' + id 'com.android.library' +} android { - compileSdkVersion defCompileSdkVersion defaultConfig { + compileSdk defCompileSdkVersion minSdkVersion defMinSdkVersion targetSdkVersion defCompileSdkVersion } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } dependencies { - api "androidx.annotation:annotation:$defAndroidAnnotationVersion" - api "androidx.appcompat:appcompat:$defAppCompatVersion" - implementation "androidx.core:core:$defAndroidXCoreVersion" + api("androidx.appcompat:appcompat:$defAppCompatVersion") { + exclude group: 'androidx.core', module: 'core-ktx' + } + implementation ("androidx.core:core:$defAndroidXCoreVersion") { + exclude group: 'androidx.core', module: 'core-ktx' + } + api("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22") { + exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib' + } } // build a jar with source files -task sourcesJar(type: Jar) { +tasks.register('sourcesJar', Jar) { from android.sourceSets.main.java.srcDirs classifier = 'sources' } -task javadoc(type: Javadoc) { - failOnError false +tasks.register('javadoc', Javadoc) { + failOnError false source = android.sourceSets.main.java.sourceFiles classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) } // build a jar with javadoc -task javadocJar(type: Jar, dependsOn: javadoc) { +tasks.register('javadocJar', Jar) { + dependsOn javadoc classifier = 'javadoc' from javadoc.destinationDir } @@ -38,3 +52,15 @@ artifacts { archives sourcesJar archives javadocJar } + +publishing { + publications { + myMaven(MavenPublication) { + groupId 'com.getkeepsafe' + artifactId 'taptargetview' + version '1.13.3' + artifact("$buildDir/outputs/aar/taptargetview-release.aar") + } + } + +} From 0021f8b17f3b8846e95bb05486a55109ede09fdd Mon Sep 17 00:00:00 2001 From: huaweikai <1297720454@qq.com> Date: Sat, 5 Aug 2023 15:27:16 +0800 Subject: [PATCH 2/5] -Replace part of the code with Kotlin --- app/build.gradle | 5 + app/src/main/AndroidManifest.xml | 3 +- .../taptargetviewsample/MainActivity.java | 127 ----- .../taptargetviewsample/MainActivity.kt | 145 +++++ .../SampleApplication.java | 13 - taptargetview/build.gradle | 3 +- .../FloatValueAnimatorBuilder.java | 7 +- .../taptargetview/ReflectExtensions.kt | 12 + .../taptargetview/ReflectUtil.java | 31 -- .../getkeepsafe/taptargetview/TapTarget.java | 502 ------------------ .../getkeepsafe/taptargetview/TapTarget.kt | 441 +++++++++++++++ .../taptargetview/TapTargetSequence.java | 238 --------- .../taptargetview/TapTargetSequence.kt | 146 +++++ .../taptargetview/TapTargetView.java | 125 ++--- .../taptargetview/TargetViewExtensions.kt | 48 ++ .../taptargetview/ToolbarTapTarget.java | 11 +- .../com/getkeepsafe/taptargetview/UiUtil.java | 70 --- .../com/getkeepsafe/taptargetview/UiUtils.kt | 35 ++ .../taptargetview/ViewTapTarget.java | 59 -- .../taptargetview/ViewTapTarget.kt | 38 ++ .../getkeepsafe/taptargetview/ViewUtil.java | 81 --- 21 files changed, 918 insertions(+), 1222 deletions(-) delete mode 100644 app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.java create mode 100644 app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.kt delete mode 100644 app/src/main/java/com/getkeepsafe/taptargetviewsample/SampleApplication.java create mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/ReflectExtensions.kt delete mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/ReflectUtil.java delete mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.java create mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.kt delete mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.java create mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.kt create mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/TargetViewExtensions.kt delete mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/UiUtil.java create mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/UiUtils.kt delete mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewTapTarget.java create mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewTapTarget.kt delete mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewUtil.java diff --git a/app/build.gradle b/app/build.gradle index f1e5eba..084bdf9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' android { compileSdkVersion defCompileSdkVersion @@ -16,6 +17,10 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } dependencies { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 57fb085..9d11093 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -7,8 +7,7 @@ android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" - android:theme="@style/AppTheme" - android:name=".SampleApplication"> + android:theme="@style/AppTheme"> diff --git a/app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.java b/app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.java deleted file mode 100644 index 77e4df6..0000000 --- a/app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.getkeepsafe.taptargetviewsample; - -import android.content.DialogInterface; -import android.graphics.Rect; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import androidx.core.content.ContextCompat; -import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.Toolbar; -import android.text.SpannableString; -import android.text.style.StyleSpan; -import android.text.style.UnderlineSpan; -import android.util.Log; -import android.view.Display; -import android.widget.TextView; -import android.widget.Toast; - -import com.getkeepsafe.taptargetview.TapTarget; -import com.getkeepsafe.taptargetview.TapTargetSequence; -import com.getkeepsafe.taptargetview.TapTargetView; - -public class MainActivity extends AppCompatActivity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); - toolbar.inflateMenu(R.menu.menu_main); - toolbar.setNavigationIcon(ContextCompat.getDrawable(this, R.drawable.ic_arrow_back_white_24dp)); - - // We load a drawable and create a location to show a tap target here - // We need the display to get the width and height at this point in time - final Display display = getWindowManager().getDefaultDisplay(); - // Load our little droid guy - final Drawable droid = ContextCompat.getDrawable(this, R.drawable.ic_android_black_24dp); - // Tell our droid buddy where we want him to appear - final Rect droidTarget = new Rect(0, 0, droid.getIntrinsicWidth() * 2, droid.getIntrinsicHeight() * 2); - // Using deprecated methods makes you look way cool - droidTarget.offset(display.getWidth() / 2, display.getHeight() / 2); - - final SpannableString sassyDesc = new SpannableString("It allows you to go back, sometimes"); - sassyDesc.setSpan(new StyleSpan(Typeface.ITALIC), sassyDesc.length() - "sometimes".length(), sassyDesc.length(), 0); - - // We have a sequence of targets, so lets build it! - final TapTargetSequence sequence = new TapTargetSequence(this) - .targets( - // This tap target will target the back button, we just need to pass its containing toolbar - TapTarget.forToolbarNavigationIcon(toolbar, "This is the back button", sassyDesc).id(1), - // Likewise, this tap target will target the search button - TapTarget.forToolbarMenuItem(toolbar, R.id.search, "This is a search icon", "As you can see, it has gotten pretty dark around here...") - .dimColor(android.R.color.black) - .outerCircleColor(R.color.colorAccent) - .targetCircleColor(android.R.color.black) - .transparentTarget(true) - .textColor(android.R.color.black) - .id(2), - // You can also target the overflow button in your toolbar - TapTarget.forToolbarOverflow(toolbar, "This will show more options", "But they're not useful :(").id(3), - // This tap target will target our droid buddy at the given target rect - TapTarget.forBounds(droidTarget, "Oh look!", "You can point to any part of the screen. You also can't cancel this one!") - .cancelable(false) - .icon(droid) - .id(4) - ) - .listener(new TapTargetSequence.Listener() { - // This listener will tell us when interesting(tm) events happen in regards - // to the sequence - @Override - public void onSequenceFinish() { - ((TextView) findViewById(R.id.educated)).setText("Congratulations! You're educated now!"); - } - - @Override - public void onSequenceStep(TapTarget lastTarget, boolean targetClicked) { - Log.d("TapTargetView", "Clicked on " + lastTarget.id()); - } - - @Override - public void onSequenceCanceled(TapTarget lastTarget) { - final AlertDialog dialog = new AlertDialog.Builder(MainActivity.this) - .setTitle("Uh oh") - .setMessage("You canceled the sequence") - .setPositiveButton("Oops", null).show(); - TapTargetView.showFor(dialog, - TapTarget.forView(dialog.getButton(DialogInterface.BUTTON_POSITIVE), "Uh oh!", "You canceled the sequence at step " + lastTarget.id()) - .cancelable(false) - .tintTarget(false), new TapTargetView.Listener() { - @Override - public void onTargetClick(TapTargetView view) { - super.onTargetClick(view); - dialog.dismiss(); - } - }); - } - }); - - // You don't always need a sequence, and for that there's a single time tap target - final SpannableString spannedDesc = new SpannableString("This is the sample app for TapTargetView"); - spannedDesc.setSpan(new UnderlineSpan(), spannedDesc.length() - "TapTargetView".length(), spannedDesc.length(), 0); - TapTargetView.showFor(this, TapTarget.forView(findViewById(R.id.fab), "Hello, world!", spannedDesc) - .cancelable(false) - .drawShadow(true) - .titleTextDimen(R.dimen.title_text_size) - .tintTarget(false), new TapTargetView.Listener() { - @Override - public void onTargetClick(TapTargetView view) { - super.onTargetClick(view); - // .. which evidently starts the sequence we defined earlier - sequence.start(); - } - - @Override - public void onOuterCircleClick(TapTargetView view) { - super.onOuterCircleClick(view); - Toast.makeText(view.getContext(), "You clicked the outer circle!", Toast.LENGTH_SHORT).show(); - } - - @Override - public void onTargetDismissed(TapTargetView view, boolean userInitiated) { - Log.d("TapTargetViewSample", "You dismissed me :("); - } - }); - } -} diff --git a/app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.kt b/app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.kt new file mode 100644 index 0000000..a13b38d --- /dev/null +++ b/app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.kt @@ -0,0 +1,145 @@ +package com.getkeepsafe.taptargetviewsample + +import android.content.DialogInterface +import android.graphics.Rect +import android.graphics.Typeface +import android.os.Bundle +import android.text.SpannableString +import android.text.style.StyleSpan +import android.text.style.UnderlineSpan +import android.util.Log +import android.view.View +import android.widget.TextView +import android.widget.Toast +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.Toolbar +import androidx.core.content.ContextCompat +import com.getkeepsafe.taptargetview.TapTarget +import com.getkeepsafe.taptargetview.TapTargetSequence +import com.getkeepsafe.taptargetview.TapTargetView +import com.getkeepsafe.taptargetview.showGuideView + +class MainActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + val toolbar = findViewById(R.id.toolbar) as Toolbar + toolbar.inflateMenu(R.menu.menu_main) + toolbar.navigationIcon = + ContextCompat.getDrawable(this, R.drawable.ic_arrow_back_white_24dp) + + // We load a drawable and create a location to show a tap target here + // We need the display to get the width and height at this point in time + val display = windowManager.defaultDisplay + // Load our little droid guy + val droid = ContextCompat.getDrawable(this, R.drawable.ic_android_black_24dp) + // Tell our droid buddy where we want him to appear + val droidTarget = Rect(0, 0, droid!!.intrinsicWidth * 2, droid.intrinsicHeight * 2) + // Using deprecated methods makes you look way cool + droidTarget.offset(display.width / 2, display.height / 2) + val sassyDesc = SpannableString("It allows you to go back, sometimes") + sassyDesc.setSpan( + StyleSpan(Typeface.ITALIC), + sassyDesc.length - "sometimes".length, + sassyDesc.length, + 0 + ) + + // We have a sequence of targets, so lets build it! + val sequence = TapTargetSequence(this) + .addTarget( // This tap target will target the back button, we just need to pass its containing toolbar + TapTarget.forToolbarNavigationIcon(toolbar, "This is the back button", sassyDesc) + .id(1), // Likewise, this tap target will target the search button + TapTarget.forToolbarMenuItem( + toolbar, + R.id.search, + "This is a search icon", + "As you can see, it has gotten pretty dark around here..." + ) + .dimColor(android.R.color.black) + .outerCircleColor(R.color.colorAccent) + .targetCircleColor(android.R.color.black) + .transparentTarget(true) + .textColor(android.R.color.black) + .id(2), // You can also target the overflow button in your toolbar + TapTarget.forToolbarOverflow( + toolbar, + "This will show more options", + "But they're not useful :(" + ).id(3), // This tap target will target our droid buddy at the given target rect + TapTarget.forBounds( + droidTarget, + "Oh look!", + "You can point to any part of the screen. You also can't cancel this one!" + ) + .cancelable(false) + .icon(droid) + .id(4) + ) + .listener(object : TapTargetSequence.Listener { + // This listener will tell us when interesting(tm) events happen in regards + // to the sequence + override fun onSequenceFinish() { + (findViewById(R.id.educated) as TextView).text = + "Congratulations! You're educated now!" + } + + override fun onSequenceStep(lastTarget: TapTarget?, targetClicked: Boolean) { + Log.d("TapTargetView", "Clicked on " + lastTarget!!.id()) + } + + override fun onSequenceCanceled(lastTarget: TapTarget?) { + val dialog = AlertDialog.Builder(this@MainActivity) + .setTitle("Uh oh") + .setMessage("You canceled the sequence") + .setPositiveButton("Oops", null).show() + dialog.showGuideView(TapTarget.forView( + dialog.getButton(DialogInterface.BUTTON_POSITIVE), + "Uh oh!", + "You canceled the sequence at step " + lastTarget?.id() + ) + .cancelable(false) + .tintTarget(false), object : TapTargetView.Listener() { + override fun onTargetClick(view: TapTargetView) { + super.onTargetClick(view) + dialog.dismiss() + } + }) + } + }) + + // You don't always need a sequence, and for that there's a single time tap target + val spannedDesc = SpannableString("This is the sample app for TapTargetView") + spannedDesc.setSpan( + UnderlineSpan(), + spannedDesc.length - "TapTargetView".length, + spannedDesc.length, + 0 + ) + this.showGuideView(TapTarget.forView(findViewById(R.id.fab), "Hello, world!", spannedDesc) + .cancelable(false) + .drawShadow(true) + .titleTextDimen(R.dimen.title_text_size) + .tintTarget(false), object : TapTargetView.Listener() { + override fun onTargetClick(view: TapTargetView) { + super.onTargetClick(view) + // .. which evidently starts the sequence we defined earlier + sequence.start() + } + + override fun onOuterCircleClick(view: TapTargetView) { + super.onOuterCircleClick(view) + Toast.makeText( + view.context, + "You clicked the outer circle!", + Toast.LENGTH_SHORT + ).show() + } + + override fun onTargetDismissed(view: TapTargetView, userInitiated: Boolean) { + Log.d("TapTargetViewSample", "You dismissed me :(") + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/getkeepsafe/taptargetviewsample/SampleApplication.java b/app/src/main/java/com/getkeepsafe/taptargetviewsample/SampleApplication.java deleted file mode 100644 index 07641a9..0000000 --- a/app/src/main/java/com/getkeepsafe/taptargetviewsample/SampleApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.getkeepsafe.taptargetviewsample; - -import android.app.Application; - -//import com.facebook.stetho.Stetho; - -public class SampleApplication extends Application { - @Override - public void onCreate() { - super.onCreate(); -// Stetho.initializeWithDefaults(this); - } -} diff --git a/taptargetview/build.gradle b/taptargetview/build.gradle index b05c00e..cfbacc8 100644 --- a/taptargetview/build.gradle +++ b/taptargetview/build.gradle @@ -1,6 +1,7 @@ plugins { id 'com.vanniktech.maven.publish' id 'com.android.library' + id 'kotlin-android' } android { @@ -21,7 +22,7 @@ dependencies { api("androidx.appcompat:appcompat:$defAppCompatVersion") { exclude group: 'androidx.core', module: 'core-ktx' } - implementation ("androidx.core:core:$defAndroidXCoreVersion") { + implementation ("androidx.core:core-ktx:$defAndroidXCoreVersion") { exclude group: 'androidx.core', module: 'core-ktx' } api("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22") { diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/FloatValueAnimatorBuilder.java b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/FloatValueAnimatorBuilder.java index 6389158..6382721 100644 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/FloatValueAnimatorBuilder.java +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/FloatValueAnimatorBuilder.java @@ -69,12 +69,7 @@ public FloatValueAnimatorBuilder repeat(int times) { } public FloatValueAnimatorBuilder onUpdate(final UpdateListener listener) { - animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - listener.onUpdate((float) animation.getAnimatedValue()); - } - }); + animator.addUpdateListener(animation -> listener.onUpdate((float) animation.getAnimatedValue())); return this; } diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ReflectExtensions.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ReflectExtensions.kt new file mode 100644 index 0000000..6ab870f --- /dev/null +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ReflectExtensions.kt @@ -0,0 +1,12 @@ +@file:JvmName("ReflectExtensions") +package com.getkeepsafe.taptargetview + +import kotlin.jvm.Throws + +@Throws(NoSuchFieldException::class, IllegalAccessException::class) +fun Any?.getPrivateField(fieldName: String?): Any? { + if (fieldName == null || this == null) return null + val field = this.javaClass.getDeclaredField(fieldName) + field.isAccessible = true + return field.get(this) +} \ No newline at end of file diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ReflectUtil.java b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ReflectUtil.java deleted file mode 100644 index c9d84af..0000000 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ReflectUtil.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright 2016 Keepsafe Software, Inc. - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.getkeepsafe.taptargetview; - -import java.lang.reflect.Field; - -class ReflectUtil { - ReflectUtil() { - } - - /** Returns the value of the given private field from the source object **/ - static Object getPrivateField(Object source, String fieldName) - throws NoSuchFieldException, IllegalAccessException { - final Field objectField = source.getClass().getDeclaredField(fieldName); - objectField.setAccessible(true); - return objectField.get(source); - } -} diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.java b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.java deleted file mode 100644 index aeb0ab9..0000000 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.java +++ /dev/null @@ -1,502 +0,0 @@ -/** - * Copyright 2016 Keepsafe Software, Inc. - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.getkeepsafe.taptargetview; - -import android.content.Context; -import android.graphics.Rect; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import androidx.annotation.ColorInt; -import androidx.annotation.ColorRes; -import androidx.annotation.DimenRes; -import androidx.annotation.IdRes; -import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; -import androidx.appcompat.widget.Toolbar; -import android.view.View; - -/** - * Describes the properties and options for a {@link TapTargetView}. - *

- * Each tap target describes a target via a pair of bounds and icon. The bounds dictate the - * location and touch area of the target, where the icon is what will be drawn within the center of - * the bounds. - *

- * This class can be extended to support various target types. - * - * @see ViewTapTarget ViewTapTarget for targeting standard Android views - */ -public class TapTarget { - final CharSequence title; - @Nullable - final CharSequence description; - - float outerCircleAlpha = 0.96f; - int targetRadius = 44; - - Rect bounds; - Drawable icon; - Typeface titleTypeface; - Typeface descriptionTypeface; - - @ColorRes - private int outerCircleColorRes = -1; - @ColorRes - private int targetCircleColorRes = -1; - @ColorRes - private int dimColorRes = -1; - @ColorRes - private int titleTextColorRes = -1; - @ColorRes - private int descriptionTextColorRes = -1; - - private Integer outerCircleColor = null; - private Integer targetCircleColor = null; - private Integer dimColor = null; - private Integer titleTextColor = null; - private Integer descriptionTextColor = null; - - @DimenRes - private int titleTextDimen = -1; - @DimenRes - private int descriptionTextDimen = -1; - - private int titleTextSize = 20; - private int descriptionTextSize = 18; - int id = -1; - - boolean drawShadow = false; - boolean cancelable = true; - boolean tintTarget = true; - boolean transparentTarget = false; - float descriptionTextAlpha = 0.54f; - - /** - * Return a tap target for the overflow button from the given toolbar - *

- * Note: This is currently experimental, use at your own risk - */ - public static TapTarget forToolbarOverflow(Toolbar toolbar, CharSequence title) { - return forToolbarOverflow(toolbar, title, null); - } - - /** Return a tap target for the overflow button from the given toolbar - *

- * Note: This is currently experimental, use at your own risk - */ - public static TapTarget forToolbarOverflow(Toolbar toolbar, CharSequence title, - @Nullable CharSequence description) { - return new ToolbarTapTarget(toolbar, false, title, description); - } - - /** Return a tap target for the overflow button from the given toolbar - *

- * Note: This is currently experimental, use at your own risk - */ - public static TapTarget forToolbarOverflow(android.widget.Toolbar toolbar, CharSequence title) { - return forToolbarOverflow(toolbar, title, null); - } - - /** Return a tap target for the overflow button from the given toolbar - *

- * Note: This is currently experimental, use at your own risk - */ - public static TapTarget forToolbarOverflow(android.widget.Toolbar toolbar, CharSequence title, - @Nullable CharSequence description) { - return new ToolbarTapTarget(toolbar, false, title, description); - } - - /** Return a tap target for the navigation button (back, up, etc) from the given toolbar **/ - public static TapTarget forToolbarNavigationIcon(Toolbar toolbar, CharSequence title) { - return forToolbarNavigationIcon(toolbar, title, null); - } - - /** Return a tap target for the navigation button (back, up, etc) from the given toolbar **/ - public static TapTarget forToolbarNavigationIcon(Toolbar toolbar, CharSequence title, - @Nullable CharSequence description) { - return new ToolbarTapTarget(toolbar, true, title, description); - } - - /** Return a tap target for the navigation button (back, up, etc) from the given toolbar **/ - public static TapTarget forToolbarNavigationIcon(android.widget.Toolbar toolbar, CharSequence title) { - return forToolbarNavigationIcon(toolbar, title, null); - } - - /** Return a tap target for the navigation button (back, up, etc) from the given toolbar **/ - public static TapTarget forToolbarNavigationIcon(android.widget.Toolbar toolbar, CharSequence title, - @Nullable CharSequence description) { - return new ToolbarTapTarget(toolbar, true, title, description); - } - - /** Return a tap target for the menu item from the given toolbar **/ - public static TapTarget forToolbarMenuItem(Toolbar toolbar, @IdRes int menuItemId, - CharSequence title) { - return forToolbarMenuItem(toolbar, menuItemId, title, null); - } - - /** Return a tap target for the menu item from the given toolbar **/ - public static TapTarget forToolbarMenuItem(Toolbar toolbar, @IdRes int menuItemId, - CharSequence title, @Nullable CharSequence description) { - return new ToolbarTapTarget(toolbar, menuItemId, title, description); - } - - /** Return a tap target for the menu item from the given toolbar **/ - public static TapTarget forToolbarMenuItem(android.widget.Toolbar toolbar, @IdRes int menuItemId, - CharSequence title) { - return forToolbarMenuItem(toolbar, menuItemId, title, null); - } - - /** Return a tap target for the menu item from the given toolbar **/ - public static TapTarget forToolbarMenuItem(android.widget.Toolbar toolbar, @IdRes int menuItemId, - CharSequence title, @Nullable CharSequence description) { - return new ToolbarTapTarget(toolbar, menuItemId, title, description); - } - - /** Return a tap target for the specified view **/ - public static TapTarget forView(View view, CharSequence title) { - return forView(view, title, null); - } - - /** Return a tap target for the specified view **/ - public static TapTarget forView(View view, CharSequence title, @Nullable CharSequence description) { - return new ViewTapTarget(view, title, description); - } - - /** Return a tap target for the specified bounds **/ - public static TapTarget forBounds(Rect bounds, CharSequence title) { - return forBounds(bounds, title, null); - } - - /** Return a tap target for the specified bounds **/ - public static TapTarget forBounds(Rect bounds, CharSequence title, @Nullable CharSequence description) { - return new TapTarget(bounds, title, description); - } - - protected TapTarget(Rect bounds, CharSequence title, @Nullable CharSequence description) { - this(title, description); - if (bounds == null) { - throw new IllegalArgumentException("Cannot pass null bounds or title"); - } - - this.bounds = bounds; - } - - protected TapTarget(CharSequence title, @Nullable CharSequence description) { - if (title == null) { - throw new IllegalArgumentException("Cannot pass null title"); - } - - this.title = title; - this.description = description; - } - - /** Specify whether the target should be transparent **/ - public TapTarget transparentTarget(boolean transparent) { - this.transparentTarget = transparent; - return this; - } - - /** Specify the color resource for the outer circle **/ - public TapTarget outerCircleColor(@ColorRes int color) { - this.outerCircleColorRes = color; - return this; - } - - /** Specify the color value for the outer circle **/ - // TODO(Hilal): In v2, this API should be cleaned up / torched - public TapTarget outerCircleColorInt(@ColorInt int color) { - this.outerCircleColor = color; - return this; - } - - /** Specify the alpha value [0.0, 1.0] of the outer circle **/ - public TapTarget outerCircleAlpha(float alpha) { - if (alpha < 0.0f || alpha > 1.0f) { - throw new IllegalArgumentException("Given an invalid alpha value: " + alpha); - } - this.outerCircleAlpha = alpha; - return this; - } - - /** Specify the color resource for the target circle **/ - public TapTarget targetCircleColor(@ColorRes int color) { - this.targetCircleColorRes = color; - return this; - } - - /** Specify the color value for the target circle **/ - // TODO(Hilal): In v2, this API should be cleaned up / torched - public TapTarget targetCircleColorInt(@ColorInt int color) { - this.targetCircleColor = color; - return this; - } - - /** Specify the color resource for all text **/ - public TapTarget textColor(@ColorRes int color) { - this.titleTextColorRes = color; - this.descriptionTextColorRes = color; - return this; - } - - /** Specify the color value for all text **/ - // TODO(Hilal): In v2, this API should be cleaned up / torched - public TapTarget textColorInt(@ColorInt int color) { - this.titleTextColor = color; - this.descriptionTextColor = color; - return this; - } - - /** Specify the color resource for the title text **/ - public TapTarget titleTextColor(@ColorRes int color) { - this.titleTextColorRes = color; - return this; - } - - /** Specify the color value for the title text **/ - // TODO(Hilal): In v2, this API should be cleaned up / torched - public TapTarget titleTextColorInt(@ColorInt int color) { - this.titleTextColor = color; - return this; - } - - /** Specify the color resource for the description text **/ - public TapTarget descriptionTextColor(@ColorRes int color) { - this.descriptionTextColorRes = color; - return this; - } - - /** Specify the color value for the description text **/ - // TODO(Hilal): In v2, this API should be cleaned up / torched - public TapTarget descriptionTextColorInt(@ColorInt int color) { - this.descriptionTextColor = color; - return this; - } - - /** Specify the typeface for all text **/ - public TapTarget textTypeface(Typeface typeface) { - if (typeface == null) throw new IllegalArgumentException("Cannot use a null typeface"); - titleTypeface = typeface; - descriptionTypeface = typeface; - return this; - } - - /** Specify the typeface for title text **/ - public TapTarget titleTypeface(Typeface titleTypeface) { - if (titleTypeface == null) throw new IllegalArgumentException("Cannot use a null typeface"); - this.titleTypeface = titleTypeface; - return this; - } - - /** Specify the typeface for description text **/ - public TapTarget descriptionTypeface(Typeface descriptionTypeface) { - if (descriptionTypeface == null) throw new IllegalArgumentException("Cannot use a null typeface"); - this.descriptionTypeface = descriptionTypeface; - return this; - } - - /** Specify the text size for the title in SP **/ - public TapTarget titleTextSize(int sp) { - if (sp < 0) throw new IllegalArgumentException("Given negative text size"); - this.titleTextSize = sp; - return this; - } - - /** Specify the text size for the description in SP **/ - public TapTarget descriptionTextSize(int sp) { - if (sp < 0) throw new IllegalArgumentException("Given negative text size"); - this.descriptionTextSize = sp; - return this; - } - - /** - * Specify the text size for the title via a dimen resource - *

- * Note: If set, this value will take precedence over the specified sp size - */ - public TapTarget titleTextDimen(@DimenRes int dimen) { - this.titleTextDimen = dimen; - return this; - } - - /** Specify the alpha value [0.0, 1.0] of the description text **/ - public TapTarget descriptionTextAlpha(float descriptionTextAlpha) { - if (descriptionTextAlpha < 0 || descriptionTextAlpha > 1f) { - throw new IllegalArgumentException("Given an invalid alpha value: " + descriptionTextAlpha); - } - this.descriptionTextAlpha = descriptionTextAlpha; - return this; - } - - /** - * Specify the text size for the description via a dimen resource - *

- * Note: If set, this value will take precedence over the specified sp size - */ - public TapTarget descriptionTextDimen(@DimenRes int dimen) { - this.descriptionTextDimen = dimen; - return this; - } - - /** - * Specify the color resource to use as a dim effect - *

- * Note: The given color will have its opacity modified to 30% automatically - */ - public TapTarget dimColor(@ColorRes int color) { - this.dimColorRes = color; - return this; - } - - /** - * Specify the color value to use as a dim effect - *

- * Note: The given color will have its opacity modified to 30% automatically - */ - // TODO(Hilal): In v2, this API should be cleaned up / torched - public TapTarget dimColorInt(@ColorInt int color) { - this.dimColor = color; - return this; - } - - /** Specify whether or not to draw a drop shadow around the outer circle **/ - public TapTarget drawShadow(boolean draw) { - this.drawShadow = draw; - return this; - } - - /** Specify whether or not the target should be cancelable **/ - public TapTarget cancelable(boolean status) { - this.cancelable = status; - return this; - } - - /** Specify whether to tint the target's icon with the outer circle's color **/ - public TapTarget tintTarget(boolean tint) { - this.tintTarget = tint; - return this; - } - - /** Specify the icon that will be drawn in the center of the target bounds **/ - public TapTarget icon(Drawable icon) { - return icon(icon, false); - } - - /** - * Specify the icon that will be drawn in the center of the target bounds - * @param hasSetBounds Whether the drawable already has its bounds correctly set. If the - * drawable does not have its bounds set, then the following bounds will - * be applied:
- * (0, 0, intrinsic-width, intrinsic-height) - */ - public TapTarget icon(Drawable icon, boolean hasSetBounds) { - if (icon == null) throw new IllegalArgumentException("Cannot use null drawable"); - this.icon = icon; - - if (!hasSetBounds) { - this.icon.setBounds(new Rect(0, 0, this.icon.getIntrinsicWidth(), this.icon.getIntrinsicHeight())); - } - - return this; - } - - /** Specify a unique identifier for this target. **/ - public TapTarget id(int id) { - this.id = id; - return this; - } - - /** Specify the target radius in dp. **/ - public TapTarget targetRadius(int targetRadius) { - this.targetRadius = targetRadius; - return this; - } - - /** Return the id associated with this tap target **/ - public int id() { - return id; - } - - /** - * In case your target needs time to be ready (laid out in your view, not created, etc), the - * runnable passed here will be invoked when the target is ready. - */ - public void onReady(Runnable runnable) { - runnable.run(); - } - - /** - * Returns the target bounds. Throws an exception if they are not set - * (target may not be ready) - *

- * This will only be called internally when {@link #onReady(Runnable)} invokes its runnable - */ - public Rect bounds() { - if (bounds == null) { - throw new IllegalStateException("Requesting bounds that are not set! Make sure your target is ready"); - } - return bounds; - } - - @Nullable - Integer outerCircleColorInt(Context context) { - return colorResOrInt(context, outerCircleColor, outerCircleColorRes); - } - - @Nullable - Integer targetCircleColorInt(Context context) { - return colorResOrInt(context, targetCircleColor, targetCircleColorRes); - } - - @Nullable - Integer dimColorInt(Context context) { - return colorResOrInt(context, dimColor, dimColorRes); - } - - @Nullable - Integer titleTextColorInt(Context context) { - return colorResOrInt(context, titleTextColor, titleTextColorRes); - } - - @Nullable - Integer descriptionTextColorInt(Context context) { - return colorResOrInt(context, descriptionTextColor, descriptionTextColorRes); - } - - int titleTextSizePx(Context context) { - return dimenOrSize(context, titleTextSize, titleTextDimen); - } - - int descriptionTextSizePx(Context context) { - return dimenOrSize(context, descriptionTextSize, descriptionTextDimen); - } - - @Nullable - private Integer colorResOrInt(Context context, @Nullable Integer value, @ColorRes int resource) { - if (resource != -1) { - return ContextCompat.getColor(context, resource); - } - - return value; - } - - private int dimenOrSize(Context context, int size, @DimenRes int dimen) { - if (dimen != -1) { - return context.getResources().getDimensionPixelSize(dimen); - } - - return UiUtil.sp(context, size); - } -} diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.kt new file mode 100644 index 0000000..58157f1 --- /dev/null +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.kt @@ -0,0 +1,441 @@ +@file:Suppress("unused") +package com.getkeepsafe.taptargetview + +import android.content.Context +import android.graphics.Rect +import android.graphics.Typeface +import android.graphics.drawable.Drawable +import android.view.View +import androidx.annotation.ColorInt +import androidx.annotation.ColorRes +import androidx.annotation.DimenRes +import androidx.annotation.IdRes +import androidx.appcompat.widget.Toolbar +import androidx.core.content.ContextCompat + +open class TapTarget protected constructor(title: CharSequence?, description: CharSequence?) { + val title: CharSequence + val description: CharSequence? + var outerCircleAlpha = 0.96f + var targetRadius = 44 + var bounds: Rect? = null + var icon: Drawable? = null + var titleTypeface: Typeface? = null + var descriptionTypeface: Typeface? = null + + @ColorRes + private var outerCircleColorRes = -1 + + @ColorRes + private var targetCircleColorRes = -1 + + @ColorRes + private var dimColorRes = -1 + + @ColorRes + private var titleTextColorRes = -1 + + @ColorRes + private var descriptionTextColorRes = -1 + private var outerCircleColor: Int? = null + private var targetCircleColor: Int? = null + private var dimColor: Int? = null + private var titleTextColor: Int? = null + private var descriptionTextColor: Int? = null + + @DimenRes + private var titleTextDimen = -1 + + @DimenRes + private var descriptionTextDimen = -1 + private var titleTextSize = 20 + private var descriptionTextSize = 18 + private var id = -1 + var drawShadow = false + var cancelable = true + var tintTarget = true + var transparentTarget = false + var descriptionTextAlpha = 0.54f + + protected constructor( + bounds: Rect?, + title: CharSequence?, + description: CharSequence? + ): this(title, description) { + requireNotNull(bounds) { "Cannot pass null bounds or title" } + this.bounds = bounds + } + + init { + requireNotNull(title) { "Cannot pass null title" } + this.title = title + this.description = description + } + + /** Specify whether the target should be transparent */ + fun transparentTarget(transparent: Boolean): TapTarget { + transparentTarget = transparent + return this + } + + /** Specify the color resource for the outer circle */ + fun outerCircleColor(@ColorRes color: Int): TapTarget { + outerCircleColorRes = color + return this + } + + /** Specify the color value for the outer circle */ + fun outerCircleColorInt(@ColorInt color: Int): TapTarget { + outerCircleColor = color + return this + } + + /** Specify the alpha value [0.0, 1.0] of the outer circle */ + fun outerCircleAlpha(alpha: Float): TapTarget { + require(!(alpha < 0.0f || alpha > 1.0f)) { "Given an invalid alpha value: $alpha" } + outerCircleAlpha = alpha + return this + } + + /** Specify the color resource for the target circle */ + fun targetCircleColor(@ColorRes color: Int): TapTarget { + targetCircleColorRes = color + return this + } + + /** Specify the color value for the target circle */ + fun targetCircleColorInt(@ColorInt color: Int): TapTarget { + targetCircleColor = color + return this + } + + /** Specify the color resource for all text */ + fun textColor(@ColorRes color: Int): TapTarget { + titleTextColorRes = color + descriptionTextColorRes = color + return this + } + + /** Specify the color value for all text */ + fun textColorInt(@ColorInt color: Int): TapTarget { + titleTextColor = color + descriptionTextColor = color + return this + } + + /** Specify the color resource for the title text */ + fun titleTextColor(@ColorRes color: Int): TapTarget { + titleTextColorRes = color + return this + } + + /** Specify the color value for the title text */ + fun titleTextColorInt(@ColorInt color: Int): TapTarget { + titleTextColor = color + return this + } + + /** Specify the color resource for the description text */ + fun descriptionTextColor(@ColorRes color: Int): TapTarget { + descriptionTextColorRes = color + return this + } + + /** Specify the color value for the description text */ + fun descriptionTextColorInt(@ColorInt color: Int): TapTarget { + descriptionTextColor = color + return this + } + + /** Specify the typeface for all text */ + fun textTypeface(typeface: Typeface?): TapTarget { + requireNotNull(typeface) { "Cannot use a null typeface" } + titleTypeface = typeface + descriptionTypeface = typeface + return this + } + + /** Specify the typeface for title text */ + fun titleTypeface(titleTypeface: Typeface?): TapTarget { + requireNotNull(titleTypeface) { "Cannot use a null typeface" } + this.titleTypeface = titleTypeface + return this + } + + /** Specify the typeface for description text */ + fun descriptionTypeface(descriptionTypeface: Typeface?): TapTarget { + requireNotNull(descriptionTypeface) { "Cannot use a null typeface" } + this.descriptionTypeface = descriptionTypeface + return this + } + + /** Specify the text size for the title in SP */ + fun titleTextSize(sp: Int): TapTarget { + require(sp >= 0) { "Given negative text size" } + titleTextSize = sp + return this + } + + /** Specify the text size for the description in SP */ + fun descriptionTextSize(sp: Int): TapTarget { + require(sp >= 0) { "Given negative text size" } + descriptionTextSize = sp + return this + } + + /** + * Specify the text size for the title via a dimen resource + * + * + * Note: If set, this value will take precedence over the specified sp size + */ + fun titleTextDimen(@DimenRes dimen: Int): TapTarget { + titleTextDimen = dimen + return this + } + + /** Specify the alpha value [0.0, 1.0] of the description text */ + fun descriptionTextAlpha(descriptionTextAlpha: Float): TapTarget { + require(!(descriptionTextAlpha < 0 || descriptionTextAlpha > 1f)) { "Given an invalid alpha value: $descriptionTextAlpha" } + this.descriptionTextAlpha = descriptionTextAlpha + return this + } + + /** + * Specify the text size for the description via a dimen resource + * + * + * Note: If set, this value will take precedence over the specified sp size + */ + fun descriptionTextDimen(@DimenRes dimen: Int): TapTarget { + descriptionTextDimen = dimen + return this + } + + /** + * Specify the color resource to use as a dim effect + * + * + * **Note:** The given color will have its opacity modified to 30% automatically + */ + fun dimColor(@ColorRes color: Int): TapTarget { + dimColorRes = color + return this + } + + /** + * Specify the color value to use as a dim effect + * + * + * **Note:** The given color will have its opacity modified to 30% automatically + */ + fun dimColorInt(@ColorInt color: Int): TapTarget { + dimColor = color + return this + } + + /** Specify whether or not to draw a drop shadow around the outer circle */ + fun drawShadow(draw: Boolean): TapTarget { + drawShadow = draw + return this + } + + /** Specify whether or not the target should be cancelable */ + fun cancelable(status: Boolean): TapTarget { + cancelable = status + return this + } + + /** Specify whether to tint the target's icon with the outer circle's color */ + fun tintTarget(tint: Boolean): TapTarget { + tintTarget = tint + return this + } + /** + * Specify the icon that will be drawn in the center of the target bounds + * @param hasSetBounds Whether the drawable already has its bounds correctly set. If the + * drawable does not have its bounds set, then the following bounds will + * be applied:

+ * `(0, 0, intrinsic-width, intrinsic-height)` + */ + @JvmOverloads + fun icon(icon: Drawable?, hasSetBounds: Boolean = false): TapTarget { + requireNotNull(icon) { "Cannot use null drawable" } + this.icon = icon + if (!hasSetBounds) { + icon.bounds = Rect(0, 0, icon.intrinsicWidth, icon.intrinsicHeight) + } + return this + } + + /** Specify a unique identifier for this target. */ + fun id(id: Int): TapTarget { + this.id = id + return this + } + + /** Specify the target radius in dp. */ + fun targetRadius(targetRadius: Int): TapTarget { + this.targetRadius = targetRadius + return this + } + + /** Return the id associated with this tap target */ + fun id(): Int { + return id + } + + /** + * In case your target needs time to be ready (laid out in your view, not created, etc), the + * runnable passed here will be invoked when the target is ready. + */ + open fun onReady(runnable: Runnable?) { + runnable?.run() + } + + /** + * Returns the target bounds. Throws an exception if they are not set + * (target may not be ready) + * + * + * This will only be called internally when [.onReady] invokes its runnable + */ + fun bounds(): Rect { + checkNotNull(bounds) { "Requesting bounds that are not set! Make sure your target is ready" } + return bounds as Rect + } + + fun outerCircleColorInt(context: Context): Int? { + return colorResOrInt(context, outerCircleColor, outerCircleColorRes) + } + + fun targetCircleColorInt(context: Context): Int? { + return colorResOrInt(context, targetCircleColor, targetCircleColorRes) + } + + fun dimColorInt(context: Context): Int? { + return colorResOrInt(context, dimColor, dimColorRes) + } + + fun titleTextColorInt(context: Context): Int? { + return colorResOrInt(context, titleTextColor, titleTextColorRes) + } + + fun descriptionTextColorInt(context: Context): Int? { + return colorResOrInt(context, descriptionTextColor, descriptionTextColorRes) + } + + fun titleTextSizePx(context: Context): Int { + return dimenOrSize(context, titleTextSize, titleTextDimen) + } + + fun descriptionTextSizePx(context: Context): Int { + return dimenOrSize(context, descriptionTextSize, descriptionTextDimen) + } + + private fun colorResOrInt(context: Context, value: Int?, @ColorRes resource: Int): Int? { + return if (resource != -1) { + ContextCompat.getColor(context, resource) + } else value + } + + private fun dimenOrSize(context: Context, size: Int, @DimenRes dimen: Int): Int { + return if (dimen != -1) { + context.resources.getDimensionPixelSize(dimen) + } else size.sp + } + + companion object { + /** Return a tap target for the overflow button from the given toolbar + * + * + * **Note:** This is currently experimental, use at your own risk + */ + /** + * Return a tap target for the overflow button from the given toolbar + * + * + * **Note:** This is currently experimental, use at your own risk + */ + @JvmOverloads + fun forToolbarOverflow( + toolbar: Toolbar?, title: CharSequence?, + description: CharSequence? = null + ): TapTarget { + return ToolbarTapTarget(toolbar, false, title, description) + } + /** Return a tap target for the overflow button from the given toolbar + * + * + * **Note:** This is currently experimental, use at your own risk + */ + /** Return a tap target for the overflow button from the given toolbar + * + * + * **Note:** This is currently experimental, use at your own risk + */ + @JvmOverloads + fun forToolbarOverflow( + toolbar: android.widget.Toolbar?, title: CharSequence?, + description: CharSequence? = null + ): TapTarget { + return ToolbarTapTarget(toolbar, false, title, description) + } + /** Return a tap target for the navigation button (back, up, etc) from the given toolbar */ + /** Return a tap target for the navigation button (back, up, etc) from the given toolbar */ + @JvmOverloads + fun forToolbarNavigationIcon( + toolbar: Toolbar?, title: CharSequence?, + description: CharSequence? = null + ): TapTarget { + return ToolbarTapTarget(toolbar, true, title, description) + } + /** Return a tap target for the navigation button (back, up, etc) from the given toolbar */ + /** Return a tap target for the navigation button (back, up, etc) from the given toolbar */ + @JvmOverloads + fun forToolbarNavigationIcon( + toolbar: android.widget.Toolbar?, title: CharSequence?, + description: CharSequence? = null + ): TapTarget { + return ToolbarTapTarget(toolbar, true, title, description) + } + /** Return a tap target for the menu item from the given toolbar */ + /** Return a tap target for the menu item from the given toolbar */ + @JvmOverloads + fun forToolbarMenuItem( + toolbar: Toolbar?, @IdRes menuItemId: Int, + title: CharSequence?, description: CharSequence? = null + ): TapTarget { + return ToolbarTapTarget(toolbar, menuItemId, title, description) + } + /** Return a tap target for the menu item from the given toolbar */ + /** Return a tap target for the menu item from the given toolbar */ + @JvmOverloads + fun forToolbarMenuItem( + toolbar: android.widget.Toolbar?, @IdRes menuItemId: Int, + title: CharSequence?, description: CharSequence? = null + ): TapTarget { + return ToolbarTapTarget(toolbar, menuItemId, title, description) + } + /** Return a tap target for the specified view */ + /** Return a tap target for the specified view */ + @JvmOverloads + fun forView( + view: View, + title: CharSequence, + description: CharSequence? = null + ): TapTarget { + return ViewTapTarget(view, title, description) + } + /** Return a tap target for the specified bounds */ + /** Return a tap target for the specified bounds */ + @JvmOverloads + fun forBounds( + bounds: Rect?, + title: CharSequence?, + description: CharSequence? = null + ): TapTarget { + return TapTarget(bounds, title, description) + } + } +} \ No newline at end of file diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.java b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.java deleted file mode 100644 index 23a33b2..0000000 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.java +++ /dev/null @@ -1,238 +0,0 @@ -/** - * Copyright 2016 Keepsafe Software, Inc. - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.getkeepsafe.taptargetview; - -import android.app.Activity; -import android.app.Dialog; -import androidx.annotation.Nullable; -import androidx.annotation.UiThread; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Queue; - -/** - * Displays a sequence of {@link TapTargetView}s. - *

- * Internally, a FIFO queue is held to dictate which {@link TapTarget} will be shown. - */ -public class TapTargetSequence { - private final @Nullable Activity activity; - private final @Nullable Dialog dialog; - private final Queue targets; - private boolean active; - - @Nullable - private TapTargetView currentView; - - Listener listener; - boolean considerOuterCircleCanceled; - boolean continueOnCancel; - - public interface Listener { - /** Called when there are no more tap targets to display */ - void onSequenceFinish(); - - /** - * Called when moving onto the next tap target. - * @param lastTarget The last displayed target - * @param targetClicked Whether the last displayed target was clicked (this will always be true - * unless you have set {@link #continueOnCancel(boolean)} and the user - * clicks outside of the target - */ - void onSequenceStep(TapTarget lastTarget, boolean targetClicked); - - /** - * Called when the user taps outside of the current target, the target is cancelable, and - * {@link #continueOnCancel(boolean)} is not set. - * @param lastTarget The last displayed target - */ - void onSequenceCanceled(TapTarget lastTarget); - } - - public TapTargetSequence(Activity activity) { - if (activity == null) throw new IllegalArgumentException("Activity is null"); - this.activity = activity; - this.dialog = null; - this.targets = new LinkedList<>(); - } - - public TapTargetSequence(Dialog dialog) { - if (dialog == null) throw new IllegalArgumentException("Given null Dialog"); - this.dialog = dialog; - this.activity = null; - this.targets = new LinkedList<>(); - } - - /** Adds the given targets, in order, to the pending queue of {@link TapTarget}s */ - public TapTargetSequence targets(List targets) { - this.targets.addAll(targets); - return this; - } - - /** Adds the given targets, in order, to the pending queue of {@link TapTarget}s */ - public TapTargetSequence targets(TapTarget... targets) { - Collections.addAll(this.targets, targets); - return this; - } - - /** Adds the given target to the pending queue of {@link TapTarget}s */ - public TapTargetSequence target(TapTarget target) { - this.targets.add(target); - return this; - } - - /** Whether or not to continue the sequence when a {@link TapTarget} is canceled **/ - public TapTargetSequence continueOnCancel(boolean status) { - this.continueOnCancel = status; - return this; - } - - /** Whether or not to consider taps on the outer circle as a cancellation **/ - public TapTargetSequence considerOuterCircleCanceled(boolean status) { - this.considerOuterCircleCanceled = status; - return this; - } - - /** Specify the listener for this sequence **/ - public TapTargetSequence listener(Listener listener) { - this.listener = listener; - return this; - } - - /** Immediately starts the sequence and displays the first target from the queue **/ - @UiThread - public void start() { - if (targets.isEmpty() || active) { - return; - } - - active = true; - showNext(); - } - - /** Immediately starts the sequence from the given targetId's position in the queue */ - public void startWith(int targetId) { - if (active) { - return; - } - - while (targets.peek() != null && targets.peek().id() != targetId) { - targets.poll(); - } - - TapTarget peekedTarget = targets.peek(); - if (peekedTarget == null || peekedTarget.id() != targetId) { - throw new IllegalStateException("Given target " + targetId + " not in sequence"); - } - - start(); - } - - /** Immediately starts the sequence at the specified zero-based index in the queue */ - public void startAt(int index) { - if (active) { - return; - } - - if (index < 0 || index >= targets.size()) { - throw new IllegalArgumentException("Given invalid index " + index); - } - - final int expectedSize = targets.size() - index; - while (targets.peek() != null && targets.size() != expectedSize) { - targets.poll(); - } - - if (targets.size() != expectedSize) { - throw new IllegalStateException("Given index " + index + " not in sequence"); - } - - start(); - } - - /** - * Cancels the sequence, if the current target is cancelable. - * When the sequence is canceled, the current target is dismissed and the remaining targets are - * removed from the sequence. - * @return whether the sequence was canceled or not - */ - @UiThread - public boolean cancel() { - if (!active || currentView == null || !currentView.cancelable) { - return false; - } - currentView.dismiss(false); - active = false; - targets.clear(); - if (listener != null) { - listener.onSequenceCanceled(currentView.target); - } - return true; - } - - void showNext() { - try { - TapTarget tapTarget = targets.remove(); - if (activity != null) { - currentView = TapTargetView.showFor(activity, tapTarget, tapTargetListener); - } else { - currentView = TapTargetView.showFor(dialog, tapTarget, tapTargetListener); - } - } catch (NoSuchElementException e) { - currentView = null; - // No more targets - if (listener != null) { - listener.onSequenceFinish(); - } - } - } - - private final TapTargetView.Listener tapTargetListener = new TapTargetView.Listener() { - @Override - public void onTargetClick(TapTargetView view) { - super.onTargetClick(view); - if (listener != null) { - listener.onSequenceStep(view.target, true); - } - showNext(); - } - - @Override - public void onOuterCircleClick(TapTargetView view) { - if (considerOuterCircleCanceled) { - onTargetCancel(view); - } - } - - @Override - public void onTargetCancel(TapTargetView view) { - super.onTargetCancel(view); - if (continueOnCancel) { - if (listener != null) { - listener.onSequenceStep(view.target, false); - } - showNext(); - } else { - if (listener != null) { - listener.onSequenceCanceled(view.target); - } - } - } - }; -} diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.kt new file mode 100644 index 0000000..b942662 --- /dev/null +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.kt @@ -0,0 +1,146 @@ +@file:Suppress("unused") +package com.getkeepsafe.taptargetview + +import android.app.Activity +import android.app.Dialog +import androidx.annotation.UiThread +import java.util.LinkedList +import java.util.Queue + +class TapTargetSequence: TapTargetView.Listener { + + private val targets: Queue = LinkedList() + + private var activity: Activity? = null + + private var dialog: Dialog? = null + + private var isActive: Boolean = false + + private var listener: Listener? = null + + private var considerOuterCircleCanceled = false + + private var continueOnCancel = false + + private var currentView: TapTargetView? = null + + constructor(activity: Activity?) { + this.activity = activity + this.dialog = null + } + + constructor(dialog: Dialog?) { + this.dialog = dialog + this.activity = null + } + + fun targets(targets: Iterable): TapTargetSequence { + this.targets.addAll(targets) + return this + } + + fun addTarget(vararg targets: TapTarget): TapTargetSequence { + this.targets.addAll(targets) + return this + } + + fun continueOnCancel(status: Boolean): TapTargetSequence { + this.continueOnCancel = status + return this + } + + fun considerOuterCircleCanceled(status: Boolean): TapTargetSequence { + considerOuterCircleCanceled = status + return this + } + + /** Specify the listener for this sequence */ + fun listener(listener: Listener?): TapTargetSequence { + this.listener = listener + return this + } + + + @UiThread + fun start() { + if (targets.isEmpty() || isActive) return + isActive = true + showNext() + } + + @UiThread + fun cancel(): Boolean { + val currentView = this.currentView ?: return false + if (!isActive || !currentView.cancelable) return false + currentView.dismiss(false) + isActive = false + targets.clear() + listener?.onSequenceCanceled(currentView.target) + return true + } + + fun startAt(index: Int) { + if (isActive) return + if (index < 0 || index >= targets.size) return + val expectedSize = targets.size - index + repeat(index) { + targets.poll() + } + check(targets.size == expectedSize) { "Given index $index not in sequence" } + start() + } + + private fun showNext() { + val target = targets.poll() + if (target == null) { + currentView = null + listener?.onSequenceFinish() + return + } + currentView = activity?.let { it.showGuideView(target, this) } + currentView = dialog?.let { it.showGuideView(target, this) } + } + + override fun onTargetClick(view: TapTargetView?) { + super.onTargetClick(view) + listener?.onSequenceStep(view?.target, true) + showNext() + } + + override fun onTargetCancel(view: TapTargetView?) { + super.onTargetCancel(view) + if (continueOnCancel) { + listener?.onSequenceStep(view?.target, false) + showNext() + } else { + listener?.onSequenceCanceled(view?.target) + } + } + + override fun onOuterCircleClick(view: TapTargetView?) { + if (considerOuterCircleCanceled) onTargetCancel(view) + } + + interface Listener { + /** Called when there are no more tap targets to display */ + fun onSequenceFinish() + + /** + * Called when moving onto the next tap target. + * @param lastTarget The last displayed target + * @param targetClicked Whether the last displayed target was clicked (this will always be true + * unless you have set [.continueOnCancel] and the user + * clicks outside of the target + */ + fun onSequenceStep(lastTarget: TapTarget?, targetClicked: Boolean) + + /** + * Called when the user taps outside of the current target, the target is cancelable, and + * [.continueOnCancel] is not set. + * @param lastTarget The last displayed target + */ + fun onSequenceCanceled(lastTarget: TapTarget?) + } + +} \ No newline at end of file diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java index c21735d..542cd15 100644 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java @@ -19,7 +19,6 @@ import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; -import android.app.Dialog; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; @@ -28,7 +27,6 @@ import android.graphics.Outline; import android.graphics.Paint; import android.graphics.Path; -import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; @@ -44,7 +42,6 @@ import android.text.StaticLayout; import android.text.TextPaint; import android.util.DisplayMetrics; -import android.view.Gravity; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -60,7 +57,7 @@ * guidelines. *

* This class should not be instantiated directly. Instead, please use the - * {@link #showFor(Activity, TapTarget, Listener)} static factory method instead. + * {@see TargetViewExtensionsKTX#showGuideView} static factory method instead. *

* More information can be found here: * https://material.google.com/growth-communications/feature-discovery.html#feature-discovery-design @@ -152,48 +149,6 @@ public class TapTargetView extends View { @Nullable ViewOutlineProvider outlineProvider; - public static TapTargetView showFor(Activity activity, TapTarget target) { - return showFor(activity, target, null); - } - - public static TapTargetView showFor(Activity activity, TapTarget target, Listener listener) { - if (activity == null) throw new IllegalArgumentException("Activity is null"); - - final ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView(); - final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); - final ViewGroup content = (ViewGroup) decor.findViewById(android.R.id.content); - final TapTargetView tapTargetView = new TapTargetView(activity, decor, content, target, listener); - decor.addView(tapTargetView, layoutParams); - - return tapTargetView; - } - - public static TapTargetView showFor(Dialog dialog, TapTarget target) { - return showFor(dialog, target, null); - } - - public static TapTargetView showFor(Dialog dialog, TapTarget target, Listener listener) { - if (dialog == null) throw new IllegalArgumentException("Dialog is null"); - - final Context context = dialog.getContext(); - final WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - final WindowManager.LayoutParams params = new WindowManager.LayoutParams(); - params.type = WindowManager.LayoutParams.TYPE_APPLICATION; - params.format = PixelFormat.RGBA_8888; - params.flags = 0; - params.gravity = Gravity.START | Gravity.TOP; - params.x = 0; - params.y = 0; - params.width = WindowManager.LayoutParams.MATCH_PARENT; - params.height = WindowManager.LayoutParams.MATCH_PARENT; - - final TapTargetView tapTargetView = new TapTargetView(context, windowManager, null, target, listener); - windowManager.addView(tapTargetView, params); - - return tapTargetView; - } - public static class Listener { /** Signals that the user has clicked inside of the target **/ public void onTargetClick(TapTargetView view) { @@ -234,7 +189,7 @@ public void onUpdate(float lerpTime) { calculateDrawingBounds(); } - final float targetAlpha = target.outerCircleAlpha * 255; + final float targetAlpha = target.getOuterCircleAlpha() * 255; outerCircleRadius = newOuterCircleRadius; outerCircleAlpha = (int) Math.min(targetAlpha, (lerpTime * 1.5f * targetAlpha)); outerCirclePath.reset(); @@ -325,7 +280,7 @@ public void onEnd() { public void onUpdate(float lerpTime) { final float spedUpLerp = Math.min(1.0f, lerpTime * 2.0f); outerCircleRadius = calculatedOuterCircleRadius * (1.0f + (spedUpLerp * 0.2f)); - outerCircleAlpha = (int) ((1.0f - spedUpLerp) * target.outerCircleAlpha * 255.0f); + outerCircleAlpha = (int) ((1.0f - spedUpLerp) * target.getOuterCircleAlpha() * 255.0f); outerCirclePath.reset(); outerCirclePath.addCircle(outerCircleCenter[0], outerCircleCenter[1], outerCircleRadius, Path.Direction.CW); targetCircleRadius = (1.0f - lerpTime) * TARGET_RADIUS; @@ -377,19 +332,19 @@ public TapTargetView(final Context context, this.parent = parent; this.boundingParent = boundingParent; this.listener = userListener != null ? userListener : new Listener(); - this.title = target.title; - this.description = target.description; - - TARGET_PADDING = UiUtil.dp(context, 20); - CIRCLE_PADDING = UiUtil.dp(context, 40); - TARGET_RADIUS = UiUtil.dp(context, target.targetRadius); - TEXT_PADDING = UiUtil.dp(context, 40); - TEXT_SPACING = UiUtil.dp(context, 8); - TEXT_MAX_WIDTH = UiUtil.dp(context, 360); - TEXT_POSITIONING_BIAS = UiUtil.dp(context, 20); - GUTTER_DIM = UiUtil.dp(context, 88); - SHADOW_DIM = UiUtil.dp(context, 8); - SHADOW_JITTER_DIM = UiUtil.dp(context, 1); + this.title = target.getTitle(); + this.description = target.getDescription(); + + TARGET_PADDING = UiUtils.getDp( 20); + CIRCLE_PADDING = UiUtils.getDp( 40); + TARGET_RADIUS = UiUtils.getDp( target.getTargetRadius()); + TEXT_PADDING = UiUtils.getDp( 40); + TEXT_SPACING = UiUtils.getDp( 8); + TEXT_MAX_WIDTH = UiUtils.getDp( 360); + TEXT_POSITIONING_BIAS = UiUtils.getDp( 20); + GUTTER_DIM = UiUtils.getDp( 88); + SHADOW_DIM = UiUtils.getDp( 8); + SHADOW_JITTER_DIM = UiUtils.getDp( 1); TARGET_PULSE_RADIUS = (int) (0.1f * TARGET_RADIUS); outerCirclePath = new Path(); @@ -409,7 +364,7 @@ public TapTargetView(final Context context, outerCirclePaint = new Paint(); outerCirclePaint.setAntiAlias(true); - outerCirclePaint.setAlpha((int) (target.outerCircleAlpha * 255.0f)); + outerCirclePaint.setAlpha((int) (target.getOuterCircleAlpha() * 255.0f)); outerCircleShadowPaint = new Paint(); outerCircleShadowPaint.setAntiAlias(true); @@ -550,13 +505,13 @@ private void startExpandAnimation() { } protected void applyTargetOptions(Context context) { - shouldTintTarget = !target.transparentTarget && target.tintTarget; - shouldDrawShadow = target.drawShadow; - cancelable = target.cancelable; + shouldTintTarget = !target.getTransparentTarget() && target.getTintTarget(); + shouldDrawShadow = target.getDrawShadow(); + cancelable = target.getCancelable(); // We can't clip out portions of a view outline, so if the user specified a transparent // target, we need to fallback to drawing a jittered shadow approximation - if (shouldDrawShadow && Build.VERSION.SDK_INT >= 21 && !target.transparentTarget) { + if (shouldDrawShadow && Build.VERSION.SDK_INT >= 21 && !target.getTransparentTarget()) { outlineProvider = new ViewOutlineProvider() { @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override @@ -583,13 +538,13 @@ public void getOutline(View view, Outline outline) { } final Resources.Theme theme = context.getTheme(); - isDark = UiUtil.themeIntAttr(context, "isLightTheme") == 0; + isDark = UiUtils.getThemeIneAttr(context, "isLightTheme") == 0; final Integer outerCircleColor = target.outerCircleColorInt(context); if (outerCircleColor != null) { outerCirclePaint.setColor(outerCircleColor); } else if (theme != null) { - outerCirclePaint.setColor(UiUtil.themeIntAttr(context, "colorPrimary")); + outerCirclePaint.setColor(UiUtils.getThemeIneAttr(context, "colorPrimary")); } else { outerCirclePaint.setColor(Color.WHITE); } @@ -601,7 +556,7 @@ public void getOutline(View view, Outline outline) { targetCirclePaint.setColor(isDark ? Color.BLACK : Color.WHITE); } - if (target.transparentTarget) { + if (target.getTransparentTarget()) { targetCirclePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); } @@ -609,7 +564,7 @@ public void getOutline(View view, Outline outline) { final Integer targetDimColor = target.dimColorInt(context); if (targetDimColor != null) { - dimColor = UiUtil.setAlpha(targetDimColor, 0.3f); + dimColor = UiUtils.setAlpha(targetDimColor, 0.3f); } else { dimColor = -1; } @@ -628,12 +583,12 @@ public void getOutline(View view, Outline outline) { descriptionPaint.setColor(titlePaint.getColor()); } - if (target.titleTypeface != null) { - titlePaint.setTypeface(target.titleTypeface); + if (target.getTitleTypeface() != null) { + titlePaint.setTypeface(target.getTitleTypeface()); } - if (target.descriptionTypeface != null) { - descriptionPaint.setTypeface(target.descriptionTypeface); + if (target.getDescriptionTypeface() != null) { + descriptionPaint.setTypeface(target.getTitleTypeface()); } } @@ -654,7 +609,7 @@ void onDismiss(boolean userInitiated) { animator.removeAllUpdateListeners(); } - ViewUtil.removeOnGlobalLayoutListener(getViewTreeObserver(), globalLayoutListener); + getViewTreeObserver().removeOnGlobalLayoutListener(globalLayoutListener); visible = false; if (listener != null) { @@ -705,7 +660,7 @@ protected void onDraw(Canvas c) { if (descriptionLayout != null && titleLayout != null) { c.translate(0, titleLayout.getHeight() + TEXT_SPACING); - descriptionPaint.setAlpha((int) (target.descriptionTextAlpha * textAlpha)); + descriptionPaint.setAlpha((int) (target.getDescriptionTextAlpha() * textAlpha)); descriptionLayout.draw(c); } } @@ -717,11 +672,11 @@ protected void onDraw(Canvas c) { c.translate(targetBounds.centerX() - tintedTarget.getWidth() / 2, targetBounds.centerY() - tintedTarget.getHeight() / 2); c.drawBitmap(tintedTarget, 0, 0, targetCirclePaint); - } else if (target.icon != null) { - c.translate(targetBounds.centerX() - target.icon.getBounds().width() / 2, - targetBounds.centerY() - target.icon.getBounds().height() / 2); - target.icon.setAlpha(targetCirclePaint.getAlpha()); - target.icon.draw(c); + } else if (target.getIcon() != null) { + c.translate(targetBounds.centerX() - target.getIcon().getBounds().width() / 2, + targetBounds.centerY() - target.getIcon().getBounds().height() / 2); + target.getIcon().setAlpha(targetCirclePaint.getAlpha()); + target.getIcon().draw(c); } } c.restoreToCount(saveCount); @@ -788,7 +743,7 @@ public void dismiss(boolean tappedTarget) { private void finishDismiss(boolean userInitiated) { onDismiss(userInitiated); - ViewUtil.removeView(parent, TapTargetView.this); + parent.removeView(TapTargetView.this); } /** Specify whether to draw a wireframe around the view, useful for debugging **/ @@ -823,13 +778,13 @@ void drawDebugInformation(Canvas c) { debugPaint = new Paint(); debugPaint.setARGB(255, 255, 0, 0); debugPaint.setStyle(Paint.Style.STROKE); - debugPaint.setStrokeWidth(UiUtil.dp(getContext(), 1)); + debugPaint.setStrokeWidth(UiUtils.getDp(1)); } if (debugTextPaint == null) { debugTextPaint = new TextPaint(); debugTextPaint.setColor(0xFFFF0000); - debugTextPaint.setTextSize(UiUtil.sp(getContext(), 16)); + debugTextPaint.setTextSize(UiUtils.getSp(16)); } // Draw wireframe @@ -872,7 +827,7 @@ void drawDebugInformation(Canvas c) { } void drawTintedTarget() { - final Drawable icon = target.icon; + final Drawable icon = target.getIcon(); if (!shouldTintTarget || icon == null) { tintedTarget = null; return; diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TargetViewExtensions.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TargetViewExtensions.kt new file mode 100644 index 0000000..d1095b0 --- /dev/null +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TargetViewExtensions.kt @@ -0,0 +1,48 @@ +@file:JvmName("TargetViewExtensionsKTX") +package com.getkeepsafe.taptargetview + +import android.app.Activity +import android.app.Dialog +import android.content.Context +import android.graphics.PixelFormat +import android.view.Gravity +import android.view.ViewGroup +import android.view.WindowManager + +@JvmName("showGuideView") +fun Activity?.showGuideView( + target: TapTarget, + listener: TapTargetView.Listener? = null +): TapTargetView { + if (this == null) throw IllegalArgumentException("Activity is null") + val decorView = this.window.decorView as? ViewGroup + ?: throw IllegalArgumentException("Activity has no decorView") + val layoutParams = ViewGroup.LayoutParams(-1, -1) + val content = decorView.findViewById(android.R.id.content) + val targetView = TapTargetView(this, decorView, content, target, listener) + decorView.addView(targetView, layoutParams) + return targetView +} + +@JvmName("showGuideWithDialog") +fun Dialog?.showGuideView( + target: TapTarget, + listener: TapTargetView.Listener? = null +): TapTargetView { + if (this == null) throw IllegalArgumentException("Dialog is null") + val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager + val params = WindowManager.LayoutParams().apply { + type = WindowManager.LayoutParams.TYPE_APPLICATION + format = PixelFormat.RGBA_8888 + flags = 0 + gravity = Gravity.START or Gravity.TOP + x = 0 + y = 0 + width = WindowManager.LayoutParams.MATCH_PARENT + height = WindowManager.LayoutParams.MATCH_PARENT + } + + val targetView = TapTargetView(context, windowManager, null, target, listener) + windowManager.addView(targetView, params) + return targetView +} \ No newline at end of file diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ToolbarTapTarget.java b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ToolbarTapTarget.java index 664ed39..547f4a4 100644 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ToolbarTapTarget.java +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ToolbarTapTarget.java @@ -15,7 +15,6 @@ */ package com.getkeepsafe.taptargetview; -import android.annotation.TargetApi; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.TextUtils; @@ -59,8 +58,7 @@ private static ToolbarProxy proxyOf(Object instance) { if (instance instanceof Toolbar) { return new SupportToolbarProxy((Toolbar) instance); - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP - && instance instanceof android.widget.Toolbar) { + } else if (instance instanceof android.widget.Toolbar) { return new StandardToolbarProxy((android.widget.Toolbar) instance); } @@ -139,9 +137,9 @@ private static View findOverflowView(Object instance) { // The "ActionMenuPresenter" then holds a reference to an "OverflowMenuButton" which is the // desired target try { - final Object actionMenuView = ReflectUtil.getPrivateField(toolbar.internalToolbar(), "mMenuView"); - final Object actionMenuPresenter = ReflectUtil.getPrivateField(actionMenuView, "mPresenter"); - return (View) ReflectUtil.getPrivateField(actionMenuPresenter, "mOverflowButton"); + final Object actionMenuView = ReflectExtensions.getPrivateField(toolbar.internalToolbar(), "mMenuView"); + final Object actionMenuPresenter = ReflectExtensions.getPrivateField(actionMenuView, "mPresenter"); + return (View) ReflectExtensions.getPrivateField(actionMenuPresenter, "mOverflowButton"); } catch (NoSuchFieldException e) { throw new IllegalStateException("Could not find overflow view for Toolbar!", e); } catch (IllegalAccessException e) { @@ -216,7 +214,6 @@ public Object internalToolbar() { } } - @TargetApi(Build.VERSION_CODES.LOLLIPOP) private static class StandardToolbarProxy implements ToolbarProxy { private final android.widget.Toolbar toolbar; diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/UiUtil.java b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/UiUtil.java deleted file mode 100644 index b34ec09..0000000 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/UiUtil.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright 2016 Keepsafe Software, Inc. - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.getkeepsafe.taptargetview; - -import android.content.Context; -import android.content.res.Resources; - -import androidx.annotation.ColorRes; -import androidx.annotation.DimenRes; -import android.util.TypedValue; - -class UiUtil { - UiUtil() { - } - - /** Returns the given pixel value in dp **/ - static int dp(Context context, int val) { - return (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, val, context.getResources().getDisplayMetrics()); - } - - /** Returns the given pixel value in sp **/ - static int sp(Context context, int val) { - return (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_SP, val, context.getResources().getDisplayMetrics()); - } - - /** Returns the value of the desired theme integer attribute, or -1 if not found **/ - static int themeIntAttr(Context context, String attr) { - final Resources.Theme theme = context.getTheme(); - if (theme == null) { - return -1; - } - - final TypedValue value = new TypedValue(); - final int id = context.getResources().getIdentifier(attr, "attr", context.getPackageName()); - - if (id == 0) { - // Not found - return -1; - } - - theme.resolveAttribute(id, value, true); - return value.data; - } - - /** Modifies the alpha value of the given ARGB color **/ - static int setAlpha(int argb, float alpha) { - if (alpha > 1.0f) { - alpha = 1.0f; - } else if (alpha <= 0.0f) { - alpha = 0.0f; - } - - return ((int) ((argb >>> 24) * alpha) << 24) | (argb & 0x00FFFFFF); - } -} diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/UiUtils.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/UiUtils.kt new file mode 100644 index 0000000..c392bec --- /dev/null +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/UiUtils.kt @@ -0,0 +1,35 @@ +@file:JvmName("UiUtils") +@file:Suppress("unused") +package com.getkeepsafe.taptargetview + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.Resources +import android.util.TypedValue +import androidx.annotation.FloatRange + +internal val Int.dp get(): Int = (this * Resources.getSystem().displayMetrics.density).toInt() + +internal val Int.px get(): Int = (this / Resources.getSystem().displayMetrics.density).toInt() + +internal val Int.sp get(): Int = (this * Resources.getSystem().displayMetrics.scaledDensity).toInt() + +internal val Int.px2dp get(): Int = (this / Resources.getSystem().displayMetrics.density).toInt() + +@SuppressLint("DiscouragedApi") +internal fun Context.getThemeIneAttr( + attr: String +): Int { + val theme = theme ?: return -1 + val typedValue = TypedValue() + val id = resources.getIdentifier(attr, "attr", packageName) + if (id == 0) return -1 + theme.resolveAttribute(id, typedValue, true) + return typedValue.data +} + +fun Int.setAlpha( + @FloatRange(0.0, 1.0) alpha: Float +): Int { + return ((this ushr 24) * alpha).toInt() shl 24 or (this and 0x00FFFFFF) +} \ No newline at end of file diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewTapTarget.java b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewTapTarget.java deleted file mode 100644 index 045ae58..0000000 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewTapTarget.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright 2016 Keepsafe Software, Inc. - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.getkeepsafe.taptargetview; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.drawable.BitmapDrawable; -import androidx.annotation.Nullable; -import android.view.View; - -class ViewTapTarget extends TapTarget { - final View view; - - ViewTapTarget(View view, CharSequence title, @Nullable CharSequence description) { - super(title, description); - if (view == null) { - throw new IllegalArgumentException("Given null view to target"); - } - this.view = view; - } - - @Override - public void onReady(final Runnable runnable) { - ViewUtil.onLaidOut(view, new Runnable() { - @Override - public void run() { - // Cache bounds - final int[] location = new int[2]; - view.getLocationOnScreen(location); - bounds = new Rect(location[0], location[1], - location[0] + view.getWidth(), location[1] + view.getHeight()); - - if (icon == null && view.getWidth() > 0 && view.getHeight() > 0) { - final Bitmap viewBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888); - final Canvas canvas = new Canvas(viewBitmap); - view.draw(canvas); - icon = new BitmapDrawable(view.getContext().getResources(), viewBitmap); - icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight()); - } - - runnable.run(); - } - }); - } -} diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewTapTarget.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewTapTarget.kt new file mode 100644 index 0000000..1733adb --- /dev/null +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewTapTarget.kt @@ -0,0 +1,38 @@ +package com.getkeepsafe.taptargetview + +import android.graphics.Canvas +import android.graphics.Rect +import android.graphics.drawable.BitmapDrawable +import android.view.View +import androidx.core.view.doOnLayout +import androidx.core.view.drawToBitmap + +open class ViewTapTarget @JvmOverloads constructor( + private val view: View, + title: CharSequence, + description: CharSequence? = null +): TapTarget(title, description) { + + override fun onReady(runnable: Runnable?) { + view.doOnLayout { + val location = IntArray(2) + view.getLocationOnScreen(location) + bounds = Rect( + location[0], + location[1], + location[0] + view.width, + location[1] + view.height + ) + if (icon == null && view.width > 0 && view.height > 0) { + val viewBitmap = view.drawToBitmap() + val canvas = Canvas(viewBitmap) + view.draw(canvas) + val icon = BitmapDrawable(view.context.resources, viewBitmap) + icon.setBounds(0, 0, view.width, view.height) + this.icon = icon + } + runnable?.run() + } + } + +} \ No newline at end of file diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewUtil.java b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewUtil.java deleted file mode 100644 index 44c9a9a..0000000 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewUtil.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright 2016 Keepsafe Software, Inc. - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.getkeepsafe.taptargetview; - -import android.os.Build; -import androidx.core.view.ViewCompat; -import android.view.View; -import android.view.ViewManager; -import android.view.ViewTreeObserver; - -class ViewUtil { - ViewUtil() { - } - - /** Returns whether or not the view has been laid out **/ - private static boolean isLaidOut(View view) { - return ViewCompat.isLaidOut(view) && view.getWidth() > 0 && view.getHeight() > 0; - } - - /** Executes the given {@link java.lang.Runnable} when the view is laid out **/ - static void onLaidOut(final View view, final Runnable runnable) { - if (isLaidOut(view)) { - runnable.run(); - return; - } - - final ViewTreeObserver observer = view.getViewTreeObserver(); - observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - final ViewTreeObserver trueObserver; - - if (observer.isAlive()) { - trueObserver = observer; - } else { - trueObserver = view.getViewTreeObserver(); - } - - removeOnGlobalLayoutListener(trueObserver, this); - - runnable.run(); - } - }); - } - - @SuppressWarnings("deprecation") - static void removeOnGlobalLayoutListener(ViewTreeObserver observer, - ViewTreeObserver.OnGlobalLayoutListener listener) { - if (Build.VERSION.SDK_INT >= 16) { - observer.removeOnGlobalLayoutListener(listener); - } else { - observer.removeGlobalOnLayoutListener(listener); - } - } - - static void removeView(ViewManager parent, View child) { - if (parent == null || child == null) { - return; - } - - try { - parent.removeView(child); - } catch (Exception ignored) { - // This catch exists for modified versions of Android that have a buggy ViewGroup - // implementation. See b.android.com/77639, #121 and #49 - } - } -} From 6fa49cabcfca96b2f39dd7a363d409e56137c0d1 Mon Sep 17 00:00:00 2001 From: huaweikai <1297720454@qq.com> Date: Sun, 6 Aug 2023 01:51:52 +0800 Subject: [PATCH 3/5] -Added to expand the shape of TargetIcon in the form of combination, and now expand the rectangle --- .github/screenshot3.jpg | Bin 0 -> 266344 bytes README.md | 55 ++-- .../taptargetviewsample/MainActivity.kt | 113 +++++--- app/src/main/res/layout/activity_main.xml | 10 + .../taptargetview/TapTargetSequence.kt | 1 + .../taptargetview/TapTargetView.java | 256 +++++++----------- .../taptargetview/TargetExtensions.kt | 90 ++++++ .../taptargetview/TargetViewExtensions.kt | 1 + .../taptargetview/ToolbarTapTarget.java | 12 +- .../getkeepsafe/taptargetview/ValueUtils.kt | 14 + .../taptargetview/ViewTapTarget.kt | 38 --- .../target/CircleShapeTapTarget.kt | 100 +++++++ .../target/RectAngleShapeType.kt | 112 ++++++++ .../taptargetview/{ => target}/TapTarget.kt | 231 ++++++---------- .../target/TapTargetShapeType.kt | 55 ++++ 15 files changed, 671 insertions(+), 417 deletions(-) create mode 100644 .github/screenshot3.jpg create mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/TargetExtensions.kt create mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/ValueUtils.kt delete mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewTapTarget.kt create mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/CircleShapeTapTarget.kt create mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/RectAngleShapeType.kt rename taptargetview/src/main/java/com/getkeepsafe/taptargetview/{ => target}/TapTarget.kt (62%) create mode 100644 taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/TapTargetShapeType.kt diff --git a/.github/screenshot3.jpg b/.github/screenshot3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2cacb9794ee81ddc958507b43bcb3898519a0352 GIT binary patch literal 266344 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�Thx~^`TcJwIyk@q?E7iRy(cS<4b9fuRHtV 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�!deqrD|wXRY7)@4fcf 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 Video 1 Screenshot 1 -Screenshot 2
+Screenshot 2 +Screenshot 2
TapTargetView @@ -37,33 +38,29 @@ For snapshots, please follow the instructions [here](https://jitpack.io/#KeepSaf ### Simple usage +```kotlin + Activity.showGuideView( + view.createTarget("Please Input Some Thing") + .outerCircleColor(R.color.colorAccent) + .targetIconColor(android.R.color.holo_blue_dark) + .transparentTarget(true) + .textColor(android.R.color.black) + .setTargetShapeType(TapTargetShapeType.RectAngle(16)) + ) +``` + ```java -TapTargetView.showFor(this, // `this` is an Activity - TapTarget.forView(findViewById(R.id.target), "This is a target", "We have the best targets, believe me") - // All options below are optional - .outerCircleColor(R.color.red) // Specify a color for the outer circle - .outerCircleAlpha(0.96f) // Specify the alpha amount for the outer circle - .targetCircleColor(R.color.white) // Specify a color for the target circle - .titleTextSize(20) // Specify the size (in sp) of the title text - .titleTextColor(R.color.white) // Specify the color of the title text - .descriptionTextSize(10) // Specify the size (in sp) of the description text - .descriptionTextColor(R.color.red) // Specify the color of the description text - .textColor(R.color.blue) // Specify a color for both the title and description text - .textTypeface(Typeface.SANS_SERIF) // Specify a typeface for the text - .dimColor(R.color.black) // If set, will dim behind the view with 30% opacity of the given color - .drawShadow(true) // Whether to draw a drop shadow or not - .cancelable(false) // Whether tapping outside the outer circle dismisses the view - .tintTarget(true) // Whether to tint the target view's color - .transparentTarget(false) // Specify whether the target is transparent (displays the content underneath) - .icon(Drawable) // Specify a custom drawable to draw as the target - .targetRadius(60), // Specify the target radius (in dp) - new TapTargetView.Listener() { // The listener can listen for regular clicks, long clicks or cancels - @Override - public void onTargetClick(TapTargetView view) { - super.onTargetClick(view); // This call is optional - doSomething(); - } - }); + TargetViewExtensionsKTX.showGuideView( + Activity, + view.createTarget("Please Input Some Thing") + .outerCircleColor(R.color.colorAccent) + .targetIconColor(android.R.color.holo_blue_dark) + .transparentTarget(true) + .textColor(android.R.color.black) + .setTargetShapeType(TapTargetShapeType.RectAngle(16)), + null + ); + } ``` You may also choose to target your own custom `Rect` with `TapTarget.forBounds(Rect, ...)` @@ -76,9 +73,9 @@ Additionally, each color can be specified via a `@ColorRes` or a `@ColorInt`. Fu You can easily create a sequence of tap targets with `TapTargetSequence`: -```java +```kotlin new TapTargetSequence(this) - .targets( + .addTarget( TapTarget.forView(findViewById(R.id.never), "Gonna"), TapTarget.forView(findViewById(R.id.give), "You", "Up") .dimColor(android.R.color.never) diff --git a/app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.kt b/app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.kt index a13b38d..40684f0 100644 --- a/app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.kt +++ b/app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.kt @@ -9,16 +9,22 @@ import android.text.style.StyleSpan import android.text.style.UnderlineSpan import android.util.Log import android.view.View +import android.widget.EditText import android.widget.TextView import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar import androidx.core.content.ContextCompat -import com.getkeepsafe.taptargetview.TapTarget +import com.getkeepsafe.taptargetview.target.TapTarget import com.getkeepsafe.taptargetview.TapTargetSequence import com.getkeepsafe.taptargetview.TapTargetView +import com.getkeepsafe.taptargetview.createNavigationIcon +import com.getkeepsafe.taptargetview.createOverflow +import com.getkeepsafe.taptargetview.createTarget +import com.getkeepsafe.taptargetview.forToolbarMenuItem import com.getkeepsafe.taptargetview.showGuideView +import com.getkeepsafe.taptargetview.target.TapTargetShapeType class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -49,32 +55,29 @@ class MainActivity : AppCompatActivity() { // We have a sequence of targets, so lets build it! val sequence = TapTargetSequence(this) .addTarget( // This tap target will target the back button, we just need to pass its containing toolbar - TapTarget.forToolbarNavigationIcon(toolbar, "This is the back button", sassyDesc) + toolbar.createNavigationIcon("This is the back button", sassyDesc) .id(1), // Likewise, this tap target will target the search button - TapTarget.forToolbarMenuItem( - toolbar, + toolbar.forToolbarMenuItem( R.id.search, "This is a search icon", "As you can see, it has gotten pretty dark around here..." ) .dimColor(android.R.color.black) .outerCircleColor(R.color.colorAccent) - .targetCircleColor(android.R.color.black) + .targetIconColor(android.R.color.black) .transparentTarget(true) .textColor(android.R.color.black) .id(2), // You can also target the overflow button in your toolbar - TapTarget.forToolbarOverflow( - toolbar, + toolbar.createOverflow( "This will show more options", "But they're not useful :(" ).id(3), // This tap target will target our droid buddy at the given target rect - TapTarget.forBounds( + droid.createTarget( droidTarget, "Oh look!", "You can point to any part of the screen. You also can't cancel this one!" ) .cancelable(false) - .icon(droid) .id(4) ) .listener(object : TapTargetSequence.Listener { @@ -94,18 +97,18 @@ class MainActivity : AppCompatActivity() { .setTitle("Uh oh") .setMessage("You canceled the sequence") .setPositiveButton("Oops", null).show() - dialog.showGuideView(TapTarget.forView( - dialog.getButton(DialogInterface.BUTTON_POSITIVE), - "Uh oh!", - "You canceled the sequence at step " + lastTarget?.id() - ) - .cancelable(false) - .tintTarget(false), object : TapTargetView.Listener() { - override fun onTargetClick(view: TapTargetView) { - super.onTargetClick(view) - dialog.dismiss() - } - }) + dialog.showGuideView( + dialog.getButton(DialogInterface.BUTTON_POSITIVE).createTarget( + "Uh oh!", + "You canceled the sequence at step " + lastTarget?.id() + ) + .cancelable(false) + .tintTarget(false), object : TapTargetView.Listener() { + override fun onTargetClick(view: TapTargetView) { + super.onTargetClick(view) + dialog.dismiss() + } + }) } }) @@ -117,29 +120,53 @@ class MainActivity : AppCompatActivity() { spannedDesc.length, 0 ) - this.showGuideView(TapTarget.forView(findViewById(R.id.fab), "Hello, world!", spannedDesc) - .cancelable(false) - .drawShadow(true) - .titleTextDimen(R.dimen.title_text_size) - .tintTarget(false), object : TapTargetView.Listener() { - override fun onTargetClick(view: TapTargetView) { - super.onTargetClick(view) - // .. which evidently starts the sequence we defined earlier - sequence.start() - } + this.showGuideView( + findViewById(R.id.fab).createTarget("Hello, world!", spannedDesc) + .cancelable(false) + .drawShadow(true) + .titleTextDimen(R.dimen.title_text_size) + .tintTarget(false), object : TapTargetView.Listener() { + override fun onTargetClick(view: TapTargetView) { + super.onTargetClick(view) + // .. which evidently starts the sequence we defined earlier + sequence.start() + } + + override fun onOuterCircleClick(view: TapTargetView) { + super.onOuterCircleClick(view) + Toast.makeText( + view.context, + "You clicked the outer circle!", + Toast.LENGTH_SHORT + ).show() + } - override fun onOuterCircleClick(view: TapTargetView) { - super.onOuterCircleClick(view) - Toast.makeText( - view.context, - "You clicked the outer circle!", - Toast.LENGTH_SHORT - ).show() - } + override fun onTargetDismissed(view: TapTargetView, userInitiated: Boolean) { + Log.d("TapTargetViewSample", "You dismissed me :(") + } + }) - override fun onTargetDismissed(view: TapTargetView, userInitiated: Boolean) { - Log.d("TapTargetViewSample", "You dismissed me :(") - } - }) + val ed = findViewById(R.id.ed) + ed.setOnClickListener { + showGuideView( + ed.createTarget("Please Input Some Thing") + .outerCircleColor(R.color.colorAccent) + .targetIconColor(android.R.color.holo_blue_dark) + .transparentTarget(true) + .textColor(android.R.color.black) + .setTargetShapeType(TapTargetShapeType.RectAngle(16)), + object : TapTargetView.Listener() { + override fun onTargetClick(view: TapTargetView) { + Toast.makeText( + view.context, + "You clicked the target!", + Toast.LENGTH_SHORT + ).show() + super.onTargetClick(view) + } + } + ) + } } + } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index f65883e..5af03ba 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -62,4 +62,14 @@ android:layout_height="wrap_content" android:padding="16dp"/> + + diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.kt index b942662..3927b74 100644 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.kt +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetSequence.kt @@ -4,6 +4,7 @@ package com.getkeepsafe.taptargetview import android.app.Activity import android.app.Dialog import androidx.annotation.UiThread +import com.getkeepsafe.taptargetview.target.TapTarget import java.util.LinkedList import java.util.Queue diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java index 542cd15..f0fafff 100644 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java @@ -52,6 +52,9 @@ import android.view.WindowManager; import android.view.animation.AccelerateDecelerateInterpolator; +import com.getkeepsafe.taptargetview.target.TapTarget; +import com.getkeepsafe.taptargetview.target.TapTargetShapeType; + /** * TapTargetView implements a feature discovery paradigm following Google's Material Design * guidelines. @@ -69,8 +72,6 @@ public class TapTargetView extends View { private boolean isInteractable = true; final int TARGET_PADDING; - final int TARGET_RADIUS; - final int TARGET_PULSE_RADIUS; final int TEXT_PADDING; final int TEXT_SPACING; final int TEXT_MAX_WIDTH; @@ -127,10 +128,8 @@ public class TapTargetView extends View { int[] outerCircleCenter; int outerCircleAlpha; - float targetCirclePulseRadius; int targetCirclePulseAlpha; - float targetCircleRadius; int targetCircleAlpha; int textAlpha; @@ -196,15 +195,8 @@ public void onUpdate(float lerpTime) { outerCirclePath.addCircle(outerCircleCenter[0], outerCircleCenter[1], outerCircleRadius, Path.Direction.CW); targetCircleAlpha = (int) Math.min(255.0f, (lerpTime * 1.5f * 255.0f)); - - if (expanding) { - targetCircleRadius = TARGET_RADIUS * Math.min(1.0f, lerpTime * 1.5f); - } else { - targetCircleRadius = TARGET_RADIUS * lerpTime; - targetCirclePulseRadius *= lerpTime; - } - - textAlpha = (int) (delayedLerp(lerpTime, 0.7f) * 255); + getTapType().expandContractChange(lerpTime, expanding); + textAlpha = (int) (ValueExtensions.getDelayLerp(lerpTime, 0.7f) * 255); if (expanding) { calculateDrawingBounds(); @@ -218,12 +210,7 @@ public void onUpdate(float lerpTime) { .duration(250) .delayBy(250) .interpolator(new AccelerateDecelerateInterpolator()) - .onUpdate(new FloatValueAnimatorBuilder.UpdateListener() { - @Override - public void onUpdate(float lerpTime) { - expandContractUpdateListener.onUpdate(lerpTime); - } - }) + .onUpdate(lerpTime -> expandContractUpdateListener.onUpdate(lerpTime)) .onEnd(new FloatValueAnimatorBuilder.EndListener() { @Override public void onEnd() { @@ -240,15 +227,12 @@ public void onEnd() { .onUpdate(new FloatValueAnimatorBuilder.UpdateListener() { @Override public void onUpdate(float lerpTime) { - final float pulseLerp = delayedLerp(lerpTime, 0.5f); - targetCirclePulseRadius = (1.0f + pulseLerp) * TARGET_RADIUS; + final float pulseLerp = ValueExtensions.getDelayLerp(lerpTime, 0.5f); + getTapType().pulseAnimation(lerpTime); targetCirclePulseAlpha = (int) ((1.0f - pulseLerp) * 255); - targetCircleRadius = TARGET_RADIUS + halfwayLerp(lerpTime) * TARGET_PULSE_RADIUS; - if (outerCircleRadius != calculatedOuterCircleRadius) { outerCircleRadius = calculatedOuterCircleRadius; } - calculateDrawingBounds(); invalidateViewAndOutline(drawingBounds); } @@ -258,18 +242,8 @@ public void onUpdate(float lerpTime) { final ValueAnimator dismissAnimation = new FloatValueAnimatorBuilder(true) .duration(250) .interpolator(new AccelerateDecelerateInterpolator()) - .onUpdate(new FloatValueAnimatorBuilder.UpdateListener() { - @Override - public void onUpdate(float lerpTime) { - expandContractUpdateListener.onUpdate(lerpTime); - } - }) - .onEnd(new FloatValueAnimatorBuilder.EndListener() { - @Override - public void onEnd() { - finishDismiss(true); - } - }) + .onUpdate(lerpTime -> expandContractUpdateListener.onUpdate(lerpTime)) + .onEnd(() -> finishDismiss(true)) .build(); private final ValueAnimator dismissConfirmAnimation = new FloatValueAnimatorBuilder() @@ -283,21 +257,15 @@ public void onUpdate(float lerpTime) { outerCircleAlpha = (int) ((1.0f - spedUpLerp) * target.getOuterCircleAlpha() * 255.0f); outerCirclePath.reset(); outerCirclePath.addCircle(outerCircleCenter[0], outerCircleCenter[1], outerCircleRadius, Path.Direction.CW); - targetCircleRadius = (1.0f - lerpTime) * TARGET_RADIUS; + getTapType().dismissConfirmAnimation(lerpTime); targetCircleAlpha = (int) ((1.0f - lerpTime) * 255.0f); - targetCirclePulseRadius = (1.0f + lerpTime) * TARGET_RADIUS; targetCirclePulseAlpha = (int) ((1.0f - lerpTime) * targetCirclePulseAlpha); textAlpha = (int) ((1.0f - spedUpLerp) * 255.0f); calculateDrawingBounds(); invalidateViewAndOutline(drawingBounds); } }) - .onEnd(new FloatValueAnimatorBuilder.EndListener() { - @Override - public void onEnd() { - finishDismiss(true); - } - }) + .onEnd(() -> finishDismiss(true)) .build(); private ValueAnimator[] animators = new ValueAnimator[] @@ -329,6 +297,7 @@ public TapTargetView(final Context context, if (target == null) throw new IllegalArgumentException("Target cannot be null"); this.target = target; + getTapType().initResource(context); this.parent = parent; this.boundingParent = boundingParent; this.listener = userListener != null ? userListener : new Listener(); @@ -337,7 +306,6 @@ public TapTargetView(final Context context, TARGET_PADDING = UiUtils.getDp( 20); CIRCLE_PADDING = UiUtils.getDp( 40); - TARGET_RADIUS = UiUtils.getDp( target.getTargetRadius()); TEXT_PADDING = UiUtils.getDp( 40); TEXT_SPACING = UiUtils.getDp( 8); TEXT_MAX_WIDTH = UiUtils.getDp( 360); @@ -345,7 +313,6 @@ public TapTargetView(final Context context, GUTTER_DIM = UiUtils.getDp( 88); SHADOW_DIM = UiUtils.getDp( 8); SHADOW_JITTER_DIM = UiUtils.getDp( 1); - TARGET_PULSE_RADIUS = (int) (0.1f * TARGET_RADIUS); outerCirclePath = new Path(); targetBounds = new Rect(); @@ -398,101 +365,88 @@ public TapTargetView(final Context context, layoutNoLimits = false; } - globalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - if (isDismissing) { - return; - } - updateTextLayouts(); - target.onReady(new Runnable() { - @Override - public void run() { - final int[] offset = new int[2]; - - targetBounds.set(target.bounds()); - - getLocationOnScreen(offset); - targetBounds.offset(-offset[0], -offset[1]); - - if (boundingParent != null) { - final WindowManager windowManager - = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - final DisplayMetrics displayMetrics = new DisplayMetrics(); - windowManager.getDefaultDisplay().getMetrics(displayMetrics); - - final Rect rect = new Rect(); - boundingParent.getWindowVisibleDisplayFrame(rect); - int[] parentLocation = new int[2]; - boundingParent.getLocationInWindow(parentLocation); - - if (translucentStatusBar) { - rect.top = parentLocation[1]; - } - if (translucentNavigationBar) { - rect.bottom = parentLocation[1] + boundingParent.getHeight(); - } - - // We bound the boundaries to be within the screen's coordinates to - // handle the case where the flag FLAG_LAYOUT_NO_LIMITS is set - if (layoutNoLimits) { - topBoundary = Math.max(0, rect.top); - bottomBoundary = Math.min(rect.bottom, displayMetrics.heightPixels); - } else { - topBoundary = rect.top; - bottomBoundary = rect.bottom; - } - } - - drawTintedTarget(); - requestFocus(); - calculateDimensions(); - - startExpandAnimation(); - } - }); + globalLayoutListener = () -> { + if (isDismissing) { + return; } + updateTextLayouts(); + target.onReady(() -> { + final int[] offset = new int[2]; + + targetBounds.set(target.bounds()); + + getLocationOnScreen(offset); + targetBounds.offset(-offset[0], -offset[1]); + + if (boundingParent != null) { + final WindowManager windowManager + = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + final DisplayMetrics displayMetrics = new DisplayMetrics(); + windowManager.getDefaultDisplay().getMetrics(displayMetrics); + + final Rect rect = new Rect(); + boundingParent.getWindowVisibleDisplayFrame(rect); + int[] parentLocation = new int[2]; + boundingParent.getLocationInWindow(parentLocation); + + if (translucentStatusBar) { + rect.top = parentLocation[1]; + } + if (translucentNavigationBar) { + rect.bottom = parentLocation[1] + boundingParent.getHeight(); + } + + // We bound the boundaries to be within the screen's coordinates to + // handle the case where the flag FLAG_LAYOUT_NO_LIMITS is set + if (layoutNoLimits) { + topBoundary = Math.max(0, rect.top); + bottomBoundary = Math.min(rect.bottom, displayMetrics.heightPixels); + } else { + topBoundary = rect.top; + bottomBoundary = rect.bottom; + } + } + + drawTintedTarget(); + requestFocus(); + calculateDimensions(); + + startExpandAnimation(); + }); }; getViewTreeObserver().addOnGlobalLayoutListener(globalLayoutListener); setFocusableInTouchMode(true); setClickable(true); - setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (listener == null || outerCircleCenter == null || !isInteractable) return; - - final boolean clickedInTarget = - distance(targetBounds.centerX(), targetBounds.centerY(), (int) lastTouchX, (int) lastTouchY) <= targetCircleRadius; - final double distanceToOuterCircleCenter = distance(outerCircleCenter[0], outerCircleCenter[1], - (int) lastTouchX, (int) lastTouchY); - final boolean clickedInsideOfOuterCircle = distanceToOuterCircleCenter <= outerCircleRadius; - - if (clickedInTarget) { - isInteractable = false; - listener.onTargetClick(TapTargetView.this); - } else if (clickedInsideOfOuterCircle) { - listener.onOuterCircleClick(TapTargetView.this); - } else if (cancelable) { - isInteractable = false; - listener.onTargetCancel(TapTargetView.this); - } + setOnClickListener(v -> { + if (listener == null || outerCircleCenter == null || !isInteractable) return; + + final boolean clickedInTarget = getTapType().clickInTarget(targetBounds, (int) lastTouchX, (int) lastTouchY); + final double distanceToOuterCircleCenter = distance(outerCircleCenter[0], outerCircleCenter[1], + (int) lastTouchX, (int) lastTouchY); + final boolean clickedInsideOfOuterCircle = distanceToOuterCircleCenter <= outerCircleRadius; + + if (clickedInTarget) { + isInteractable = false; + listener.onTargetClick(TapTargetView.this); + } else if (clickedInsideOfOuterCircle) { + listener.onOuterCircleClick(TapTargetView.this); + } else if (cancelable) { + isInteractable = false; + listener.onTargetCancel(TapTargetView.this); } }); - setOnLongClickListener(new OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - if (listener == null) return false; + setOnLongClickListener(v -> { + if (listener == null) return false; - if (targetBounds.contains((int) lastTouchX, (int) lastTouchY)) { - listener.onTargetLongClick(TapTargetView.this); - return true; - } - - return false; + if (targetBounds.contains((int) lastTouchX, (int) lastTouchY)) { + listener.onTargetLongClick(TapTargetView.this); + return true; } + + return false; }); } @@ -644,12 +598,9 @@ protected void onDraw(Canvas c) { targetCirclePaint.setAlpha(targetCircleAlpha); if (targetCirclePulseAlpha > 0) { targetCirclePulsePaint.setAlpha(targetCirclePulseAlpha); - c.drawCircle(targetBounds.centerX(), targetBounds.centerY(), - targetCirclePulseRadius, targetCirclePulsePaint); + getTapType().drawPulse(c, targetCirclePulseAlpha, targetBounds, targetCirclePulsePaint); } - c.drawCircle(targetBounds.centerX(), targetBounds.centerY(), - targetCircleRadius, targetCirclePaint); - + getTapType().drawTarget(c, targetBounds, targetCirclePaint); saveCount = c.save(); { c.translate(textBounds.left, textBounds.top); @@ -793,7 +744,7 @@ void drawDebugInformation(Canvas c) { c.drawRect(targetBounds, debugPaint); c.drawCircle(outerCircleCenter[0], outerCircleCenter[1], 10, debugPaint); c.drawCircle(outerCircleCenter[0], outerCircleCenter[1], calculatedOuterCircleRadius - CIRCLE_PADDING, debugPaint); - c.drawCircle(targetBounds.centerX(), targetBounds.centerY(), TARGET_RADIUS + TARGET_PADDING, debugPaint); + getTapType().drawInformation(c, targetBounds, targetCirclePaint); // Draw positions and dimensions debugPaint.setStyle(Paint.Style.FILL); @@ -861,22 +812,6 @@ void updateTextLayouts() { } } - float halfwayLerp(float lerp) { - if (lerp < 0.5f) { - return lerp / 0.5f; - } - - return (1.0f - lerp) / 0.5f; - } - - float delayedLerp(float lerp, float threshold) { - if (lerp < threshold) { - return 0.0f; - } - - return (lerp - threshold) / (1.0f - threshold); - } - void calculateDimensions() { textBounds = getTextBounds(); outerCircleCenter = getOuterCircleCenterPoint(); @@ -900,7 +835,7 @@ void calculateDrawingBounds() { int getOuterCircleRadius(int centerX, int centerY, Rect textBounds, Rect targetBounds) { final int targetCenterX = targetBounds.centerX(); final int targetCenterY = targetBounds.centerY(); - final int expandedRadius = (int) (1.1f * TARGET_RADIUS); + final int expandedRadius = (int) (1.1f * getTapType().getEdgeLength()); final Rect expandedBounds = new Rect(targetCenterX, targetCenterY, targetCenterX, targetCenterY); expandedBounds.inset(-expandedRadius, -expandedRadius); @@ -910,15 +845,16 @@ int getOuterCircleRadius(int centerX, int centerY, Rect textBounds, Rect targetB } Rect getTextBounds() { + int targetLength = getTapType().getEdgeLength(); final int totalTextHeight = getTotalTextHeight(); final int totalTextWidth = getTotalTextWidth(); - final int possibleTop = targetBounds.centerY() - TARGET_RADIUS - TARGET_PADDING - totalTextHeight; + final int possibleTop = targetBounds.centerY() - targetLength - TARGET_PADDING - totalTextHeight; final int top; if (possibleTop > topBoundary) { top = possibleTop; } else { - top = targetBounds.centerY() + TARGET_RADIUS + TARGET_PADDING; + top = targetBounds.centerY() + targetLength + TARGET_PADDING; } final int relativeCenterDistance = (getWidth() / 2) - targetBounds.centerX(); @@ -933,18 +869,20 @@ int[] getOuterCircleCenterPoint() { return new int[]{targetBounds.centerX(), targetBounds.centerY()}; } + int edgeLength = getTapType().getEdgeLength(); + final int targetRadius = Math.max(targetBounds.width(), targetBounds.height()) / 2 + TARGET_PADDING; final int totalTextHeight = getTotalTextHeight(); - final boolean onTop = targetBounds.centerY() - TARGET_RADIUS - TARGET_PADDING - totalTextHeight > 0; + final boolean onTop = targetBounds.centerY() - edgeLength - TARGET_PADDING - totalTextHeight > 0; final int left = Math.min(textBounds.left, targetBounds.left - targetRadius); final int right = Math.max(textBounds.right, targetBounds.right + targetRadius); final int titleHeight = titleLayout == null ? 0 : titleLayout.getHeight(); final int centerY = onTop ? - targetBounds.centerY() - TARGET_RADIUS - TARGET_PADDING - totalTextHeight + titleHeight + targetBounds.centerY() - edgeLength - TARGET_PADDING - totalTextHeight + titleHeight : - targetBounds.centerY() + TARGET_RADIUS + TARGET_PADDING + titleHeight; + targetBounds.centerY() + edgeLength + TARGET_PADDING + titleHeight; return new int[] { (left + right) / 2, centerY }; } @@ -999,4 +937,8 @@ void invalidateViewAndOutline(Rect bounds) { invalidateOutline(); } } + + TapTargetShapeType getTapType() { + return target.getTapTargetType$taptargetview_debug(); + } } diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TargetExtensions.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TargetExtensions.kt new file mode 100644 index 0000000..e23c650 --- /dev/null +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TargetExtensions.kt @@ -0,0 +1,90 @@ +@file:Suppress("unused") +package com.getkeepsafe.taptargetview + +import android.graphics.Rect +import android.graphics.drawable.Drawable +import android.view.View +import androidx.annotation.IdRes +import androidx.appcompat.widget.Toolbar +import com.getkeepsafe.taptargetview.target.TapTarget + +/** Return a tap target for the overflow button from the given toolbar + * + * + * **Note:** This is currently experimental, use at your own risk + */ +@JvmOverloads +fun Toolbar?.createOverflow( + title: CharSequence?, + description: CharSequence? = null +): TapTarget { + return ToolbarTapTarget(this, false, title, description) +} +/** Return a tap target for the overflow button from the given toolbar + * + * + * **Note:** This is currently experimental, use at your own risk + */ +@JvmOverloads +fun android.widget.Toolbar?.createOverflow( + title: CharSequence?, + description: CharSequence? = null +): TapTarget { + return ToolbarTapTarget(this, false, title, description) +} +/** Return a tap target for the navigation button (back, up, etc) from the given toolbar */ +@JvmOverloads +fun Toolbar?.createNavigationIcon( + title: CharSequence?, + description: CharSequence? = null +): TapTarget { + return ToolbarTapTarget(this, true, title, description) +} +/** Return a tap target for the navigation button (back, up, etc) from the given toolbar */ +@JvmOverloads +fun android.widget.Toolbar?.createNavigationIcon( + title: CharSequence?, + description: CharSequence? = null +): TapTarget { + return ToolbarTapTarget(this, true, title, description) +} +/** Return a tap target for the menu item from the given toolbar */ +@JvmOverloads +fun Toolbar?.forToolbarMenuItem( + @IdRes menuItemId: Int, + title: CharSequence?, description: CharSequence? = null +): TapTarget { + return ToolbarTapTarget(this, menuItemId, title, description) +} +/** Return a tap target for the menu item from the given toolbar */ +/** Return a tap target for the menu item from the given toolbar */ +@JvmOverloads +fun android.widget.Toolbar?.forToolbarMenuItem( + @IdRes menuItemId: Int, + title: CharSequence?, description: CharSequence? = null +): TapTarget { + return ToolbarTapTarget(this, menuItemId, title, description) +} +/** Return a tap target for the specified view */ +@JvmOverloads +fun View?.createTarget( + title: CharSequence, + description: CharSequence? = null +): TapTarget { + requireNotNull(this) { + "Cannot create tap target with null" + } + return TapTarget(this, title, description) +} +/** Return a tap target for the specified bounds */ +@JvmOverloads +fun Drawable?.createTarget( + bounds: Rect?, + title: CharSequence?, + description: CharSequence? = null +): TapTarget { + requireNotNull(this) { + "Cannot create tap target with null" + } + return TapTarget(this, title, description, bounds) +} \ No newline at end of file diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TargetViewExtensions.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TargetViewExtensions.kt index d1095b0..a6dd51f 100644 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TargetViewExtensions.kt +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TargetViewExtensions.kt @@ -8,6 +8,7 @@ import android.graphics.PixelFormat import android.view.Gravity import android.view.ViewGroup import android.view.WindowManager +import com.getkeepsafe.taptargetview.target.TapTarget @JvmName("showGuideView") fun Activity?.showGuideView( diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ToolbarTapTarget.java b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ToolbarTapTarget.java index 547f4a4..78e6149 100644 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ToolbarTapTarget.java +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ToolbarTapTarget.java @@ -30,23 +30,25 @@ import androidx.annotation.Nullable; import androidx.appcompat.widget.Toolbar; -class ToolbarTapTarget extends ViewTapTarget { - ToolbarTapTarget(Toolbar toolbar, @IdRes int menuItemId, +import com.getkeepsafe.taptargetview.target.TapTarget; + +public class ToolbarTapTarget extends TapTarget { + public ToolbarTapTarget(Toolbar toolbar, @IdRes int menuItemId, CharSequence title, @Nullable CharSequence description) { super(toolbar.findViewById(menuItemId), title, description); } - ToolbarTapTarget(android.widget.Toolbar toolbar, @IdRes int menuItemId, + public ToolbarTapTarget(android.widget.Toolbar toolbar, @IdRes int menuItemId, CharSequence title, @Nullable CharSequence description) { super(toolbar.findViewById(menuItemId), title, description); } - ToolbarTapTarget(Toolbar toolbar, boolean findNavView, + public ToolbarTapTarget(Toolbar toolbar, boolean findNavView, CharSequence title, @Nullable CharSequence description) { super(findNavView ? findNavView(toolbar) : findOverflowView(toolbar), title, description); } - ToolbarTapTarget(android.widget.Toolbar toolbar, boolean findNavView, + public ToolbarTapTarget(android.widget.Toolbar toolbar, boolean findNavView, CharSequence title, @Nullable CharSequence description) { super(findNavView ? findNavView(toolbar) : findOverflowView(toolbar), title, description); } diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ValueUtils.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ValueUtils.kt new file mode 100644 index 0000000..62ccd0f --- /dev/null +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ValueUtils.kt @@ -0,0 +1,14 @@ +@file:JvmName("ValueExtensions") +package com.getkeepsafe.taptargetview + + +internal val Float.halfwayLerp: Float + get() { + if (this < 0.5f) return this / 0.5f + return (1.0f - this) / 0.5f + } + +internal fun Float.getDelayLerp(threshold: Float): Float { + if (this < threshold) return 0f + return (this - threshold) / (1.0f - threshold) +} \ No newline at end of file diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewTapTarget.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewTapTarget.kt deleted file mode 100644 index 1733adb..0000000 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/ViewTapTarget.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.getkeepsafe.taptargetview - -import android.graphics.Canvas -import android.graphics.Rect -import android.graphics.drawable.BitmapDrawable -import android.view.View -import androidx.core.view.doOnLayout -import androidx.core.view.drawToBitmap - -open class ViewTapTarget @JvmOverloads constructor( - private val view: View, - title: CharSequence, - description: CharSequence? = null -): TapTarget(title, description) { - - override fun onReady(runnable: Runnable?) { - view.doOnLayout { - val location = IntArray(2) - view.getLocationOnScreen(location) - bounds = Rect( - location[0], - location[1], - location[0] + view.width, - location[1] + view.height - ) - if (icon == null && view.width > 0 && view.height > 0) { - val viewBitmap = view.drawToBitmap() - val canvas = Canvas(viewBitmap) - view.draw(canvas) - val icon = BitmapDrawable(view.context.resources, viewBitmap) - icon.setBounds(0, 0, view.width, view.height) - this.icon = icon - } - runnable?.run() - } - } - -} \ No newline at end of file diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/CircleShapeTapTarget.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/CircleShapeTapTarget.kt new file mode 100644 index 0000000..bc580f3 --- /dev/null +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/CircleShapeTapTarget.kt @@ -0,0 +1,100 @@ +package com.getkeepsafe.taptargetview.target + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Rect +import com.getkeepsafe.taptargetview.dp +import com.getkeepsafe.taptargetview.getDelayLerp +import com.getkeepsafe.taptargetview.halfwayLerp +import kotlin.math.pow +import kotlin.math.roundToInt + +object CircleShapeTapTarget: TapTargetShapeType { + + private var targetRadius = 44 + + private var targetCircleRadius = 0f + + private var targetCirclePulseRadius = 0f + + private var TARGET_RADIUS = 0 + + private var TARGET_PULSE_RADIUS = 0 + + + /** + * 用于测量文本,圆心等位置的 + */ + override val edgeLength: Int get() = TARGET_RADIUS + + /** Specify the target radius in dp. */ + fun setTargetRadius(targetRadius: Int): CircleShapeTapTarget { + this.targetRadius = targetRadius + return this + } + + override fun initResource(context: Context) { + TARGET_RADIUS = targetRadius.dp + TARGET_PULSE_RADIUS = (TARGET_RADIUS * 0.1f).roundToInt() + } + + override fun expandContractChange(lerpTime: Float, isExpanding: Boolean) { + if (isExpanding) { + targetCircleRadius = TARGET_RADIUS * 1.0f.coerceAtMost(lerpTime * 1.5f) + } else { + targetCircleRadius = TARGET_RADIUS * lerpTime + targetCirclePulseRadius *= lerpTime + } + } + + override fun pulseAnimation(lerpTime: Float) { + targetCirclePulseRadius = (1.0f + lerpTime.getDelayLerp(0.5f)) * TARGET_RADIUS + targetCircleRadius = TARGET_RADIUS + lerpTime.halfwayLerp * TARGET_PULSE_RADIUS + } + + override fun dismissConfirmAnimation(lerpTime: Float) { + targetCircleRadius = (1.0f - lerpTime) * TARGET_RADIUS + targetCirclePulseRadius = (1.0f + lerpTime) * TARGET_RADIUS + } + + override fun drawTarget( + canvas: Canvas, + targetBounds: Rect, + paint: Paint + ) { + canvas.drawCircle( + targetBounds.centerX().toFloat(), targetBounds.centerY().toFloat(), + targetCircleRadius, paint + ) + } + + override fun drawPulse( + canvas: Canvas, + targetPulseAlpha: Float, + targetBounds: Rect, + paint: Paint + ) { + if (targetPulseAlpha < 0) return + canvas.drawCircle( + targetBounds.centerX().toFloat(), targetBounds.centerY().toFloat(), + targetCirclePulseRadius, paint + ) + } + + override fun drawInformation(canvas: Canvas, targetBounds: Rect, paint: Paint) { + canvas.drawCircle( + targetBounds.centerX().toFloat(), + targetBounds.centerY().toFloat(), + TARGET_RADIUS + 20.dp.toFloat(), + paint + ) + } + + override fun clickInTarget(targetBounds: Rect, lastTouchX: Int, lastTouchY: Int): Boolean { + val xPow = (lastTouchX - targetBounds.centerX()).toDouble().pow(2.0) + val yPow = (lastTouchY - targetBounds.centerY()).toDouble().pow(2.0) + val sqrt = (xPow + yPow).pow(0.5) + return sqrt <= targetCircleRadius + } +} \ No newline at end of file diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/RectAngleShapeType.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/RectAngleShapeType.kt new file mode 100644 index 0000000..0e68dca --- /dev/null +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/RectAngleShapeType.kt @@ -0,0 +1,112 @@ +@file:Suppress("unused") +package com.getkeepsafe.taptargetview.target + +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Rect +import android.graphics.RectF +import com.getkeepsafe.taptargetview.dp +import com.getkeepsafe.taptargetview.getDelayLerp +import com.getkeepsafe.taptargetview.halfwayLerp + +object RectAngleShapeType : TapTargetShapeType { + + private var width = 0 + + private var height = 0 + + private var drawWidth = 0f + + private var drawHeight = 0f + + private var pulseLength = 4.dp + + private var drawPulseWidth= 0f + + private var drawPulseHeight = 0f + + internal var roundRadius = 8.dp + + override val edgeLength: Int + get() = 8.dp + + override fun onReadyTarget(bounds: Rect?) { + checkNotNull(bounds) + this.width = bounds.width() + this.height = bounds.height() + } + + override fun expandContractChange(lerpTime: Float, isExpanding: Boolean) { + if (isExpanding) { + drawHeight = height * 1.0f.coerceAtMost(lerpTime * 1.5f) + drawWidth = width * 1.0f.coerceAtMost(lerpTime * 1.5f) + } else { + drawHeight = height * lerpTime + drawWidth = width * lerpTime + drawPulseWidth *= lerpTime + drawPulseHeight *= lerpTime + } + } + + override fun dismissConfirmAnimation(lerpTime: Float) { + drawHeight = height * (1.0f - lerpTime) + drawWidth = width * (1.0f - lerpTime) + drawPulseWidth = (1.0f + lerpTime) * width + drawPulseHeight = (1.0f + lerpTime) * height + } + + override fun pulseAnimation(lerpTime: Float) { + drawWidth = width + lerpTime.halfwayLerp * pulseLength + drawHeight = height + lerpTime.halfwayLerp * pulseLength + drawPulseHeight = (1.0f + lerpTime.getDelayLerp(0.5f)) * height + drawPulseWidth = (1.0f + lerpTime.getDelayLerp(0.5f)) * width + } + + override fun drawTarget(canvas: Canvas, targetBounds: Rect, paint: Paint) { + canvas.drawRoundRect( + targetBounds.toTargetRectF( + drawWidth, drawHeight + ), + roundRadius.toFloat(), + roundRadius.toFloat(), + paint + ) + } + + private fun Rect.toTargetRectF( + width: Float, + height: Float + ): RectF { + val centerX = centerX() + val centerY = centerY() + val right = width * 0.5f + roundRadius / 2 + val bottom = height * 0.5f + roundRadius / 2 + return RectF( + centerX - right, + centerY - bottom, + centerX + right, + centerY + bottom + ) + } + + override fun drawPulse( + canvas: Canvas, + targetPulseAlpha: Float, + targetBounds: Rect, + paint: Paint + ) { + if (targetPulseAlpha < 0) return + canvas.drawRoundRect( + targetBounds.toTargetRectF( + drawPulseWidth, drawPulseHeight + ), + roundRadius.toFloat(), + roundRadius.toFloat(), + paint + ) + } + + override fun clickInTarget(targetBounds: Rect, lastTouchX: Int, lastTouchY: Int): Boolean { + return targetBounds.contains(lastTouchX, lastTouchY) + } +} \ No newline at end of file diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/TapTarget.kt similarity index 62% rename from taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.kt rename to taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/TapTarget.kt index 58157f1..ff7ca30 100644 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.kt +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/TapTarget.kt @@ -1,25 +1,67 @@ @file:Suppress("unused") -package com.getkeepsafe.taptargetview +package com.getkeepsafe.taptargetview.target import android.content.Context +import android.graphics.Canvas import android.graphics.Rect import android.graphics.Typeface +import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable import android.view.View import androidx.annotation.ColorInt import androidx.annotation.ColorRes import androidx.annotation.DimenRes -import androidx.annotation.IdRes -import androidx.appcompat.widget.Toolbar import androidx.core.content.ContextCompat +import androidx.core.view.doOnLayout +import androidx.core.view.drawToBitmap +import com.getkeepsafe.taptargetview.sp -open class TapTarget protected constructor(title: CharSequence?, description: CharSequence?) { - val title: CharSequence +open class TapTarget { + + private var view: View? = null + + val title: CharSequence? val description: CharSequence? - var outerCircleAlpha = 0.96f - var targetRadius = 44 - var bounds: Rect? = null + private var bounds: Rect? var icon: Drawable? = null + + internal var tapTargetType: TapTargetShapeType = CircleShapeTapTarget + + @JvmOverloads + constructor( + view: View, + title: CharSequence?, + description: CharSequence?, + bounds: Rect? = null + ) { + this.view = view + this.title = title + this.description = description + this.bounds = bounds + } + + @JvmOverloads + constructor( + icon: Drawable, + title: CharSequence?, + description: CharSequence?, + bounds: Rect? = null, + iconBounds: Rect? = null + ) { + this.icon = icon + if (iconBounds == null) { + icon.bounds = Rect(0, 0, icon.intrinsicWidth, icon.intrinsicHeight) + } else { + icon.bounds = iconBounds + } + this.title = title + this.description = description + this.bounds = bounds + } + + var outerCircleAlpha = 0.96f + private set + var titleTypeface: Typeface? = null var descriptionTypeface: Typeface? = null @@ -27,7 +69,7 @@ open class TapTarget protected constructor(title: CharSequence?, description: Ch private var outerCircleColorRes = -1 @ColorRes - private var targetCircleColorRes = -1 + private var targetIconColorRes = -1 @ColorRes private var dimColorRes = -1 @@ -38,7 +80,7 @@ open class TapTarget protected constructor(title: CharSequence?, description: Ch @ColorRes private var descriptionTextColorRes = -1 private var outerCircleColor: Int? = null - private var targetCircleColor: Int? = null + private var targetIconColor: Int? = null private var dimColor: Int? = null private var titleTextColor: Int? = null private var descriptionTextColor: Int? = null @@ -57,21 +99,6 @@ open class TapTarget protected constructor(title: CharSequence?, description: Ch var transparentTarget = false var descriptionTextAlpha = 0.54f - protected constructor( - bounds: Rect?, - title: CharSequence?, - description: CharSequence? - ): this(title, description) { - requireNotNull(bounds) { "Cannot pass null bounds or title" } - this.bounds = bounds - } - - init { - requireNotNull(title) { "Cannot pass null title" } - this.title = title - this.description = description - } - /** Specify whether the target should be transparent */ fun transparentTarget(transparent: Boolean): TapTarget { transparentTarget = transparent @@ -98,14 +125,14 @@ open class TapTarget protected constructor(title: CharSequence?, description: Ch } /** Specify the color resource for the target circle */ - fun targetCircleColor(@ColorRes color: Int): TapTarget { - targetCircleColorRes = color + fun targetIconColor(@ColorRes color: Int): TapTarget { + targetIconColorRes = color return this } /** Specify the color value for the target circle */ - fun targetCircleColorInt(@ColorInt color: Int): TapTarget { - targetCircleColor = color + fun targetIconColorInt(@ColorInt color: Int): TapTarget { + targetIconColor = color return this } @@ -251,22 +278,6 @@ open class TapTarget protected constructor(title: CharSequence?, description: Ch tintTarget = tint return this } - /** - * Specify the icon that will be drawn in the center of the target bounds - * @param hasSetBounds Whether the drawable already has its bounds correctly set. If the - * drawable does not have its bounds set, then the following bounds will - * be applied:

- * `(0, 0, intrinsic-width, intrinsic-height)` - */ - @JvmOverloads - fun icon(icon: Drawable?, hasSetBounds: Boolean = false): TapTarget { - requireNotNull(icon) { "Cannot use null drawable" } - this.icon = icon - if (!hasSetBounds) { - icon.bounds = Rect(0, 0, icon.intrinsicWidth, icon.intrinsicHeight) - } - return this - } /** Specify a unique identifier for this target. */ fun id(id: Int): TapTarget { @@ -274,12 +285,6 @@ open class TapTarget protected constructor(title: CharSequence?, description: Ch return this } - /** Specify the target radius in dp. */ - fun targetRadius(targetRadius: Int): TapTarget { - this.targetRadius = targetRadius - return this - } - /** Return the id associated with this tap target */ fun id(): Int { return id @@ -290,7 +295,31 @@ open class TapTarget protected constructor(title: CharSequence?, description: Ch * runnable passed here will be invoked when the target is ready. */ open fun onReady(runnable: Runnable?) { - runnable?.run() + val view = this.view ?: kotlin.run { + runnable?.run() + tapTargetType.onReadyTarget(bounds) + return + } + view.doOnLayout { + val location = IntArray(2) + view.getLocationOnScreen(location) + bounds = Rect( + location[0], + location[1], + location[0] + view.width, + location[1] + view.height + ) + if (icon == null && view.width > 0 && view.height > 0) { + val viewBitmap = view.drawToBitmap() + val canvas = Canvas(viewBitmap) + view.draw(canvas) + val icon = BitmapDrawable(view.context.resources, viewBitmap) + icon.setBounds(0, 0, view.width, view.height) + this.icon = icon + } + tapTargetType.onReadyTarget(bounds) + runnable?.run() + } } /** @@ -310,7 +339,7 @@ open class TapTarget protected constructor(title: CharSequence?, description: Ch } fun targetCircleColorInt(context: Context): Int? { - return colorResOrInt(context, targetCircleColor, targetCircleColorRes) + return colorResOrInt(context, targetIconColor, targetIconColorRes) } fun dimColorInt(context: Context): Int? { @@ -345,97 +374,9 @@ open class TapTarget protected constructor(title: CharSequence?, description: Ch } else size.sp } - companion object { - /** Return a tap target for the overflow button from the given toolbar - * - * - * **Note:** This is currently experimental, use at your own risk - */ - /** - * Return a tap target for the overflow button from the given toolbar - * - * - * **Note:** This is currently experimental, use at your own risk - */ - @JvmOverloads - fun forToolbarOverflow( - toolbar: Toolbar?, title: CharSequence?, - description: CharSequence? = null - ): TapTarget { - return ToolbarTapTarget(toolbar, false, title, description) - } - /** Return a tap target for the overflow button from the given toolbar - * - * - * **Note:** This is currently experimental, use at your own risk - */ - /** Return a tap target for the overflow button from the given toolbar - * - * - * **Note:** This is currently experimental, use at your own risk - */ - @JvmOverloads - fun forToolbarOverflow( - toolbar: android.widget.Toolbar?, title: CharSequence?, - description: CharSequence? = null - ): TapTarget { - return ToolbarTapTarget(toolbar, false, title, description) - } - /** Return a tap target for the navigation button (back, up, etc) from the given toolbar */ - /** Return a tap target for the navigation button (back, up, etc) from the given toolbar */ - @JvmOverloads - fun forToolbarNavigationIcon( - toolbar: Toolbar?, title: CharSequence?, - description: CharSequence? = null - ): TapTarget { - return ToolbarTapTarget(toolbar, true, title, description) - } - /** Return a tap target for the navigation button (back, up, etc) from the given toolbar */ - /** Return a tap target for the navigation button (back, up, etc) from the given toolbar */ - @JvmOverloads - fun forToolbarNavigationIcon( - toolbar: android.widget.Toolbar?, title: CharSequence?, - description: CharSequence? = null - ): TapTarget { - return ToolbarTapTarget(toolbar, true, title, description) - } - /** Return a tap target for the menu item from the given toolbar */ - /** Return a tap target for the menu item from the given toolbar */ - @JvmOverloads - fun forToolbarMenuItem( - toolbar: Toolbar?, @IdRes menuItemId: Int, - title: CharSequence?, description: CharSequence? = null - ): TapTarget { - return ToolbarTapTarget(toolbar, menuItemId, title, description) - } - /** Return a tap target for the menu item from the given toolbar */ - /** Return a tap target for the menu item from the given toolbar */ - @JvmOverloads - fun forToolbarMenuItem( - toolbar: android.widget.Toolbar?, @IdRes menuItemId: Int, - title: CharSequence?, description: CharSequence? = null - ): TapTarget { - return ToolbarTapTarget(toolbar, menuItemId, title, description) - } - /** Return a tap target for the specified view */ - /** Return a tap target for the specified view */ - @JvmOverloads - fun forView( - view: View, - title: CharSequence, - description: CharSequence? = null - ): TapTarget { - return ViewTapTarget(view, title, description) - } - /** Return a tap target for the specified bounds */ - /** Return a tap target for the specified bounds */ - @JvmOverloads - fun forBounds( - bounds: Rect?, - title: CharSequence?, - description: CharSequence? = null - ): TapTarget { - return TapTarget(bounds, title, description) - } + fun setTargetShapeType(type: TapTargetShapeType): TapTarget { + this.tapTargetType = type + return this } + } \ No newline at end of file diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/TapTargetShapeType.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/TapTargetShapeType.kt new file mode 100644 index 0000000..5c20228 --- /dev/null +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/TapTargetShapeType.kt @@ -0,0 +1,55 @@ +@file:Suppress("unused") +package com.getkeepsafe.taptargetview.target + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Rect + +interface TapTargetShapeType { + + companion object { + + val Circle = CircleShapeTapTarget + + val RectAngle = RectAngleShapeType + + fun RectAngle(roundRadius: Int): RectAngleShapeType { + RectAngleShapeType.roundRadius = roundRadius + return RectAngleShapeType + } + + } + + + val edgeLength: Int + + fun initResource(context: Context) {} + + fun expandContractChange(lerpTime: Float, isExpanding: Boolean) + + fun pulseAnimation(lerpTime: Float) {} + + fun dismissConfirmAnimation(lerpTime: Float) + + fun drawTarget( + canvas: Canvas, + targetBounds: Rect, + paint: Paint + ) + + fun drawPulse( + canvas: Canvas, + targetPulseAlpha: Float, + targetBounds: Rect, + paint: Paint + ) {} + + fun drawInformation(canvas: Canvas, targetBounds: Rect, paint: Paint) {} + + fun clickInTarget(targetBounds: Rect, lastTouchX: Int, lastTouchY: Int): Boolean + + fun onReadyTarget(bounds: Rect?) {} + +} + From 9177619ac57f5421651195dce78729d1f41bf6c8 Mon Sep 17 00:00:00 2001 From: huaweikai <1297720454@qq.com> Date: Sun, 6 Aug 2023 02:07:52 +0800 Subject: [PATCH 4/5] -update README.md --- README.md | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 0e34cfd..edd554e 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@

Video 1 Screenshot 1 -Screenshot 2 -Screenshot 2
+Screenshot 2 +Screenshot 2
TapTargetView

@@ -13,7 +13,7 @@ An implementation of tap targets from [Google's Material Design guidelines on feature discovery](https://material.io/archive/guidelines/growth-communications/feature-discovery.html). - **Min SDK:** 14 + **Min SDK:** 21 [JavaDoc](https://javadoc.jitpack.io/com/github/KeepSafe/TapTargetView/latest/javadoc/) @@ -21,15 +21,7 @@ An implementation of tap targets from [Google's Material Design guidelines on fe TapTargetView is distributed using [MavenCentral](https://search.maven.org/artifact/com.getkeepsafe.taptargetview/taptargetview). -```groovy - repositories { - mavenCentral() - } - - dependencies { - implementation 'com.getkeepsafe.taptargetview:taptargetview:x.x.x' - } -``` +## No Publish If you wish, you may also use TapTargetView with [jitpack](https://jitpack.io/#KeepSafe/TapTargetView). For snapshots, please follow the instructions [here](https://jitpack.io/#KeepSafe/TapTargetView/-SNAPSHOT). @@ -60,7 +52,6 @@ For snapshots, please follow the instructions [here](https://jitpack.io/#KeepSaf .setTargetShapeType(TapTargetShapeType.RectAngle(16)), null ); - } ``` You may also choose to target your own custom `Rect` with `TapTarget.forBounds(Rect, ...)` From 84c5a09fe98adac1a0ad27ead4c4c963f09301d9 Mon Sep 17 00:00:00 2001 From: huaweikai <1297720454@qq.com> Date: Wed, 9 Aug 2023 10:55:14 +0800 Subject: [PATCH 5/5] -Putting more attributes in TapTargetShapeType can customize the settings, and in order to prevent conflicts between each TapTargetView, it will not be used as a singleton, and a new object will be used for each use to prevent data confusion. -In the RectangleType mode, the text may be incompletely displayed or blocked by the targetView. Repairs have been made, and the method of obtaining textBounds is migrated to TapTargetShapeType. The author does not modify the original one, but modifies the RectAngleShapeType to obtain the correct display coordinates. . --- .../taptargetviewsample/MainActivity.kt | 6 +- app/src/main/res/layout/activity_main.xml | 9 +- .../taptargetview/TapTargetView.java | 28 ++---- .../target/CircleShapeTapTarget.kt | 2 +- .../target/RectAngleShapeType.kt | 16 +++- .../taptargetview/target/TapTarget.kt | 2 +- .../target/TapTargetShapeType.kt | 90 +++++++++++++++---- 7 files changed, 106 insertions(+), 47 deletions(-) diff --git a/app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.kt b/app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.kt index 40684f0..526ec90 100644 --- a/app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.kt +++ b/app/src/main/java/com/getkeepsafe/taptargetviewsample/MainActivity.kt @@ -146,10 +146,10 @@ class MainActivity : AppCompatActivity() { } }) - val ed = findViewById(R.id.ed) + val ed = findViewById(R.id.ed) ed.setOnClickListener { showGuideView( - ed.createTarget("Please Input Some Thing") + ed.createTarget("Please Input Some Thing", "Hello Some One") .outerCircleColor(R.color.colorAccent) .targetIconColor(android.R.color.holo_blue_dark) .transparentTarget(true) @@ -159,7 +159,7 @@ class MainActivity : AppCompatActivity() { override fun onTargetClick(view: TapTargetView) { Toast.makeText( view.context, - "You clicked the target!", + "You clicked the target! yes!!!!!", Toast.LENGTH_SHORT ).show() super.onTargetClick(view) diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 5af03ba..9011d35 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -62,14 +62,13 @@ android:layout_height="wrap_content" android:padding="16dp"/> - diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java index f0fafff..a8c543d 100644 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTargetView.java @@ -304,12 +304,12 @@ public TapTargetView(final Context context, this.title = target.getTitle(); this.description = target.getDescription(); - TARGET_PADDING = UiUtils.getDp( 20); - CIRCLE_PADDING = UiUtils.getDp( 40); - TEXT_PADDING = UiUtils.getDp( 40); - TEXT_SPACING = UiUtils.getDp( 8); - TEXT_MAX_WIDTH = UiUtils.getDp( 360); - TEXT_POSITIONING_BIAS = UiUtils.getDp( 20); + TARGET_PADDING = getTapType().getTargetPadding(); + CIRCLE_PADDING = getTapType().getCirclePadding(); + TEXT_PADDING = getTapType().getTextPadding(); + TEXT_SPACING = getTapType().getTextSpacing(); + TEXT_MAX_WIDTH = getTapType().getTextMaxWidth(); + TEXT_POSITIONING_BIAS = getTapType().getTextPositionBias(); GUTTER_DIM = UiUtils.getDp( 88); SHADOW_DIM = UiUtils.getDp( 8); SHADOW_JITTER_DIM = UiUtils.getDp( 1); @@ -845,23 +845,9 @@ int getOuterCircleRadius(int centerX, int centerY, Rect textBounds, Rect targetB } Rect getTextBounds() { - int targetLength = getTapType().getEdgeLength(); final int totalTextHeight = getTotalTextHeight(); final int totalTextWidth = getTotalTextWidth(); - - final int possibleTop = targetBounds.centerY() - targetLength - TARGET_PADDING - totalTextHeight; - final int top; - if (possibleTop > topBoundary) { - top = possibleTop; - } else { - top = targetBounds.centerY() + targetLength + TARGET_PADDING; - } - - final int relativeCenterDistance = (getWidth() / 2) - targetBounds.centerX(); - final int bias = relativeCenterDistance < 0 ? -TEXT_POSITIONING_BIAS : TEXT_POSITIONING_BIAS; - final int left = Math.max(TEXT_PADDING, targetBounds.centerX() - bias - totalTextWidth); - final int right = Math.min(getWidth() - TEXT_PADDING, left + totalTextWidth); - return new Rect(left, top, right, top + totalTextHeight); + return getTapType().getTextBounds(totalTextHeight, totalTextWidth, targetBounds, topBoundary, getWidth()); } int[] getOuterCircleCenterPoint() { diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/CircleShapeTapTarget.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/CircleShapeTapTarget.kt index bc580f3..5a557e2 100644 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/CircleShapeTapTarget.kt +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/CircleShapeTapTarget.kt @@ -10,7 +10,7 @@ import com.getkeepsafe.taptargetview.halfwayLerp import kotlin.math.pow import kotlin.math.roundToInt -object CircleShapeTapTarget: TapTargetShapeType { +class CircleShapeTapTarget: TapTargetShapeType() { private var targetRadius = 44 diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/RectAngleShapeType.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/RectAngleShapeType.kt index 0e68dca..d20866b 100644 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/RectAngleShapeType.kt +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/RectAngleShapeType.kt @@ -9,7 +9,7 @@ import com.getkeepsafe.taptargetview.dp import com.getkeepsafe.taptargetview.getDelayLerp import com.getkeepsafe.taptargetview.halfwayLerp -object RectAngleShapeType : TapTargetShapeType { +class RectAngleShapeType : TapTargetShapeType() { private var width = 0 @@ -106,6 +106,20 @@ object RectAngleShapeType : TapTargetShapeType { ) } + override fun getTextVertical( + targetBounds: Rect, + totalTextHeight: Int, + topBoundary: Int + ): Pair { + val possibleTop = targetBounds.top - edgeLength - totalTextHeight - textPadding + val top = if (possibleTop > topBoundary) { + possibleTop + } else { + targetBounds.centerY() + edgeLength + targetPadding + } + return top to top + totalTextHeight + } + override fun clickInTarget(targetBounds: Rect, lastTouchX: Int, lastTouchY: Int): Boolean { return targetBounds.contains(lastTouchX, lastTouchY) } diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/TapTarget.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/TapTarget.kt index ff7ca30..a44f788 100644 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/TapTarget.kt +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/TapTarget.kt @@ -25,7 +25,7 @@ open class TapTarget { private var bounds: Rect? var icon: Drawable? = null - internal var tapTargetType: TapTargetShapeType = CircleShapeTapTarget + internal var tapTargetType: TapTargetShapeType = TapTargetShapeType.Circle @JvmOverloads constructor( diff --git a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/TapTargetShapeType.kt b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/TapTargetShapeType.kt index 5c20228..817a045 100644 --- a/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/TapTargetShapeType.kt +++ b/taptargetview/src/main/java/com/getkeepsafe/taptargetview/target/TapTargetShapeType.kt @@ -5,51 +5,111 @@ import android.content.Context import android.graphics.Canvas import android.graphics.Paint import android.graphics.Rect +import com.getkeepsafe.taptargetview.dp + +abstract class TapTargetShapeType { + + var textPadding = 40.dp + + var circlePadding = 40.dp + + var textSpacing = 8.dp + + var textMaxWidth = 360.dp + + var targetPadding = 20.dp + + var textPositionBias = 20.dp -interface TapTargetShapeType { companion object { - val Circle = CircleShapeTapTarget + val Circle = CircleShapeTapTarget() - val RectAngle = RectAngleShapeType + val RectAngle = RectAngleShapeType() fun RectAngle(roundRadius: Int): RectAngleShapeType { - RectAngleShapeType.roundRadius = roundRadius - return RectAngleShapeType + val rectangleType = RectAngleShapeType() + rectangleType.roundRadius = roundRadius + return rectangleType } } - val edgeLength: Int + abstract val edgeLength: Int - fun initResource(context: Context) {} + open fun initResource(context: Context) {} - fun expandContractChange(lerpTime: Float, isExpanding: Boolean) + abstract fun expandContractChange(lerpTime: Float, isExpanding: Boolean) - fun pulseAnimation(lerpTime: Float) {} + open fun pulseAnimation(lerpTime: Float) {} - fun dismissConfirmAnimation(lerpTime: Float) + abstract fun dismissConfirmAnimation(lerpTime: Float) - fun drawTarget( + abstract fun drawTarget( canvas: Canvas, targetBounds: Rect, paint: Paint ) - fun drawPulse( + open fun drawPulse( canvas: Canvas, targetPulseAlpha: Float, targetBounds: Rect, paint: Paint ) {} - fun drawInformation(canvas: Canvas, targetBounds: Rect, paint: Paint) {} + open fun drawInformation(canvas: Canvas, targetBounds: Rect, paint: Paint) {} - fun clickInTarget(targetBounds: Rect, lastTouchX: Int, lastTouchY: Int): Boolean + abstract fun clickInTarget(targetBounds: Rect, lastTouchX: Int, lastTouchY: Int): Boolean - fun onReadyTarget(bounds: Rect?) {} + open fun onReadyTarget(bounds: Rect?) {} + + open fun getTextBounds( + totalTextHeight: Int, + totalTextWidth: Int, + targetBounds: Rect, + topBoundary: Int, + viewWidth: Int + ): Rect { + val verticalLocation = getTextVertical(targetBounds, totalTextHeight, topBoundary) + val horizontalLocation = getTextHorizontal(targetBounds, totalTextWidth, viewWidth, viewWidth) + return Rect( + horizontalLocation.first, + verticalLocation.first, + horizontalLocation.second, + verticalLocation.second + ) + } + + open fun getTextVertical( + targetBounds: Rect, + totalTextHeight: Int, + topBoundary: Int + ): Pair { + val possibleTop = targetBounds.centerY() - edgeLength - targetPadding - totalTextHeight + val top = if (possibleTop > topBoundary) { + possibleTop + } else { + targetBounds.centerY() + edgeLength + targetPadding + } + return top to top + totalTextHeight + } + + open fun getTextHorizontal( + targetBounds: Rect, + totalTextWidth: Int, + leftBoundary: Int, + viewWidth: Int + ): Pair { + val relativeCenterDistance: Int = viewWidth / 2 - targetBounds.centerX() + val bias: Int = + if (relativeCenterDistance < 0) -textPositionBias else textPositionBias + val left: Int = textPadding.coerceAtLeast(targetBounds.centerX() - bias - totalTextWidth) + val right = (viewWidth - textPadding).coerceAtMost(left + totalTextWidth) + return left to right + } }