diff --git a/README.md b/README.md index e5a16c4..93adb33 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # virtual-joystick-android -**v1.10.1** _(New version - [support custom images](#image), button & background size, limited direction, normalized coordinate, alpha border)_ + +**v1.13.5** _(New version - [support custom images](#image), button & background size, limited direction, normalized coordinate, alpha border, Rectangle or circle support)_ _I created this very simple library as a learning process and I have been inspired by this project [JoystickView](https://github.com/zerokol/JoystickView) (the author is a genius!)_ @@ -22,7 +23,7 @@ protected void onCreate(Bundle savedInstanceState) { JoystickView joystick = (JoystickView) findViewById(R.id.joystickView); joystick.setOnMoveListener(new JoystickView.OnMoveListener() { @Override - public void onMove(int angle, int strength) { + public void onMove(int angle, int strength, MotionEvent event) { // do whatever you want } }); @@ -32,14 +33,10 @@ The **angle** follow the rules of a simple **counter-clock** protractor. The **s ![Alt text](/misc/virtual-joystick.png?raw=true "Explanation") -By default the **refresh rate** to get the data is **20/sec (every 50ms)**. If you want more or less just set the listener with one more parameters to set the refresh rate in milliseconds. -```java -joystick.setOnMoveListener(new JoystickView.OnMoveListener() { ... }, 17); // around 60/sec -``` ### Attributes -You can customize the joystick according to these attributes `JV_buttonImage`, `JV_buttonColor`, `JV_buttonSizeRatio`, `JV_borderColor`, `JV_borderAlpha`, `JV_borderWidth`, `JV_backgroundColor`, `JV_backgroundSizeRatio`, `JV_fixedCenter`, `JV_autoReCenterButton`, `JV_buttonStickToBorder`, `JV_enabled` and `JV_buttonDirection` +You can customize the joystick according to these attributes `JV_useRectangle`,`JV_axisToCenter`, `JV_buttonImage`, `JV_buttonColor`, `JV_buttonSizeRatio`, `JV_borderColor`, `JV_borderAlpha`, `JV_borderWidth`, `JV_backgroundColor`, `JV_backgroundSizeRatio`, `JV_fixedCenter`, `JV_autoReCenterButton`, `JV_buttonStickToBorder`, `JV_enabled` and `JV_buttonDirection` If you specified `JV_buttonImage` you don't need `JV_buttonColor` @@ -70,13 +67,18 @@ If you want a more customized joystick, you can use `JV_buttonImage` and the reg ![Alt text](/misc/android-virtual-joystick-custom-image.png?raw=true "Left joystick with custom image") +#### Rectangle +It is possible to combine several configurations to create something new, such as a linear bar + +![Alt text](/misc/virtual-joystick-android-rectangle.png?raw=true "rectangle joystick with vertical axis") + #### SizeRatio We can change the default size of the button and background. The size is calculated as a percentage of the total width/height. -By default, the button is 25% (0.25) and the background 75% (0.25), as the first screenshot above. +By default, the button is 25% (25) and the background 75% (75), as the first screenshot above. -If the total (background + button) is above 1.0, the button will probably be a bit cut when on the border. +If the total (background + button) is above 100%, the button will probably be a bit cut when on the border. ```xml <... @@ -86,12 +88,10 @@ If the total (background + button) is above 1.0, the button will probably be a b ``` ```java -joystick.setBackgroundSizeRatio(0.5); -joystick.setButtonSizeRatio(0.1); +joystick.setBackgroundSizeRatio(50); +joystick.setButtonSizeRatio(10); ``` -_The background size is not working for a custom picture._ - #### FixedCenter or Not? (and auto re-center) If you don’t set up this parameter, it will be FixedCenter by default, which is the regular behavior. @@ -116,48 +116,75 @@ joystick.setEnabled(false); // disabled the joystick joystick.isEnabled(); // return enabled state ``` -#### ButtonDirection +#### AxisMotion By default the button can move in both direction X,Y (regular behavior), but we can limit the movement through one axe horizontal or vertical. ```xml <... - custom:JV_buttonDirection="horizontal"/> + custom:JV_axisMotion="horizontal"/> ``` In the layout file (xml), this option can be set to `horizontal`, `vertical` or `both`. We can also set this option in the Java file by setting an integer value: -- any negative value (e.g. -1) for the horizontal axe -- any positive value (e.g. 1) for the vertical axe -- zero (0) for both (which is the default option) +- `BUTTON_DIRECTION_HORIZONTAL` for the horizontal axe +- `BUTTON_DIRECTION_VERTICAL` for the vertical axe +- `BUTTON_DIRECTION_BOTH` for both (which is the default option) ```java -joystick.setButtonDirection(1); // vertical +joystick.setAxisMotion(JoystickView.BUTTON_DIRECTION_VERTICAL); // vertical ``` -### Wearable -If you use this library in Wearable app, you will probably disable the Swipe-To-Dismiss Gesture and implement the Long Press to Dismiss Pattern, which could be a problem for a Joystick Pattern (because we usually let the user touch the joystick as long as she/he wants), in that case you can set another convenient listener: `OnMultipleLongPressListener` which will be invoked only with multiple pointers (at least two fingers) instead of one. +#### Position +The joystick is divided into eight positions + `none` + +![Alt text](/misc/virtual-joystick-positions.png?raw=true " stick positions") + ```java -joystick.setOnMultiLongPressListener(new JoystickView.OnMultipleLongPressListener() { - @Override - public void onMultipleLongPress() { - ... // eg. mDismissOverlay.show(); - } -}); +joystick.getPosition() == JoystickView.RIGHT_UP; +``` + +#### Deadzone +Most joysticks have an inner deadzone, else games would feel hypersensitive in their inputs. +By default, the deadzone is at 10% strength. +To change the deadzone, you can specify the following in xml. +```xml +<... + custom:JV_deadzone="10%"/> ``` + Or better, if you just want a simple Joystick (and few other cool stuff) as a controller for your mobile app you can use the following related project ;) ## Demo For those who want more than just a snippet, here is the demo : -- [Basic two joysticks ](https://github.com/controlwear/virtual-joystick-demo) (similar to screenshot) +- [Basic two joysticks ](https://github.com/lukkass222/virtual-joystick-android/tree/master/joystickdemo_2) - [similar to screenshot](#image). +- [Basic joystick ](https://github.com/lukkass222/virtual-joystick-android/tree/master/joystickdemo) - [similar to screenshot](#Rectangle). -If you want to add your project here, go ahead :) ## Required Minimum API level is 16 (Android 4.1.x - Jelly Bean) which cover 99.5% of the Android platforms as of October 2018 according to the distribution dashboard. ## Download ### Gradle -```java -compile 'io.github.controlwear:virtualjoystick:1.10.1' + +**Step 1.** Add the JitPack repository to your build file + +Add it in your root build.gradle at the end of repositories: + +```Gradle + dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + mavenCentral() + maven { url 'https://jitpack.io' } + } + } +``` + +**Step 2.** Add the dependency + +```Gradle +dependencies { + implementation 'com.github.lukkass222:virtual-joystick-android:1.13.5' + } ``` ## Contributing @@ -183,5 +210,27 @@ limitations under the License. **virtual-joystick-android** is an open source project created by @makowildcat (mostly spare time) and partially funded by [Black Artick](http://blackartick.com/) and [NSERC](http://www.nserc-crsng.gc.ca/index_eng.asp). -Also, thanks to Bernix01, teancake, Spettacolo83, djjaysmith, jaybkim1, sikrinick, AlexandrDavydov, indrek-koue, QitmentX7, esplemea, FenixGit, AlexanderShniperson +Also, thanks to Bernix01, +teancake, +Spettacolo83, +djjaysmith, +jaybkim1, +sikrinick, +AlexandrDavydov, +indrek-koue, +QitmentX7, +esplemea, +FenixGit, +AlexanderShniperson +, omarhemaia, +mstniy +Mathias-Boulay, +osfunapps, +eziosoft, +scottbarnesg, +tomerlevi444, +BenDelGreco, +dooully, +jonyhunter, +lukkass222 and GijsGoudzwaard for contributing. diff --git a/build.gradle b/build.gradle index 8bbeaab..dca942d 100644 --- a/build.gradle +++ b/build.gradle @@ -3,13 +3,10 @@ buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' - - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.0' - classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' + classpath 'com.android.tools.build:gradle:7.2.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -18,7 +15,7 @@ buildscript { allprojects { repositories { - jcenter() + mavenCentral() google() } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9f723b0..7a2999f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Nov 20 17:17:49 EST 2018 +#Sun May 14 19:31:20 CEST 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip diff --git a/gradlew b/gradlew index 9d82f78..cccdd3d 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -6,20 +6,38 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# 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 +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$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="" + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,26 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# 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 -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -85,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +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 @@ -150,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +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 -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index aec9973..e95643d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@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 DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@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= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,10 +46,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +59,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line diff --git a/joystickdemo/.gitignore b/joystickdemo/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/joystickdemo/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/joystickdemo/build.gradle b/joystickdemo/build.gradle new file mode 100644 index 0000000..164d086 --- /dev/null +++ b/joystickdemo/build.gradle @@ -0,0 +1,37 @@ +plugins { + id 'com.android.application' +} + +android { + namespace 'fr.spse.joystickdemo' + compileSdk 33 + + defaultConfig { + applicationId "fr.spse.joystickdemo" + minSdk 21 + targetSdk 33 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + implementation 'com.android.support.constraint:constraint-layout:2.0.4' + implementation project(':virtualjoystick') + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' +} \ No newline at end of file diff --git a/joystickdemo/proguard-rules.pro b/joystickdemo/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/joystickdemo/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/joystickdemo/src/androidTest/java/fr/spse/joystickdemo/ExampleInstrumentedTest.java b/joystickdemo/src/androidTest/java/fr/spse/joystickdemo/ExampleInstrumentedTest.java new file mode 100644 index 0000000..23cf7a4 --- /dev/null +++ b/joystickdemo/src/androidTest/java/fr/spse/joystickdemo/ExampleInstrumentedTest.java @@ -0,0 +1,25 @@ +package fr.spse.joystickdemo; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("fr.spse.joystickdemo", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/joystickdemo/src/main/AndroidManifest.xml b/joystickdemo/src/main/AndroidManifest.xml new file mode 100644 index 0000000..878f8a4 --- /dev/null +++ b/joystickdemo/src/main/AndroidManifest.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/joystickdemo/src/main/java/fr/spse/joystickdemo/MainActivity.java b/joystickdemo/src/main/java/fr/spse/joystickdemo/MainActivity.java new file mode 100644 index 0000000..a51a6d8 --- /dev/null +++ b/joystickdemo/src/main/java/fr/spse/joystickdemo/MainActivity.java @@ -0,0 +1,79 @@ +package fr.spse.joystickdemo; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.MotionEvent; +import android.widget.CheckBox; +import android.widget.Switch; +import android.widget.TextView; + +import io.github.controlwear.virtual.joystick.android.JoystickView; + +public class MainActivity extends AppCompatActivity { + @SuppressLint({"DefaultLocale","SetTextI18n"}) + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + JoystickView joystick = findViewById(R.id.joystick); + + CheckBox checkBoxH = findViewById(R.id.horizontal); + CheckBox checkBoxV = findViewById(R.id.vertical); + + checkBoxH.setOnCheckedChangeListener((compoundButton, b) -> { + checkBoxV.setChecked(false); + joystick.setAxisMotion(b ? JoystickView.AXIS_HORIZONTAL : 0); + }); + + checkBoxV.setOnCheckedChangeListener((compoundButton, b) -> { + checkBoxH.setChecked(false); + joystick.setAxisMotion(b ? JoystickView.AXIS_VERTICAL : 0); + }); + + joystick.setAxisMotion(JoystickView.AXIS_BOTH); + + + Switch Switch = findViewById(R.id.switch_use_Rectangle); + Switch.setOnCheckedChangeListener((buttonView, isChecked) -> joystick.setRectangle(isChecked) ); + joystick.setRectangle (Switch.isChecked()); + + Switch fixedCenterSwitch = findViewById(R.id.switch_fixed_center); + fixedCenterSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> joystick.setFixedCenter(isChecked)); + joystick.setFixedCenter(fixedCenterSwitch.isChecked()); + + Switch stickyBorderSwitch = findViewById(R.id.switch_sticky_border); + stickyBorderSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> joystick.setButtonStickToBorder(isChecked)); + joystick.setButtonStickToBorder(stickyBorderSwitch.isChecked()); + + Switch autoCenterSwitch = findViewById(R.id.switch_auto_center); + autoCenterSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> joystick.setAutoReCenterButton(isChecked)); + joystick.setAutoReCenterButton(autoCenterSwitch.isChecked()); + + TextView normalized = findViewById(R.id.normalized); + TextView del = findViewById(R.id.del); + TextView mStrength = findViewById(R.id.strength); + TextView mDirection = findViewById(R.id.stickDirection); + joystick.setOnMoveListener(new JoystickView.OnMoveListener() { + + @Override + public void onMove(int angle, int strength, MotionEvent event) { + mStrength.setText(strength + "%"); + mDirection.setText(joystick.getPosition() + ""); + int I =JoystickView.SCROLL_AXIS_HORIZONTAL; + normalized.setText( + String.format("norm "+"x%03d:y%03d", + joystick.getNormalizedX(), + joystick.getNormalizedY()) + ); + del.setText( + String.format("del "+"x%03d:y%03d", + joystick.getDelX(), + joystick.getDelY()) + ); + } + }); + + } +} \ No newline at end of file diff --git a/joystickdemo/src/main/res/drawable-v24/ic_launcher_foreground.xml b/joystickdemo/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/joystickdemo/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/joystickdemo/src/main/res/drawable/ic_launcher_background.xml b/joystickdemo/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/joystickdemo/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/joystickdemo/src/main/res/layout/activity_main.xml b/joystickdemo/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..d931982 --- /dev/null +++ b/joystickdemo/src/main/res/layout/activity_main.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/joystickdemo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/joystickdemo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/joystickdemo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/joystickdemo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/joystickdemo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/joystickdemo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/joystickdemo/src/main/res/mipmap-hdpi/ic_launcher.webp b/joystickdemo/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/joystickdemo/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/joystickdemo/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/joystickdemo/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d Binary files /dev/null and b/joystickdemo/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/joystickdemo/src/main/res/mipmap-mdpi/ic_launcher.webp b/joystickdemo/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/joystickdemo/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/joystickdemo/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/joystickdemo/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d Binary files /dev/null and b/joystickdemo/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/joystickdemo/src/main/res/mipmap-xhdpi/ic_launcher.webp b/joystickdemo/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/joystickdemo/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/joystickdemo/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/joystickdemo/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 Binary files /dev/null and b/joystickdemo/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/joystickdemo/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/joystickdemo/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/joystickdemo/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/joystickdemo/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/joystickdemo/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/joystickdemo/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/joystickdemo/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/joystickdemo/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/joystickdemo/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/joystickdemo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/joystickdemo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 Binary files /dev/null and b/joystickdemo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/joystickdemo/src/main/res/values-night/themes.xml b/joystickdemo/src/main/res/values-night/themes.xml new file mode 100644 index 0000000..50ec3fe --- /dev/null +++ b/joystickdemo/src/main/res/values-night/themes.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/joystickdemo/src/main/res/values/colors.xml b/joystickdemo/src/main/res/values/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/joystickdemo/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/joystickdemo/src/main/res/values/strings.xml b/joystickdemo/src/main/res/values/strings.xml new file mode 100644 index 0000000..5fc0f49 --- /dev/null +++ b/joystickdemo/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Demo application + \ No newline at end of file diff --git a/joystickdemo/src/main/res/values/themes.xml b/joystickdemo/src/main/res/values/themes.xml new file mode 100644 index 0000000..ba12ea5 --- /dev/null +++ b/joystickdemo/src/main/res/values/themes.xml @@ -0,0 +1,16 @@ + + + + + \ No newline at end of file diff --git a/joystickdemo/src/test/java/fr/spse/joystickdemo/ExampleUnitTest.java b/joystickdemo/src/test/java/fr/spse/joystickdemo/ExampleUnitTest.java new file mode 100644 index 0000000..824417f --- /dev/null +++ b/joystickdemo/src/test/java/fr/spse/joystickdemo/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package fr.spse.joystickdemo; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/joystickdemo_2/.gitignore b/joystickdemo_2/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/joystickdemo_2/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/joystickdemo_2/build.gradle b/joystickdemo_2/build.gradle new file mode 100644 index 0000000..70c1518 --- /dev/null +++ b/joystickdemo_2/build.gradle @@ -0,0 +1,38 @@ + +plugins { + id 'com.android.application' +} + +android { + namespace 'com.lukkass.rcble' + compileSdk 34 + + defaultConfig { + applicationId "com.lukkass.rcble" + minSdk 16 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + + + implementation project(':virtualjoystick') + implementation 'com.android.support:design:28.0.0' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'com.android.support.test:runner:1.0.2' +} \ No newline at end of file diff --git a/joystickdemo_2/proguard-rules.pro b/joystickdemo_2/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/joystickdemo_2/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/joystickdemo_2/src/androidTest/java/com/lukkass/rcble/ExampleInstrumentedTest.java b/joystickdemo_2/src/androidTest/java/com/lukkass/rcble/ExampleInstrumentedTest.java new file mode 100644 index 0000000..b07b660 --- /dev/null +++ b/joystickdemo_2/src/androidTest/java/com/lukkass/rcble/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.lukkass.rcble; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.lukkass.rcble", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/joystickdemo_2/src/main/AndroidManifest.xml b/joystickdemo_2/src/main/AndroidManifest.xml new file mode 100644 index 0000000..9a49d49 --- /dev/null +++ b/joystickdemo_2/src/main/AndroidManifest.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/joystickdemo_2/src/main/java/com/lukkass/rcble/MainActivity.java b/joystickdemo_2/src/main/java/com/lukkass/rcble/MainActivity.java new file mode 100644 index 0000000..959a6b7 --- /dev/null +++ b/joystickdemo_2/src/main/java/com/lukkass/rcble/MainActivity.java @@ -0,0 +1,53 @@ +package com.lukkass.rcble; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.widget.TextView; + +import io.github.controlwear.virtual.joystick.android.JoystickView; + + +public class MainActivity extends AppCompatActivity { + private TextView mTextViewAngleLeft; + private TextView mTextViewStrengthLeft; + + private TextView mTextViewAngleRight; + private TextView mTextViewStrengthRight; + private TextView mTextViewCoordinateRight; + + + @SuppressLint({"SetTextI18n", "DefaultLocale"}) + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.joystick_view_layout); + + mTextViewAngleLeft = findViewById(R.id.textView_angle_left); + mTextViewStrengthLeft = findViewById(R.id.textView_strength_left); + + JoystickView joystickLeft = findViewById(R.id.joystickView_left); + joystickLeft.setOnMoveListener((angle, strength, event) -> { + + mTextViewAngleLeft.setText(angle + "°"); + mTextViewStrengthLeft.setText(strength + "%"); + }); + + + mTextViewAngleRight = findViewById(R.id.textView_angle_right); + mTextViewStrengthRight = findViewById(R.id.textView_strength_right); + mTextViewCoordinateRight = findViewById(R.id.textView_coordinate_right); + + final JoystickView joystickRight = findViewById(R.id.joystickView_right); + joystickRight.setOnMoveListener((angle, strength, event) -> { + mTextViewAngleRight.setText(angle + "°"); + mTextViewStrengthRight.setText(strength + "%"); + mTextViewCoordinateRight.setText( + String.format("x%03d:y%03d", + joystickRight.getNormalizedX(), + joystickRight.getNormalizedY()) + ); + }); + } +} + diff --git a/joystickdemo_2/src/main/res/drawable-v24/ic_launcher_foreground.xml b/joystickdemo_2/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/joystickdemo_2/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/joystickdemo_2/src/main/res/drawable/ic_launcher_background.xml b/joystickdemo_2/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/joystickdemo_2/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/joystickdemo_2/src/main/res/drawable/pink_ball.xml b/joystickdemo_2/src/main/res/drawable/pink_ball.xml new file mode 100644 index 0000000..ca3826a --- /dev/null +++ b/joystickdemo_2/src/main/res/drawable/pink_ball.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/joystickdemo_2/src/main/res/layout/joystick_view_layout.xml b/joystickdemo_2/src/main/res/layout/joystick_view_layout.xml new file mode 100644 index 0000000..9c5a8c5 --- /dev/null +++ b/joystickdemo_2/src/main/res/layout/joystick_view_layout.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/joystickdemo_2/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/joystickdemo_2/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/joystickdemo_2/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/joystickdemo_2/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/joystickdemo_2/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/joystickdemo_2/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/joystickdemo_2/src/main/res/mipmap-anydpi-v26/joystick_background.xml b/joystickdemo_2/src/main/res/mipmap-anydpi-v26/joystick_background.xml new file mode 100644 index 0000000..11e604c --- /dev/null +++ b/joystickdemo_2/src/main/res/mipmap-anydpi-v26/joystick_background.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/joystickdemo_2/src/main/res/mipmap-anydpi-v26/joystick_background_round.xml b/joystickdemo_2/src/main/res/mipmap-anydpi-v26/joystick_background_round.xml new file mode 100644 index 0000000..11e604c --- /dev/null +++ b/joystickdemo_2/src/main/res/mipmap-anydpi-v26/joystick_background_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/joystickdemo_2/src/main/res/mipmap-anydpi-v26/pink_ball.xml b/joystickdemo_2/src/main/res/mipmap-anydpi-v26/pink_ball.xml new file mode 100644 index 0000000..ebf88da --- /dev/null +++ b/joystickdemo_2/src/main/res/mipmap-anydpi-v26/pink_ball.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/joystickdemo_2/src/main/res/mipmap-anydpi-v26/pink_ball_round.xml b/joystickdemo_2/src/main/res/mipmap-anydpi-v26/pink_ball_round.xml new file mode 100644 index 0000000..ebf88da --- /dev/null +++ b/joystickdemo_2/src/main/res/mipmap-anydpi-v26/pink_ball_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/joystickdemo_2/src/main/res/mipmap-hdpi/ic_launcher.webp b/joystickdemo_2/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/joystickdemo_2/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/joystickdemo_2/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/joystickdemo_2/src/main/res/mipmap-hdpi/joystick_background.png b/joystickdemo_2/src/main/res/mipmap-hdpi/joystick_background.png new file mode 100644 index 0000000..39e8387 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-hdpi/joystick_background.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-hdpi/joystick_background_foreground.png b/joystickdemo_2/src/main/res/mipmap-hdpi/joystick_background_foreground.png new file mode 100644 index 0000000..9f82527 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-hdpi/joystick_background_foreground.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-hdpi/joystick_background_round.png b/joystickdemo_2/src/main/res/mipmap-hdpi/joystick_background_round.png new file mode 100644 index 0000000..39e8387 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-hdpi/joystick_background_round.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-hdpi/pink_ball.png b/joystickdemo_2/src/main/res/mipmap-hdpi/pink_ball.png new file mode 100644 index 0000000..5fa19ab Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-hdpi/pink_ball.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-hdpi/pink_ball_foreground.png b/joystickdemo_2/src/main/res/mipmap-hdpi/pink_ball_foreground.png new file mode 100644 index 0000000..4f6d56e Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-hdpi/pink_ball_foreground.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-hdpi/pink_ball_round.png b/joystickdemo_2/src/main/res/mipmap-hdpi/pink_ball_round.png new file mode 100644 index 0000000..5fa19ab Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-hdpi/pink_ball_round.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-mdpi/ic_launcher.webp b/joystickdemo_2/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/joystickdemo_2/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/joystickdemo_2/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/joystickdemo_2/src/main/res/mipmap-mdpi/joystick_background.png b/joystickdemo_2/src/main/res/mipmap-mdpi/joystick_background.png new file mode 100644 index 0000000..6b514fe Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-mdpi/joystick_background.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-mdpi/joystick_background_foreground.png b/joystickdemo_2/src/main/res/mipmap-mdpi/joystick_background_foreground.png new file mode 100644 index 0000000..d96b60d Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-mdpi/joystick_background_foreground.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-mdpi/joystick_background_round.png b/joystickdemo_2/src/main/res/mipmap-mdpi/joystick_background_round.png new file mode 100644 index 0000000..6b514fe Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-mdpi/joystick_background_round.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-mdpi/pink_ball.png b/joystickdemo_2/src/main/res/mipmap-mdpi/pink_ball.png new file mode 100644 index 0000000..40d66bf Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-mdpi/pink_ball.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-mdpi/pink_ball_foreground.png b/joystickdemo_2/src/main/res/mipmap-mdpi/pink_ball_foreground.png new file mode 100644 index 0000000..59dca38 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-mdpi/pink_ball_foreground.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-mdpi/pink_ball_round.png b/joystickdemo_2/src/main/res/mipmap-mdpi/pink_ball_round.png new file mode 100644 index 0000000..40d66bf Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-mdpi/pink_ball_round.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xhdpi/ic_launcher.webp b/joystickdemo_2/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/joystickdemo_2/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/joystickdemo_2/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/joystickdemo_2/src/main/res/mipmap-xhdpi/joystick_background.png b/joystickdemo_2/src/main/res/mipmap-xhdpi/joystick_background.png new file mode 100644 index 0000000..f9fe07b Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xhdpi/joystick_background.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xhdpi/joystick_background_foreground.png b/joystickdemo_2/src/main/res/mipmap-xhdpi/joystick_background_foreground.png new file mode 100644 index 0000000..629de57 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xhdpi/joystick_background_foreground.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xhdpi/joystick_background_round.png b/joystickdemo_2/src/main/res/mipmap-xhdpi/joystick_background_round.png new file mode 100644 index 0000000..f9fe07b Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xhdpi/joystick_background_round.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xhdpi/pink_ball.png b/joystickdemo_2/src/main/res/mipmap-xhdpi/pink_ball.png new file mode 100644 index 0000000..fc434c7 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xhdpi/pink_ball.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xhdpi/pink_ball_foreground.png b/joystickdemo_2/src/main/res/mipmap-xhdpi/pink_ball_foreground.png new file mode 100644 index 0000000..7967973 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xhdpi/pink_ball_foreground.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xhdpi/pink_ball_round.png b/joystickdemo_2/src/main/res/mipmap-xhdpi/pink_ball_round.png new file mode 100644 index 0000000..fc434c7 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xhdpi/pink_ball_round.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/joystickdemo_2/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/joystickdemo_2/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/joystickdemo_2/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/joystickdemo_2/src/main/res/mipmap-xxhdpi/joystick_background.png b/joystickdemo_2/src/main/res/mipmap-xxhdpi/joystick_background.png new file mode 100644 index 0000000..652153f Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xxhdpi/joystick_background.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xxhdpi/joystick_background_foreground.png b/joystickdemo_2/src/main/res/mipmap-xxhdpi/joystick_background_foreground.png new file mode 100644 index 0000000..b774118 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xxhdpi/joystick_background_foreground.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xxhdpi/joystick_background_round.png b/joystickdemo_2/src/main/res/mipmap-xxhdpi/joystick_background_round.png new file mode 100644 index 0000000..652153f Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xxhdpi/joystick_background_round.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xxhdpi/pink_ball.png b/joystickdemo_2/src/main/res/mipmap-xxhdpi/pink_ball.png new file mode 100644 index 0000000..169c452 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xxhdpi/pink_ball.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xxhdpi/pink_ball_foreground.png b/joystickdemo_2/src/main/res/mipmap-xxhdpi/pink_ball_foreground.png new file mode 100644 index 0000000..ad9934d Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xxhdpi/pink_ball_foreground.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xxhdpi/pink_ball_round.png b/joystickdemo_2/src/main/res/mipmap-xxhdpi/pink_ball_round.png new file mode 100644 index 0000000..169c452 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xxhdpi/pink_ball_round.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/joystickdemo_2/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/joystickdemo_2/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/joystickdemo_2/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/joystickdemo_2/src/main/res/mipmap-xxxhdpi/joystick_background.png b/joystickdemo_2/src/main/res/mipmap-xxxhdpi/joystick_background.png new file mode 100644 index 0000000..1a0ae64 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xxxhdpi/joystick_background.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xxxhdpi/joystick_background_foreground.png b/joystickdemo_2/src/main/res/mipmap-xxxhdpi/joystick_background_foreground.png new file mode 100644 index 0000000..11533e3 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xxxhdpi/joystick_background_foreground.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xxxhdpi/joystick_background_round.png b/joystickdemo_2/src/main/res/mipmap-xxxhdpi/joystick_background_round.png new file mode 100644 index 0000000..1a0ae64 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xxxhdpi/joystick_background_round.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xxxhdpi/pink_ball.png b/joystickdemo_2/src/main/res/mipmap-xxxhdpi/pink_ball.png new file mode 100644 index 0000000..2ede697 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xxxhdpi/pink_ball.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xxxhdpi/pink_ball_foreground.png b/joystickdemo_2/src/main/res/mipmap-xxxhdpi/pink_ball_foreground.png new file mode 100644 index 0000000..048fd66 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xxxhdpi/pink_ball_foreground.png differ diff --git a/joystickdemo_2/src/main/res/mipmap-xxxhdpi/pink_ball_round.png b/joystickdemo_2/src/main/res/mipmap-xxxhdpi/pink_ball_round.png new file mode 100644 index 0000000..2ede697 Binary files /dev/null and b/joystickdemo_2/src/main/res/mipmap-xxxhdpi/pink_ball_round.png differ diff --git a/joystickdemo_2/src/main/res/raw/joystick_background.png b/joystickdemo_2/src/main/res/raw/joystick_background.png new file mode 100644 index 0000000..037ac77 Binary files /dev/null and b/joystickdemo_2/src/main/res/raw/joystick_background.png differ diff --git a/joystickdemo_2/src/main/res/raw/pink_ball.png b/joystickdemo_2/src/main/res/raw/pink_ball.png new file mode 100644 index 0000000..42bcc84 Binary files /dev/null and b/joystickdemo_2/src/main/res/raw/pink_ball.png differ diff --git a/joystickdemo_2/src/main/res/values-night/themes.xml b/joystickdemo_2/src/main/res/values-night/themes.xml new file mode 100644 index 0000000..37cb716 --- /dev/null +++ b/joystickdemo_2/src/main/res/values-night/themes.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/joystickdemo_2/src/main/res/values/colors.xml b/joystickdemo_2/src/main/res/values/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/joystickdemo_2/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/joystickdemo_2/src/main/res/values/joystick_background_background.xml b/joystickdemo_2/src/main/res/values/joystick_background_background.xml new file mode 100644 index 0000000..4422052 --- /dev/null +++ b/joystickdemo_2/src/main/res/values/joystick_background_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file diff --git a/joystickdemo_2/src/main/res/values/pink_ball_background.xml b/joystickdemo_2/src/main/res/values/pink_ball_background.xml new file mode 100644 index 0000000..f86f412 --- /dev/null +++ b/joystickdemo_2/src/main/res/values/pink_ball_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file diff --git a/joystickdemo_2/src/main/res/values/strings.xml b/joystickdemo_2/src/main/res/values/strings.xml new file mode 100644 index 0000000..1f4c9d9 --- /dev/null +++ b/joystickdemo_2/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + demo + \ No newline at end of file diff --git a/joystickdemo_2/src/main/res/values/themes.xml b/joystickdemo_2/src/main/res/values/themes.xml new file mode 100644 index 0000000..ea9ef45 --- /dev/null +++ b/joystickdemo_2/src/main/res/values/themes.xml @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/joystickdemo_2/src/test/java/com/lukkass/rcble/ExampleUnitTest.java b/joystickdemo_2/src/test/java/com/lukkass/rcble/ExampleUnitTest.java new file mode 100644 index 0000000..9260abf --- /dev/null +++ b/joystickdemo_2/src/test/java/com/lukkass/rcble/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.lukkass.rcble; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/misc/virtual-joystick-android-rectangle.png b/misc/virtual-joystick-android-rectangle.png new file mode 100644 index 0000000..a4b584a Binary files /dev/null and b/misc/virtual-joystick-android-rectangle.png differ diff --git a/misc/virtual-joystick-positions.png b/misc/virtual-joystick-positions.png new file mode 100644 index 0000000..b8a3d64 Binary files /dev/null and b/misc/virtual-joystick-positions.png differ diff --git a/settings.gradle b/settings.gradle index 0175e54..1db903c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,3 @@ include ':virtualjoystick' +include ':joystickdemo' +include ':joystickdemo_2' diff --git a/virtualjoystick/build.gradle b/virtualjoystick/build.gradle index 393b443..ea72c8f 100644 --- a/virtualjoystick/build.gradle +++ b/virtualjoystick/build.gradle @@ -1,47 +1,48 @@ -apply plugin: 'com.android.library' +plugins{ + id 'com.android.library' + id 'maven-publish' +} android { - compileSdkVersion 28 + namespace 'io.github.controlwear.virtual.joystick.android' + compileSdk 34 defaultConfig { minSdkVersion 16 - targetSdkVersion 28 - versionCode 20 - versionName "1.10.1" + versionCode 22 + versionName "1.13.5" } + buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - testImplementation 'junit:junit:4.12' + implementation 'com.android.support:support-annotations:28.0.0' + testImplementation 'junit:junit:4.13.2' } -ext { - // Where you will see your artifact in Bintray's web interface - // The "bintrayName" should match the name of the Bintray repro. - bintrayRepo = 'maven' - bintrayName = 'virtual-joystick-android' - - // Maven metadata - publishedGroupId = 'io.github.controlwear' - libraryName = 'virtual-joystick-android' - // Save yourself a head ache, and set this equal to the name of the Android Studio library - // module. The artifact name needs to match the name of the library. - artifact = 'virtualjoystick' - - libraryDescription = 'This library provides a very simple and ready-to-use custom view which emulates a joystick for Android.' - libraryVersion = '1.10.1' - - developerId = 'makowildcat' - developerName = 'Damien Brun' - developerEmail = 'makowildcat@gmail.com' -} - -apply from: 'https://raw.githubusercontent.com/attwellbrian/JCenter/master/installv1.gradle' -apply from: 'https://raw.githubusercontent.com/attwellbrian/JCenter/master/bintrayv1.gradle' +afterEvaluate { + publishing { + publications { + // Creates a Maven publication called "release". + release(MavenPublication) { + // Applies the component for the release build variant. + from components.release + // You can then customize attributes of the publication as shown below. + groupId = 'com.github.lukkass222' + artifactId = 'virtual-joystick-android' + version = '1.13.5' + } + } + } +} \ No newline at end of file diff --git a/virtualjoystick/src/main/AndroidManifest.xml b/virtualjoystick/src/main/AndroidManifest.xml index a80144e..e100076 100644 --- a/virtualjoystick/src/main/AndroidManifest.xml +++ b/virtualjoystick/src/main/AndroidManifest.xml @@ -1,5 +1,4 @@ - + diff --git a/virtualjoystick/src/main/java/io/github/controlwear/virtual/joystick/android/JoystickView.java b/virtualjoystick/src/main/java/io/github/controlwear/virtual/joystick/android/JoystickView.java index bcf400d..23185b3 100644 --- a/virtualjoystick/src/main/java/io/github/controlwear/virtual/joystick/android/JoystickView.java +++ b/virtualjoystick/src/main/java/io/github/controlwear/virtual/joystick/android/JoystickView.java @@ -1,30 +1,24 @@ package io.github.controlwear.virtual.joystick.android; - import android.content.Context; import android.content.res.TypedArray; -import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; -import android.os.Handler; +import android.support.annotation.NonNull; import android.util.AttributeSet; +import android.util.Log; import android.view.MotionEvent; import android.view.View; -import android.view.ViewConfiguration; -public class JoystickView extends View - implements - Runnable { +public class JoystickView extends View { /* INTERFACES */ - /** * Interface definition for a callback to be invoked when a * JoystickView's button is moved @@ -36,128 +30,82 @@ public interface OnMoveListener { * @param angle current angle * @param strength current strength */ - void onMove(int angle, int strength); - } - - - /** - * Interface definition for a callback to be invoked when a JoystickView - * is touched and held by multiple pointers. - */ - public interface OnMultipleLongPressListener { - /** - * Called when a JoystickView has been touch and held enough time by multiple pointers. - */ - void onMultipleLongPress(); + void onMove(int angle, int strength, MotionEvent event); } /* CONSTANTS */ - - /** - * Default refresh rate as a time in milliseconds to send move values through callback - */ - private static final int DEFAULT_LOOP_INTERVAL = 50; // in milliseconds - + public static final int AXIS_VERTICAL = 1; + /** Default value for both directions (horizontal and vertical movement) */ + public static final int AXIS_BOTH = 0; + public static final int AXIS_HORIZONTAL = -1; /** * Used to allow a slight move without cancelling MultipleLongPress */ - private static final int MOVE_TOLERANCE = 10; + private static final int DEFAULT_DEADZONE = 1; - /** - * Default color for button - */ + /** Default color for button */ private static final int DEFAULT_COLOR_BUTTON = Color.BLACK; - /** - * Default color for border - */ + /** Default color for border */ private static final int DEFAULT_COLOR_BORDER = Color.TRANSPARENT; - /** - * Default alpha for border - */ + /** Default alpha for border */ private static final int DEFAULT_ALPHA_BORDER = 255; - /** - * Default background color - */ + /** Default background color */ private static final int DEFAULT_BACKGROUND_COLOR = Color.TRANSPARENT; - /** - * Default View's size - */ + /** Default View's size */ private static final int DEFAULT_SIZE = 200; - /** - * Default border's width - */ + /** Default border's width */ private static final int DEFAULT_WIDTH_BORDER = 3; - /** - * Default behavior to fixed center (not auto-defined) - */ + /** Default behavior to fixed center (not auto-defined) */ private static final boolean DEFAULT_FIXED_CENTER = true; - - /** - * Default behavior to auto re-center button (automatically recenter the button) - */ + /** Default behavior to auto re-center button (automatically recenter the button) */ private static final boolean DEFAULT_AUTO_RECENTER_BUTTON = true; - - /** - * Default behavior to button stickToBorder (button stay on the border) - */ + /** Default behavior to button stickToBorder (button stay on the border) */ private static final boolean DEFAULT_BUTTON_STICK_TO_BORDER = false; - // DRAWING - private Paint mPaintCircleButton; - private Paint mPaintCircleBorder; - private Paint mPaintBackground; - - private Paint mPaintBitmapButton; - private Bitmap mButtonBitmap; + private final Paint mPaintCircleButton; + private final Paint mPaintBorder; + private final Paint mPaintBackground; + private Drawable mButtonDrawable; - /** - * Ratio use to define the size of the button - */ + /** Ratio use to define the size of the button */ private float mButtonSizeRatio; - - /** - * Ratio use to define the size of the background - * - */ + /** Ratio use to define the size of the background */ private float mBackgroundSizeRatio; - // COORDINATE - private int mPosX = 0; - private int mPosY = 0; - private int mCenterX = 0; - private int mCenterY = 0; + private float mLastPosX = 0; + private float mLastPosY = 0; + private float mPosX = 0; + private float mPosY = 0; + private float mCenterX = 0; + private float mCenterY = 0; - private int mFixedCenterX = 0; - private int mFixedCenterY = 0; + private float mFixedCenterX = 0; + private float mFixedCenterY = 0; - /** - * Used to adapt behavior whether it is auto-defined center (false) or fixed center (true) - */ + /** Used to adapt behavior whether it is auto-defined center (false) or fixed center (true) */ private boolean mFixedCenter; - /** * Used to adapt behavior whether the button is automatically re-centered (true) * when released or not (false) */ private boolean mAutoReCenterButton; - /** * Used to adapt behavior whether the button is stick to border (true) or * could be anywhere (when false - similar to regular behavior) @@ -171,48 +119,33 @@ public interface OnMultipleLongPressListener { */ private boolean mEnabled; - // SIZE private int mButtonRadius; - private int mBorderRadius; + private float mBorderRadius; + private float mBorderWidth; + private float mBorderHeight; - /** - * Alpha of the border (to use when changing color dynamically) - */ + /** Alpha of the border (to use when changing color dynamically) */ private int mBorderAlpha; - - /** - * Based on mBorderRadius but a bit smaller (minus half the stroke size of the border) - */ + /** Based on mBorderRadius but a bit smaller (minus half the stroke size of the border) */ private float mBackgroundRadius; + /**Based on mBorderWidth/Height but a bit smaller (minus half the stroke size of the border) */ + private float mBackgroundWidth, mBackgroundHeight; - /** - * Listener used to dispatch OnMove event - */ - private OnMoveListener mCallback; - - private long mLoopInterval = DEFAULT_LOOP_INTERVAL; - private Thread mThread = new Thread(this); + private boolean isRectangle; + /** Listener used to dispatch OnMove event */ + private OnMoveListener mCallback; - /** - * Listener used to dispatch MultipleLongPress event - */ - private OnMultipleLongPressListener mOnMultipleLongPressListener; - - private final Handler mHandlerMultipleLongPress = new Handler(); - private Runnable mRunnableMultipleLongPress; - private int mMoveTolerance; + /** PointerID used to track the original pointer triggering the joystick */ + private int pointerID = -1; + /** The deadzone for the joystick from 0 to 100%*/ + private float mDeadzone; - /** - * Default value. - * Both direction correspond to horizontal and vertical movement - */ - public static int BUTTON_DIRECTION_BOTH = 0; /** * The allowed direction of the button is define by the value of this parameter: @@ -220,14 +153,21 @@ public interface OnMultipleLongPressListener { * - a positive value for vertical axe * - zero for both axes */ - private int mButtonDirection = 0; + private int mAxisMotionType; + + /* + * Detect if joystick has been pressed, even if strength and angle are 0 + */ + private boolean isPressed = false; + + /** axis to be centered */ + private int mAxisToCenter; /* CONSTRUCTORS */ - /** * Simple constructor to use when creating a JoystickView from code. * Call another constructor passing null to Attribute. @@ -239,11 +179,15 @@ public JoystickView(Context context) { } - public JoystickView(Context context, AttributeSet attrs, int defStyleAttr) { - this(context, attrs); + public JoystickView(Context context, AttributeSet attrs) { + this(context, attrs, 0); } + public JoystickView(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + /** * Constructor that is called when inflating a JoystickView from XML. This is called * when a JoystickView is being constructed from an XML file, supplying attributes @@ -252,20 +196,19 @@ public JoystickView(Context context, AttributeSet attrs, int defStyleAttr) { * access the current theme, resources, etc. * @param attrs The attributes of the XML tag that is inflating the JoystickView. */ - public JoystickView(Context context, AttributeSet attrs) { - super(context, attrs); + public JoystickView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr); TypedArray styledAttributes = context.getTheme().obtainStyledAttributes( attrs, R.styleable.JoystickView, - 0, 0 + defStyleAttr, defStyleRes ); int buttonColor; int borderColor; int backgroundColor; int borderWidth; - Drawable buttonDrawable; try { buttonColor = styledAttributes.getColor(R.styleable.JoystickView_JV_buttonColor, DEFAULT_COLOR_BUTTON); borderColor = styledAttributes.getColor(R.styleable.JoystickView_JV_borderColor, DEFAULT_COLOR_BORDER); @@ -275,84 +218,94 @@ public JoystickView(Context context, AttributeSet attrs) { mFixedCenter = styledAttributes.getBoolean(R.styleable.JoystickView_JV_fixedCenter, DEFAULT_FIXED_CENTER); mAutoReCenterButton = styledAttributes.getBoolean(R.styleable.JoystickView_JV_autoReCenterButton, DEFAULT_AUTO_RECENTER_BUTTON); mButtonStickToBorder = styledAttributes.getBoolean(R.styleable.JoystickView_JV_buttonStickToBorder, DEFAULT_BUTTON_STICK_TO_BORDER); - buttonDrawable = styledAttributes.getDrawable(R.styleable.JoystickView_JV_buttonImage); + mButtonDrawable = styledAttributes.getDrawable(R.styleable.JoystickView_JV_buttonImage); + mDeadzone = styledAttributes.getFraction(R.styleable.JoystickView_JV_deadzone, 10, 10, DEFAULT_DEADZONE); mEnabled = styledAttributes.getBoolean(R.styleable.JoystickView_JV_enabled, true); mButtonSizeRatio = styledAttributes.getFraction(R.styleable.JoystickView_JV_buttonSizeRatio, 1, 1, 0.25f); mBackgroundSizeRatio = styledAttributes.getFraction(R.styleable.JoystickView_JV_backgroundSizeRatio, 1, 1, 0.75f); - mButtonDirection = styledAttributes.getInteger(R.styleable.JoystickView_JV_buttonDirection, BUTTON_DIRECTION_BOTH); + mAxisMotionType = styledAttributes.getInteger(R.styleable.JoystickView_JV_axisMotion, AXIS_BOTH); + mAxisToCenter = styledAttributes.getInteger(R.styleable.JoystickView_JV_axisToCenter, AXIS_BOTH); + isRectangle = styledAttributes.getBoolean(R.styleable.JoystickView_JV_useRectangle, false); + } finally { styledAttributes.recycle(); } // Initialize the drawing according to attributes - + + + // mDeadzone = Math.round(_deadzone); mPaintCircleButton = new Paint(); mPaintCircleButton.setAntiAlias(true); mPaintCircleButton.setColor(buttonColor); mPaintCircleButton.setStyle(Paint.Style.FILL); - if (buttonDrawable != null) { - if (buttonDrawable instanceof BitmapDrawable) { - mButtonBitmap = ((BitmapDrawable) buttonDrawable).getBitmap(); - mPaintBitmapButton = new Paint(); - } - } - - mPaintCircleBorder = new Paint(); - mPaintCircleBorder.setAntiAlias(true); - mPaintCircleBorder.setColor(borderColor); - mPaintCircleBorder.setStyle(Paint.Style.STROKE); - mPaintCircleBorder.setStrokeWidth(borderWidth); + mPaintBorder = new Paint(); + mPaintBorder.setAntiAlias(true); + mPaintBorder.setColor(borderColor); + mPaintBorder.setStyle(Paint.Style.STROKE); + mPaintBorder.setStrokeWidth(borderWidth); if (borderColor != Color.TRANSPARENT) { - mPaintCircleBorder.setAlpha(mBorderAlpha); + mPaintBorder.setAlpha(mBorderAlpha); } mPaintBackground = new Paint(); mPaintBackground.setAntiAlias(true); mPaintBackground.setColor(backgroundColor); mPaintBackground.setStyle(Paint.Style.FILL); - - - // Init Runnable for MultiLongPress - - mRunnableMultipleLongPress = new Runnable() { - @Override - public void run() { - if (mOnMultipleLongPressListener != null) - mOnMultipleLongPressListener.onMultipleLongPress(); - } - }; } - private void initPosition() { // get the center of view to position circle - mFixedCenterX = mCenterX = mPosX = getWidth() / 2; - mFixedCenterY = mCenterY = mPosY = getWidth() / 2; + mFixedCenterX = mCenterX = mPosX = getWidth() / 2f; + mFixedCenterY = mCenterY = mPosY = getHeight() / 2f; } - + public boolean isVisible() { + return getVisibility() == VISIBLE; + } + /** * Draw the background, the border and the button * @param canvas the canvas on which the shapes will be drawn */ @Override - protected void onDraw(Canvas canvas) { - // Draw the background - canvas.drawCircle(mFixedCenterX, mFixedCenterY, mBackgroundRadius, mPaintBackground); - - // Draw the circle border - canvas.drawCircle(mFixedCenterX, mFixedCenterY, mBorderRadius, mPaintCircleBorder); + protected void onDraw(@NonNull Canvas canvas) { + if (isRectangle) { + // Draw the rectangle background + canvas.drawRect( + mFixedCenterX - mBackgroundWidth / 2f, + mFixedCenterY - mBackgroundHeight / 2f, + mFixedCenterX + mBackgroundWidth / 2f, + mFixedCenterY + mBackgroundHeight / 2f, + mPaintBackground); + + // Draw the rectangle border + canvas.drawRect( + mFixedCenterX - mBorderWidth / 2f, + mFixedCenterY - mBorderHeight / 2f, + mFixedCenterX + mBorderWidth / 2f, + mFixedCenterY + mBorderHeight / 2f, + mPaintBorder); + } else { + // Draw the background + canvas.drawCircle(mFixedCenterX, mFixedCenterY, mBackgroundRadius, mPaintBackground); + // Draw the circle border + canvas.drawCircle(mFixedCenterX, mFixedCenterY, mBorderRadius, mPaintBorder); + } + /* + canvas.drawLine(mCenterX, mCenterY, mCenterX+mBorderWidth/2f, mCenterY+mBorderHeight /2f, mPaintBorder);//raio + canvas.drawLine(mFixedCenterX, mFixedCenterY, mFixedCenterX+mBorderWidth/2f, mFixedCenterY, mPaintBorder); + canvas.drawLine(mCenterX, mCenterY, mPosX,mPosY,mPaintBorder); + */ // Draw the button from image - if (mButtonBitmap != null) { - canvas.drawBitmap( - mButtonBitmap, - mPosX + mFixedCenterX - mCenterX - mButtonRadius, - mPosY + mFixedCenterY - mCenterY - mButtonRadius, - mPaintBitmapButton - ); + if (mButtonDrawable != null) { + int x = Math.round(mPosX + mFixedCenterX - mCenterX - mButtonRadius); + int y = Math.round(mPosY + mFixedCenterY - mCenterY - mButtonRadius); + mButtonDrawable.setBounds(x, y, x + mButtonRadius * 2, y + mButtonRadius * 2); + mButtonDrawable.draw(canvas); } // Draw the button as simple circle else { @@ -364,8 +317,7 @@ protected void onDraw(Canvas canvas) { ); } } - - + /** * This is called during layout when the size of this view has changed. * Here we get the center of the view and the radius to draw all the shapes. @@ -384,19 +336,19 @@ protected void onSizeChanged(int w, int h, int oldW, int oldH) { // radius based on smallest size : height OR width int d = Math.min(w, h); mButtonRadius = (int) (d / 2 * mButtonSizeRatio); - mBorderRadius = (int) (d / 2 * mBackgroundSizeRatio); - mBackgroundRadius = mBorderRadius - (mPaintCircleBorder.getStrokeWidth() / 2); + mBorderRadius = (d / 2f * mBackgroundSizeRatio); + mBackgroundRadius = mBorderRadius - (mPaintBorder.getStrokeWidth() / 2); - if (mButtonBitmap != null) - mButtonBitmap = Bitmap.createScaledBitmap(mButtonBitmap, mButtonRadius * 2, mButtonRadius * 2, true); + mBorderWidth = (mAxisMotionType > AXIS_BOTH ? d * mButtonSizeRatio : w * mBackgroundSizeRatio);// if vertical + mBorderHeight = (mAxisMotionType < AXIS_BOTH ? d * mButtonSizeRatio : h * mBackgroundSizeRatio);// if horizontal + mBackgroundWidth = mBorderWidth - mPaintBorder.getStrokeWidth() / 2; + mBackgroundHeight = mBorderHeight - mPaintBorder.getStrokeWidth() / 2; } - @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // setting the measured values to resize the view to a certain width and height - int d = Math.min(measure(widthMeasureSpec), measure(heightMeasureSpec)); - setMeasuredDimension(d, d); + setMeasuredDimension(measure(widthMeasureSpec), measure(heightMeasureSpec)); } @@ -416,6 +368,10 @@ private int measure(int measureSpec) { USER EVENT */ + @Override + public boolean performClick() { + return super.performClick(); + } /** * Handle touch screen motion event. Move the button according to the @@ -426,98 +382,111 @@ private int measure(int measureSpec) { */ @Override public boolean onTouchEvent(MotionEvent event) { - // if disabled we don't move the - if (!mEnabled) { - return true; - } + super.onTouchEvent(event); + performClick(); + // if disabled we don't move the joystick + if (!mEnabled) return false; + boolean isHorizontal = mAxisMotionType < AXIS_BOTH; + boolean isVertical = mAxisMotionType > AXIS_BOTH; // to move the button according to the finger coordinate // (or limited to one axe according to direction option - mPosY = mButtonDirection < 0 ? mCenterY : (int) event.getY(); // direction negative is horizontal axe - mPosX = mButtonDirection > 0 ? mCenterX : (int) event.getX(); // direction positive is vertical axe + int pointerIndex; + if ((pointerIndex = event.findPointerIndex(pointerID)) != -1) { + mPosY = isHorizontal ? mCenterY : event.getY(pointerIndex); // if horizontal + mPosX = isVertical ? mCenterX : event.getX(pointerIndex); // if vertical + } - if (event.getAction() == MotionEvent.ACTION_UP) { + if (event.getAction() == MotionEvent.ACTION_POINTER_UP) { + if (event.findPointerIndex(pointerID) == event.getActionIndex()) + event.setAction(MotionEvent.ACTION_UP); + } - // stop listener because the finger left the touch screen - mThread.interrupt(); + if (event.getAction() == MotionEvent.ACTION_POINTER_DOWN) { + if (pointerID == -1) event.setAction(MotionEvent.ACTION_DOWN); + } + + // up + if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { + isPressed = false; + // Reset the pointerID; + pointerID = -1; // re-center the button or not (depending on settings) if (mAutoReCenterButton) { resetButtonPosition(); - - // update now the last strength and angle which should be zero after resetButton - if (mCallback != null) - mCallback.onMove(getAngle(), getStrength()); } // if mAutoReCenterButton is false we will send the last strength and angle a bit - // later only after processing new position X and Y otherwise it could be above the border limit + // later only after processing new position HORIZONTAL and VERTICAL otherwise it could be above the border limit } + // down if (event.getAction() == MotionEvent.ACTION_DOWN) { - if (mThread != null && mThread.isAlive()) { - mThread.interrupt(); - } - - mThread = new Thread(this); - mThread.start(); - - if (mCallback != null) - mCallback.onMove(getAngle(), getStrength()); + // Check if the pointer is inside the original joystick zone + if (isRectangle) { + if (Math.abs(mFixedCenterX - event.getX()) > mBackgroundWidth / 2f + mPaintBorder.getStrokeWidth()) + return false; // outside of the round joystick + if (Math.abs(mFixedCenterY - event.getY()) > mBackgroundHeight / 2f + mPaintBorder.getStrokeWidth()) + return false; // outside of the round joystick + } else if (Math.hypot(Math.abs(mFixedCenterX - event.getX()), Math.abs(mFixedCenterY - event.getY())) > mBackgroundRadius + mPaintBorder.getStrokeWidth()) + return false; // outside of the round joystick + + isPressed = true; + // Map the pointerID + pointerID = event.getPointerId(event.getActionIndex()); + + mPosY = isHorizontal ? mCenterY : event.getY(); // if horizontal + mPosX = isVertical ? mCenterX : event.getX(); // if vertical } - // handle first touch and long press with multiple touch only - switch (event.getActionMasked()) { - case MotionEvent.ACTION_DOWN: - // when the first touch occurs we update the center (if set to auto-defined center) - if (!mFixedCenter) { - mCenterX = mPosX; - mCenterY = mPosY; - } - break; - - case MotionEvent.ACTION_POINTER_DOWN: { - // when the second finger touch - if (event.getPointerCount() == 2) { - mHandlerMultipleLongPress.postDelayed(mRunnableMultipleLongPress, ViewConfiguration.getLongPressTimeout()*2); - mMoveTolerance = MOVE_TOLERANCE; - } - break; + if (Math.abs(mLastPosX - mPosX) < mDeadzone) + if (Math.abs(mLastPosY - mPosY) < mDeadzone) { + return false; } - case MotionEvent.ACTION_MOVE: - mMoveTolerance--; - if (mMoveTolerance == 0) { - mHandlerMultipleLongPress.removeCallbacks(mRunnableMultipleLongPress); - } - break; - - case MotionEvent.ACTION_POINTER_UP: { - // when the last multiple touch is released - if (event.getPointerCount() == 2) { - mHandlerMultipleLongPress.removeCallbacks(mRunnableMultipleLongPress); - } - break; + mLastPosX = mPosX; + mLastPosY = mPosY; + + // handle first touch and long press with multiple touch only + // when the first touch occurs we update the center (if set to auto-defined center) + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + if (!mFixedCenter) { + mCenterX = mPosX; + mCenterY = mPosY; } } - double abs = Math.sqrt((mPosX - mCenterX) * (mPosX - mCenterX) - + (mPosY - mCenterY) * (mPosY - mCenterY)); - - // (abs > mBorderRadius) means button is too far therefore we limit to border - // (buttonStickBorder && abs != 0) means wherever is the button we stick it to the border except when abs == 0 - if (abs > mBorderRadius || (mButtonStickToBorder && abs != 0)) { - mPosX = (int) ((mPosX - mCenterX) * mBorderRadius / abs + mCenterX); - mPosY = (int) ((mPosY - mCenterY) * mBorderRadius / abs + mCenterY); + double _maxRadius = mBorderRadius; + float xPos = mPosX - mCenterX; + float yPos = mPosY - mCenterY; + + if (isRectangle) { + float Xb = mBorderWidth / 2f; + float Yb = mBorderHeight / 2f; + + float _X = Math.abs(xPos); + float _Y = Math.abs(yPos); + + //regra de três simples + float Yc = (_Y * Xb) / _X; + float Xc = (_X * Yb) / _Y; + + _maxRadius = Math.hypot(Math.min(Xb, Xc), Math.min(Yb, Yc)); } - - if (!mAutoReCenterButton) { - // Now update the last strength and angle if not reset to center - if (mCallback != null) - mCallback.onMove(getAngle(), getStrength()); + + double _radius = Math.hypot(xPos, yPos); + + // (_radius > mBorderRadius) means button is too far therefore we limit to border + // (buttonStickBorder && _radius != 0) means wherever is the button we stick it to the border except when _radius == 0 + if (_radius > _maxRadius || (mButtonStickToBorder && _radius != 0)) { + mPosX = (float) (xPos * _maxRadius / _radius + mCenterX); + mPosY = (float) (yPos * _maxRadius / _radius + mCenterY); } + // Events are instantaneous now + notifyOnMove(event); // to force a new draw invalidate(); @@ -525,127 +494,231 @@ public boolean onTouchEvent(MotionEvent event) { return true; } + /** + * Check if a callback exists + */ + private void notifyOnMove(MotionEvent event) { + if (mCallback == null) return; + mCallback.onMove(getAngle(), getStrength(), event); + } + + /** + * Reset the button position to the center. + */ + public void resetButtonPosition() { + mPosY = mAxisToCenter < AXIS_BOTH ? mPosY : mCenterY; // Axis positive, center vertical axe + mPosX = mAxisToCenter > AXIS_BOTH ? mPosX : mCenterX; // Axis negative, center horizontal axe + } + /* GETTERS */ - /** * Process the angle following the 360° counter-clock protractor rules. * @return the angle of the button */ - private int getAngle() { - int angle = (int) Math.toDegrees(Math.atan2(mCenterY - mPosY, mPosX - mCenterX)); + public int getAngle() { + int angle = (int) Math.round(Math.toDegrees(Math.atan2(mCenterY - mPosY, mPosX - mCenterX))); return angle < 0 ? angle + 360 : angle; // make it as a regular counter-clock protractor } - /** * Process the strength as a percentage of the distance between the center and the border. * @return the strength of the button */ - private int getStrength() { - return (int) (100 * Math.sqrt((mPosX - mCenterX) - * (mPosX - mCenterX) + (mPosY - mCenterY) - * (mPosY - mCenterY)) / mBorderRadius); + public int getStrength() { + int strength; + + if (isRectangle) { + if (false) { + + float Xb = mBorderWidth / 2f; + + float _X = Math.abs(mPosX - mCenterX); + + float Yb = mBorderHeight / 2f; + + float _Y = Math.abs(mPosY - mCenterY); + + float Yc = (_Y * Xb) / _X; + float Xc = (_X * Yb) / _Y; + + double _radius = Math.hypot(_X, _Y); + double _maxRadius = Math.hypot(Math.min(Xb, Xc), Math.min(Yb, Yc)); + + strength = (int) Math.round(_radius / _maxRadius * 100.0f); + } else + strength = Math.max(Math.abs(getDelX()), Math.abs(getDelY())); + + } else + strength = (int) Math.round(100 * Math.hypot(mPosX - mCenterX, mPosY - mCenterY) / mBorderRadius); + + // if (strength < mDeadzone) strength = 0; + + return strength; } + public final static int NONE = 0; + public final static int RIGHT_UP = 1; + public static final int UP_RIGHT = 2; + public static final int UP_LEFT = 3; + public final static int LEFT_UP = 4; + public final static int LEFT_DOWN = 5; + public final static int DOWN_LEFT = 6; + public final static int DOWN_RIGHT = 7; + public final static int RIGHT_DOWN = 8; /** - * Reset the button position to the center. + * @return return stick position + * {@link JoystickView#NONE}, + * {@link JoystickView#RIGHT_UP}, + * {@link JoystickView#UP_RIGHT}, + * {@link JoystickView#UP_LEFT}, + * {@link JoystickView#LEFT_UP}, + * {@link JoystickView#LEFT_DOWN}, + * {@link JoystickView#DOWN_LEFT}, + * {@link JoystickView#DOWN_RIGHT}, + * {@link JoystickView#RIGHT_DOWN}, */ - public void resetButtonPosition() { - mPosX = mCenterX; - mPosY = mCenterY; + public int getPosition() { + if ((mPosY - mCenterY) == 0 && (mPosX - mCenterX) == 0) { + return 0; + } + /* + int a = 0; + if (getAngle() <= 0) { + a = (getAngle() * -1) + 90; + } else if (getAngle() > 0) { + if (getAngle() <= 90) { + a = 90 - getAngle(); + } else { + a = 360 - (getAngle() - 90); + } + } + Log.e("TAG", "getDirection: "+a + " getAngle: "+getAngle()); +*/ + + return getAngle() / 45 + 1; } - /** * Return the current direction allowed for the button to move + * * @return Actually return an integer corresponding to the direction: * - A negative value is horizontal axe, * - A positive value is vertical axe, * - Zero means both axes */ - public int getButtonDirection() { - return mButtonDirection; + public int getAxisMotion() { + return mAxisMotionType; } - /** * Return the state of the joystick. False when the button don't move. + * * @return the state of the joystick */ + @Override public boolean isEnabled() { return mEnabled; } + /* + * Returns whether or not joystick is pressed, independent of angle/strength + */ + public boolean isPressed() { + return isPressed; + } + + public boolean isRectangle() { + return isRectangle; + } /** * Return the size of the button (as a ratio of the total width/height) * Default is 0.25 (25%). + * * @return button size (value between 0.0 and 1.0) */ public float getButtonSizeRatio() { - return mButtonSizeRatio; + return mButtonSizeRatio * 100; } /** * Return the size of the background (as a ratio of the total width/height) * Default is 0.75 (75%). + * * @return background size (value between 0.0 and 1.0) */ - public float getmBackgroundSizeRatio() { - return mBackgroundSizeRatio; + public float getBackgroundSizeRatio() { + return mBackgroundSizeRatio * 100; } /** * Return the current behavior of the auto re-center button + * * @return True if automatically re-centered or False if not */ public boolean isAutoReCenterButton() { return mAutoReCenterButton; } - /** * Return the current behavior of the button stick to border + * * @return True if the button stick to the border otherwise False */ public boolean isButtonStickToBorder() { return mButtonStickToBorder; } + public int getDelX() { + if (isRectangle) + return Math.round((mPosX - mCenterX) * 100.0f / (mBorderWidth / 2f)); + else + return Math.round((mPosX - mCenterX) * 100.0f / mBorderRadius); + } + + public int getDelY() { + if (isRectangle) + return Math.round((mPosY - mCenterY) * -100.0f / (mBorderHeight / 2.0f)); + else + return Math.round((mPosY - mCenterY) * -100.0f / mBorderRadius); + } /** - * Return the relative X coordinate of button center related + * Return the relative HORIZONTAL coordinate of button center related * to top-left virtual corner of the border - * @return coordinate of X (normalized between 0 and 100) + * + * @return coordinate of HORIZONTAL (normalized between 0 and 100) */ public int getNormalizedX() { - if (getWidth() == 0) { - return 50; - } - return Math.round((mPosX-mButtonRadius)*100.0f/(getWidth()-mButtonRadius*2)); - } + if (getWidth() == 0) return 50; + if (isRectangle) + return Math.round((mPosX - (mCenterX - mBorderWidth / 2f)) * 100.0f / mBorderWidth); + else + return Math.round((mPosX - (mCenterX - mBorderRadius)) * 100.0f / (mBorderRadius * 2)); + } /** - * Return the relative Y coordinate of the button center related + * Return the relative VERTICAL coordinate of the button center related * to top-left virtual corner of the border - * @return coordinate of Y (normalized between 0 and 100) + * + * @return coordinate of VERTICAL (normalized between 0 and 100) */ public int getNormalizedY() { - if (getHeight() == 0) { - return 50; - } - return Math.round((mPosY-mButtonRadius)*100.0f/(getHeight()-mButtonRadius*2)); + if (getHeight() == 0) return 50; + if (isRectangle) + return Math.round(100 - (mPosY - (mCenterY - mBorderHeight / 2f)) * 100.0f / mBorderHeight); + else + return Math.round(100 - (mPosY - (mCenterY - mBorderRadius)) * 100.0f / (mBorderRadius * 2)); } - /** * Return the alpha of the border * @return it should be an integer between 0 and 255 previously set @@ -654,35 +727,46 @@ public int getBorderAlpha() { return mBorderAlpha; } + public float getDeadzone() { + return mDeadzone; + } + + /** + * get axis to be centered + */ + public int getAxisToCenter() { + return mAxisToCenter; + } /* SETTERS */ + /** + * Sets the angle following the 360° counter-clock protractor rules. + */ + public void setAngle(int angle) { + mPosX = Math.round((getStrength() * 0.01 * Math.cos(Math.toRadians(angle))) + mCenterX); + mPosY = Math.round((getStrength() * 0.01 * Math.sin(Math.toRadians(angle))) + mCenterY); + invalidate(); + } + + /** + * Sets the strength as a percentage of the distance between the center and the border. + */ + public void setStrength(int strength) { + mPosX = Math.round((strength * 0.01 * Math.cos(Math.toRadians(getAngle()))) + mCenterX); + mPosY = Math.round((strength * 0.01 * Math.sin(Math.toRadians(getAngle()))) + mCenterY); + invalidate(); + } /** * Set an image to the button with a drawable * @param d drawable to pick the image */ public void setButtonDrawable(Drawable d) { - if (d != null) { - if (d instanceof BitmapDrawable) { - mButtonBitmap = ((BitmapDrawable) d).getBitmap(); - - if (mButtonRadius != 0) { - mButtonBitmap = Bitmap.createScaledBitmap( - mButtonBitmap, - mButtonRadius * 2, - mButtonRadius * 2, - true); - } - - if (mPaintBitmapButton != null) - mPaintBitmapButton = new Paint(); - } - } + mButtonDrawable = d; } - /** * Set the button color for this JoystickView. * @param color the color of the button @@ -692,27 +776,25 @@ public void setButtonColor(int color) { invalidate(); } - /** * Set the border color for this JoystickView. * @param color the color of the border */ public void setBorderColor(int color) { - mPaintCircleBorder.setColor(color); + mPaintBorder.setColor(color); if (color != Color.TRANSPARENT) { - mPaintCircleBorder.setAlpha(mBorderAlpha); + mPaintBorder.setAlpha(mBorderAlpha); } invalidate(); } - /** * Set the border alpha for this JoystickView. * @param alpha the transparency of the border between 0 and 255 */ public void setBorderAlpha(int alpha) { mBorderAlpha = alpha; - mPaintCircleBorder.setAlpha(alpha); + mPaintBorder.setAlpha(alpha); invalidate(); } @@ -733,41 +815,24 @@ public void setBackgroundColor(int color) { * @param width the width of the border */ public void setBorderWidth(int width) { - mPaintCircleBorder.setStrokeWidth(width); + mPaintBorder.setStrokeWidth(width); mBackgroundRadius = mBorderRadius - (width / 2.0f); - invalidate(); - } + mBackgroundWidth = mBorderWidth - (width / 2f); + mBackgroundHeight = mBorderHeight - (width / 2f); - /** - * Register a callback to be invoked when this JoystickView's button is moved - * @param l The callback that will run - */ - public void setOnMoveListener(OnMoveListener l) { - setOnMoveListener(l, DEFAULT_LOOP_INTERVAL); + invalidate(); } /** * Register a callback to be invoked when this JoystickView's button is moved - * @param l The callback that will run - * @param loopInterval Refresh rate to be invoked in milliseconds + * @param callback The callback that will run */ - public void setOnMoveListener(OnMoveListener l, int loopInterval) { - mCallback = l; - mLoopInterval = loopInterval; + public void setOnMoveListener(OnMoveListener callback) { + mCallback = callback; } - - /** - * Register a callback to be invoked when this JoystickView is touch and held by multiple pointers - * @param l The callback that will run - */ - public void setOnMultiLongPressListener(OnMultipleLongPressListener l) { - mOnMultipleLongPressListener = l; - } - - /** * Set the joystick center's behavior (fixed or auto-defined) * @param fixedCenter True for fixed center, False for auto-defined center based on touch down @@ -786,42 +851,54 @@ public void setFixedCenter(boolean fixedCenter) { * Enable or disable the joystick * @param enabled False mean the button won't move and onMove won't be called */ + @Override public void setEnabled(boolean enabled) { mEnabled = enabled; + super.setEnabled(enabled); + + if (mButtonDrawable == null) return; + int[] state = new int[]{enabled ? android.R.attr.state_enabled : -android.R.attr.state_enabled}; + mButtonDrawable.setState(state); + } /** * Set the joystick button size (as a fraction of the real width/height) - * By default it is 25% (0.25). - * @param newRatio between 0.0 and 1.0 + * By default it is 25% (25). + * @param newRatio between 0.0 and 100.0 */ public void setButtonSizeRatio(float newRatio) { - if (newRatio > 0.0f & newRatio <= 1.0f) { - mButtonSizeRatio = newRatio; + if (newRatio > 0.0f & newRatio <= 100.0f) { + mButtonSizeRatio = newRatio / 100; } } /** * Set the joystick button size (as a fraction of the real width/height) - * By default it is 75% (0.75). + * By default it is 75% (75). * Not working if the background is an image. - * @param newRatio between 0.0 and 1.0 + * @param newRatio between 0.0 and 100.0 */ public void setBackgroundSizeRatio(float newRatio) { - if (newRatio > 0.0f & newRatio <= 1.0f) { - mBackgroundSizeRatio = newRatio; + if (newRatio > 0.0f & newRatio <= 100f) { + mBackgroundSizeRatio = newRatio / 100; } } /** * Set the current behavior of the auto re-center button - * @param b True if automatically re-centered or False if not + * @param autoReCenter True if automatically re-centered or False if not */ - public void setAutoReCenterButton(boolean b) { - mAutoReCenterButton = b; + public void setAutoReCenterButton(boolean autoReCenter) { + mAutoReCenterButton = autoReCenter; + + if (mAutoReCenterButton) + resetButtonPosition(); + + invalidate(); } @@ -833,6 +910,10 @@ public void setButtonStickToBorder(boolean b) { mButtonStickToBorder = b; } + public void setRectangle(boolean useRectangle) { + this.isRectangle = useRectangle; + invalidate(); + } /** * Set the current authorized direction for the button to move @@ -841,31 +922,24 @@ public void setButtonStickToBorder(boolean b) { * - any positive value (such as 1) for vertical axe * - zero (0) for the full direction (both axes) */ - public void setButtonDirection(int direction) { - mButtonDirection = direction; + public void setAxisMotion(int direction) { + mAxisMotionType = direction; + onSizeChanged(getWidth(), getHeight(), getWidth(), getHeight()); + invalidate(); } - - /* - IMPLEMENTS + /** + * Set the joystick deadzone from 0-100. Having no of full deadzone is not recommended + * @param deadzone The deadzone, from 0-100. Strengths lower than it get reduced to 0. */ + public void setDeadzone(int deadzone) { + mDeadzone = deadzone; + } - - @Override // Runnable - public void run() { - while (!Thread.interrupted()) { - post(new Runnable() { - public void run() { - if (mCallback != null) - mCallback.onMove(getAngle(), getStrength()); - } - }); - - try { - Thread.sleep(mLoopInterval); - } catch (InterruptedException e) { - break; - } - } + /** + * set axis to be centered + */ + public void setAxisToCenter(int axisToCenter) { + this.mAxisToCenter = axisToCenter; } } \ No newline at end of file diff --git a/virtualjoystick/src/main/res/values/attrs.xml b/virtualjoystick/src/main/res/values/attrs.xml index c3bf1dc..8b6f5be 100644 --- a/virtualjoystick/src/main/res/values/attrs.xml +++ b/virtualjoystick/src/main/res/values/attrs.xml @@ -18,6 +18,8 @@ + + @@ -28,13 +30,21 @@ - + + + - + + + + + + + \ No newline at end of file