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

-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

+#### Rectangle
+It is possible to combine several configurations to create something new, such as a linear bar
+
+
+
#### 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`
+
+
+
```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