Added Joy stick classes and resources

Signed-off-by: Ricky Barrette <rickbarrette@gmail.com>
This commit is contained in:
2012-12-11 11:47:12 -05:00
parent 2c30e39eaa
commit b10f5d1c85
10 changed files with 817 additions and 3 deletions

View File

@@ -4,6 +4,5 @@
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry kind="lib" path="/home/ricky/App/android-sdk-linux_86/extras/android-support-v4-r6-googlemaps.jar"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View File

@@ -9,6 +9,6 @@
# Project target.
target=Google Inc.:Google APIs:17
android.library.reference.3=../ioiolib/IOIOLib
android.library.reference.1=../../exception_handler_library/ExceptionHandlerLib
android.library.reference.2=../../location_library/LocationLib
android.library.reference.2=../ioiolib/IOIOLib
android.library.reference.3=../../location_library/LocationLib

View File

@@ -0,0 +1,37 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.MobileAnarchy.Android.Widgets.Joystick.DualJoystickView
android:id="@+id/dualjoystickView" android:layout_gravity="center_horizontal"
android:layout_marginTop="5dip" android:layout_width="fill_parent"
android:layout_height="175dip" />
<TableLayout android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="center_horizontal"
android:layout_marginTop="10dip">
<TableRow>
<TextView android:text="X" android:layout_width="50dip"
android:layout_height="wrap_content"></TextView>
<TextView android:text="" android:id="@+id/TextViewX1"
android:layout_width="150dip" android:layout_height="wrap_content"></TextView>
<TextView android:text="X" android:layout_width="50dip"
android:layout_height="wrap_content"></TextView>
<TextView android:text="" android:id="@+id/TextViewX2"
android:layout_width="100dip" android:layout_height="wrap_content"></TextView>
</TableRow>
<TableRow>
<TextView android:text="Y" android:layout_width="wrap_content"
android:layout_height="wrap_content"></TextView>
<TextView android:text="" android:id="@+id/TextViewY1"
android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
<TextView android:text="Y" android:layout_width="wrap_content"
android:layout_height="wrap_content"></TextView>
<TextView android:text="" android:id="@+id/TextViewY2"
android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
</TableRow>
</TableLayout>
</LinearLayout>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.MobileAnarchy.Android.Widgets.Joystick.JoystickView
android:id="@+id/joystickView" android:layout_gravity="center_horizontal"
android:layout_marginTop="20dip" android:layout_width="175dip"
android:layout_height="175dip" />
<TableLayout android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="center_horizontal"
android:layout_marginTop="10dip">
<TableRow>
<TextView android:text="X" android:layout_width="50dip"
android:layout_height="wrap_content"></TextView>
<TextView android:text="" android:id="@+id/TextViewX"
android:layout_width="100dip" android:layout_height="wrap_content"></TextView>
</TableRow>
<TableRow>
<TextView android:text="Y" android:layout_width="wrap_content"
android:layout_height="wrap_content"></TextView>
<TextView android:text="" android:id="@+id/TextViewY"
android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
</TableRow>
</TableLayout>
</LinearLayout>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="DockPanel">
<attr name="handleButtonDrawableId" format="reference" />
<attr name="contentLayoutId" format="reference" />
<attr name="dockPosition" format="enum" />
<attr name="isOpen" format="boolean" />
<attr name="animationDuration" format="integer" />
</declare-styleable>
<declare-styleable name="ThresholdEditText">
<attr name="threshold" format="integer" />
<attr name="disableThresholdOnEmptyInput" format="boolean" />
</declare-styleable>
</resources>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2009 The Android Open Source Project Licensed under the
Apache License, Version 2.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for
the specific language governing permissions and limitations under the
License.
-->
<resources>
<!-- height of a normal list item in edit playlist mode -->
<dimen name="normal_height">66dip</dimen>
<!-- height of an expanded list item in edit playlist mode -->
<dimen name="expanded_height">132dip</dimen>
</resources>

View File

@@ -0,0 +1,156 @@
package com.MobileAnarchy.Android.Widgets.Joystick;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
public class DualJoystickView extends LinearLayout {
@SuppressWarnings("unused")
private static final String TAG = DualJoystickView.class.getSimpleName();
private final boolean D = false;
private Paint dbgPaint1;
private JoystickView stickL;
private JoystickView stickR;
private View pad;
public DualJoystickView(Context context) {
super(context);
stickL = new JoystickView(context);
stickR = new JoystickView(context);
initDualJoystickView();
}
public DualJoystickView(Context context, AttributeSet attrs) {
super(context, attrs);
stickL = new JoystickView(context, attrs);
stickR = new JoystickView(context, attrs);
initDualJoystickView();
}
private void initDualJoystickView() {
setOrientation(LinearLayout.HORIZONTAL);
if (D) {
dbgPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
dbgPaint1.setColor(Color.CYAN);
dbgPaint1.setStrokeWidth(1);
dbgPaint1.setStyle(Paint.Style.STROKE);
}
pad = new View(getContext());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
removeView(stickL);
removeView(stickR);
float padW = getMeasuredWidth() - (getMeasuredHeight() * 2);
int joyWidth = (int) ((getMeasuredWidth() - padW) / 2);
LayoutParams joyLParams = new LayoutParams(joyWidth,
getMeasuredHeight());
stickL.setLayoutParams(joyLParams);
stickR.setLayoutParams(joyLParams);
stickL.TAG = "L";
stickR.TAG = "R";
stickL.setPointerId(JoystickView.INVALID_POINTER_ID);
stickR.setPointerId(JoystickView.INVALID_POINTER_ID);
addView(stickL);
ViewGroup.LayoutParams padLParams = new ViewGroup.LayoutParams(
(int) padW, getMeasuredHeight());
removeView(pad);
pad.setLayoutParams(padLParams);
addView(pad);
addView(stickR);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
stickR.setTouchOffset(stickR.getLeft(), stickR.getTop());
}
public void setAutoReturnToCenter(boolean left, boolean right) {
stickL.setAutoReturnToCenter(left);
stickR.setAutoReturnToCenter(right);
}
public void setOnJostickMovedListener(JoystickMovedListener left,
JoystickMovedListener right) {
stickL.setOnJostickMovedListener(left);
stickR.setOnJostickMovedListener(right);
}
public void setOnJostickClickedListener(JoystickClickedListener left,
JoystickClickedListener right) {
stickL.setOnJostickClickedListener(left);
stickR.setOnJostickClickedListener(right);
}
public void setYAxisInverted(boolean leftYAxisInverted,
boolean rightYAxisInverted) {
stickL.setYAxisInverted(leftYAxisInverted);
stickL.setYAxisInverted(rightYAxisInverted);
}
public void setMovementConstraint(int movementConstraint) {
stickL.setMovementConstraint(movementConstraint);
stickR.setMovementConstraint(movementConstraint);
}
public void setMovementRange(float movementRangeLeft,
float movementRangeRight) {
stickL.setMovementRange(movementRangeLeft);
stickR.setMovementRange(movementRangeRight);
}
public void setMoveResolution(float leftMoveResolution,
float rightMoveResolution) {
stickL.setMoveResolution(leftMoveResolution);
stickR.setMoveResolution(rightMoveResolution);
}
public void setUserCoordinateSystem(int leftCoordinateSystem,
int rightCoordinateSystem) {
stickL.setUserCoordinateSystem(leftCoordinateSystem);
stickR.setUserCoordinateSystem(rightCoordinateSystem);
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (D) {
canvas.drawRect(1, 1, getMeasuredWidth() - 1,
getMeasuredHeight() - 1, dbgPaint1);
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean l = stickL.dispatchTouchEvent(ev);
boolean r = stickR.dispatchTouchEvent(ev);
return l || r;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean l = stickL.onTouchEvent(ev);
boolean r = stickR.onTouchEvent(ev);
return l || r;
}
}

View File

@@ -0,0 +1,7 @@
package com.MobileAnarchy.Android.Widgets.Joystick;
public interface JoystickClickedListener {
public void OnClicked();
public void OnReleased();
}

View File

@@ -0,0 +1,9 @@
package com.MobileAnarchy.Android.Widgets.Joystick;
public interface JoystickMovedListener {
public void OnMoved(int pan, int tilt);
public void OnReleased();
public void OnReturnedToCenter();
}

View File

@@ -0,0 +1,542 @@
package com.MobileAnarchy.Android.Widgets.Joystick;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
public class JoystickView extends View {
public static final int INVALID_POINTER_ID = -1;
// =========================================
// Private Members
// =========================================
private final boolean D = false;
String TAG = "JoystickView";
private Paint dbgPaint1;
private Paint dbgPaint2;
private Paint bgPaint;
private Paint handlePaint;
private int innerPadding;
private int bgRadius;
private int handleRadius;
private int movementRadius;
private int handleInnerBoundaries;
private JoystickMovedListener moveListener;
private JoystickClickedListener clickListener;
// # of pixels movement required between reporting to the listener
private float moveResolution;
private boolean yAxisInverted;
private boolean autoReturnToCenter;
// Max range of movement in user coordinate system
public final static int CONSTRAIN_BOX = 0;
public final static int CONSTRAIN_CIRCLE = 1;
private int movementConstraint;
private float movementRange;
public final static int COORDINATE_CARTESIAN = 0; // Regular cartesian
// coordinates
public final static int COORDINATE_DIFFERENTIAL = 1; // Uses polar rotation
// of 45 degrees to
// calc differential
// drive paramaters
private int userCoordinateSystem;
// Records touch pressure for click handling
private float touchPressure;
private boolean clicked;
private float clickThreshold;
// Last touch point in view coordinates
private int pointerId = INVALID_POINTER_ID;
private float touchX, touchY;
// Last reported position in view coordinates (allows different reporting
// sensitivities)
private float reportX, reportY;
// Handle center in view coordinates
private float handleX, handleY;
// Center of the view in view coordinates
private int cX, cY;
// Size of the view in view coordinates
private int dimX;
// Cartesian coordinates of last touch point - joystick center is (0,0)
private int cartX, cartY;
// Polar coordinates of the touch point from joystick center
private double radial;
private double angle;
// User coordinates of last touch point
private int userX, userY;
// Offset co-ordinates (used when touch events are received from parent's
// coordinate origin)
private int offsetX;
private int offsetY;
// =========================================
// Constructors
// =========================================
public JoystickView(Context context) {
super(context);
initJoystickView();
}
public JoystickView(Context context, AttributeSet attrs) {
super(context, attrs);
initJoystickView();
}
public JoystickView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initJoystickView();
}
// =========================================
// Initialization
// =========================================
private void initJoystickView() {
setFocusable(true);
dbgPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
dbgPaint1.setColor(Color.RED);
dbgPaint1.setStrokeWidth(1);
dbgPaint1.setStyle(Paint.Style.STROKE);
dbgPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
dbgPaint2.setColor(Color.GREEN);
dbgPaint2.setStrokeWidth(1);
dbgPaint2.setStyle(Paint.Style.STROKE);
bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bgPaint.setColor(Color.GRAY);
bgPaint.setStrokeWidth(1);
bgPaint.setAlpha(80);
bgPaint.setStyle(Paint.Style.FILL_AND_STROKE);
handlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
handlePaint.setColor(Color.DKGRAY);
handlePaint.setStrokeWidth(1);
handlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
innerPadding = 10;
setMovementRange(10);
setMoveResolution(1.0f);
setClickThreshold(0.4f);
setYAxisInverted(true);
setUserCoordinateSystem(COORDINATE_CARTESIAN);
setAutoReturnToCenter(true);
}
public void setAutoReturnToCenter(boolean autoReturnToCenter) {
this.autoReturnToCenter = autoReturnToCenter;
}
public boolean isAutoReturnToCenter() {
return autoReturnToCenter;
}
public void setUserCoordinateSystem(int userCoordinateSystem) {
if (userCoordinateSystem < COORDINATE_CARTESIAN
|| movementConstraint > COORDINATE_DIFFERENTIAL)
Log.e(TAG, "invalid value for userCoordinateSystem");
else
this.userCoordinateSystem = userCoordinateSystem;
}
public int getUserCoordinateSystem() {
return userCoordinateSystem;
}
public void setMovementConstraint(int movementConstraint) {
if (movementConstraint < CONSTRAIN_BOX
|| movementConstraint > CONSTRAIN_CIRCLE)
Log.e(TAG, "invalid value for movementConstraint");
else
this.movementConstraint = movementConstraint;
}
public int getMovementConstraint() {
return movementConstraint;
}
public boolean isYAxisInverted() {
return yAxisInverted;
}
public void setYAxisInverted(boolean yAxisInverted) {
this.yAxisInverted = yAxisInverted;
}
/**
* Set the pressure sensitivity for registering a click
*
* @param clickThreshold
* threshold 0...1.0f inclusive. 0 will cause clicks to never be
* reported, 1.0 is a very hard click
*/
public void setClickThreshold(float clickThreshold) {
if (clickThreshold < 0 || clickThreshold > 1.0f)
Log.e(TAG, "clickThreshold must range from 0...1.0f inclusive");
else
this.clickThreshold = clickThreshold;
}
public float getClickThreshold() {
return clickThreshold;
}
public void setMovementRange(float movementRange) {
this.movementRange = movementRange;
}
public float getMovementRange() {
return movementRange;
}
public void setMoveResolution(float moveResolution) {
this.moveResolution = moveResolution;
}
public float getMoveResolution() {
return moveResolution;
}
// =========================================
// Public Methods
// =========================================
public void setOnJostickMovedListener(JoystickMovedListener listener) {
this.moveListener = listener;
}
public void setOnJostickClickedListener(JoystickClickedListener listener) {
this.clickListener = listener;
}
// =========================================
// Drawing Functionality
// =========================================
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Here we make sure that we have a perfect circle
int measuredWidth = measure(widthMeasureSpec);
int measuredHeight = measure(heightMeasureSpec);
setMeasuredDimension(measuredWidth, measuredHeight);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
int d = Math.min(getMeasuredWidth(), getMeasuredHeight());
dimX = d;
// dimY = d;
cX = d / 2;
cY = d / 2;
bgRadius = dimX / 2 - innerPadding;
handleRadius = (int) (d * 0.25);
handleInnerBoundaries = handleRadius;
movementRadius = Math.min(cX, cY) - handleInnerBoundaries;
}
private int measure(int measureSpec) {
int result = 0;
// Decode the measurement specifications.
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.UNSPECIFIED) {
// Return a default size of 200 if no bounds are specified.
result = 200;
} else {
// As you want to fill the available space
// always return the full available bounds.
result = specSize;
}
return result;
}
@Override
protected void onDraw(Canvas canvas) {
canvas.save();
// Draw the background
canvas.drawCircle(cX, cY, bgRadius, bgPaint);
// Draw the handle
handleX = touchX + cX;
handleY = touchY + cY;
canvas.drawCircle(handleX, handleY, handleRadius, handlePaint);
if (D) {
canvas.drawRect(1, 1, getMeasuredWidth() - 1,
getMeasuredHeight() - 1, dbgPaint1);
canvas.drawCircle(handleX, handleY, 3, dbgPaint1);
if (movementConstraint == CONSTRAIN_CIRCLE) {
canvas.drawCircle(cX, cY, this.movementRadius, dbgPaint1);
} else {
canvas.drawRect(cX - movementRadius, cY - movementRadius, cX
+ movementRadius, cY + movementRadius, dbgPaint1);
}
// Origin to touch point
canvas.drawLine(cX, cY, handleX, handleY, dbgPaint2);
int baseY = (int) (touchY < 0 ? cY + handleRadius : cY
- handleRadius);
canvas.drawText(
String.format("%s (%.0f,%.0f)", TAG, touchX, touchY),
handleX - 20, baseY - 7, dbgPaint2);
canvas.drawText(
"("
+ String.format("%.0f, %.1f", radial,
angle * 57.2957795) + (char) 0x00B0 + ")",
handleX - 20, baseY + 15, dbgPaint2);
}
// Log.d(TAG, String.format("touch(%f,%f)", touchX, touchY));
// Log.d(TAG, String.format("onDraw(%.1f,%.1f)\n\n", handleX, handleY));
canvas.restore();
}
// Constrain touch within a box
private void constrainBox() {
touchX = Math.max(Math.min(touchX, movementRadius), -movementRadius);
touchY = Math.max(Math.min(touchY, movementRadius), -movementRadius);
}
// Constrain touch within a circle
private void constrainCircle() {
float diffX = touchX;
float diffY = touchY;
double radial = Math.sqrt((diffX * diffX) + (diffY * diffY));
if (radial > movementRadius) {
touchX = (int) ((diffX / radial) * movementRadius);
touchY = (int) ((diffY / radial) * movementRadius);
}
}
public void setPointerId(int id) {
this.pointerId = id;
}
public int getPointerId() {
return pointerId;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_MOVE: {
return processMoveEvent(ev);
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
if (pointerId != INVALID_POINTER_ID) {
// Log.d(TAG, "ACTION_UP");
returnHandleToCenter();
setPointerId(INVALID_POINTER_ID);
}
break;
}
case MotionEvent.ACTION_POINTER_UP: {
if (pointerId != INVALID_POINTER_ID) {
final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == this.pointerId) {
// Log.d(TAG, "ACTION_POINTER_UP: " + pointerId);
returnHandleToCenter();
setPointerId(INVALID_POINTER_ID);
return true;
}
}
break;
}
case MotionEvent.ACTION_DOWN: {
if (pointerId == INVALID_POINTER_ID) {
int x = (int) ev.getX();
if (x >= offsetX && x < offsetX + dimX) {
setPointerId(ev.getPointerId(0));
// Log.d(TAG, "ACTION_DOWN: " + getPointerId());
return true;
}
}
break;
}
case MotionEvent.ACTION_POINTER_DOWN: {
if (pointerId == INVALID_POINTER_ID) {
final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
int x = (int) ev.getX(pointerId);
if (x >= offsetX && x < offsetX + dimX) {
// Log.d(TAG, "ACTION_POINTER_DOWN: " + pointerId);
setPointerId(pointerId);
return true;
}
}
break;
}
}
return false;
}
private boolean processMoveEvent(MotionEvent ev) {
if (pointerId != INVALID_POINTER_ID) {
final int pointerIndex = ev.findPointerIndex(pointerId);
// Translate touch position to center of view
float x = ev.getX(pointerIndex);
touchX = x - cX - offsetX;
float y = ev.getY(pointerIndex);
touchY = y - cY - offsetY;
// Log.d(TAG,
// String.format("ACTION_MOVE: (%03.0f, %03.0f) => (%03.0f, %03.0f)",
// x, y, touchX, touchY));
reportOnMoved();
invalidate();
touchPressure = ev.getPressure(pointerIndex);
reportOnPressure();
return true;
}
return false;
}
private void reportOnMoved() {
if (movementConstraint == CONSTRAIN_CIRCLE)
constrainCircle();
else
constrainBox();
calcUserCoordinates();
if (moveListener != null) {
boolean rx = Math.abs(touchX - reportX) >= moveResolution;
boolean ry = Math.abs(touchY - reportY) >= moveResolution;
if (rx || ry) {
this.reportX = touchX;
this.reportY = touchY;
// Log.d(TAG, String.format("moveListener.OnMoved(%d,%d)",
// (int)userX, (int)userY));
moveListener.OnMoved(userX, userY);
}
}
}
private void calcUserCoordinates() {
// First convert to cartesian coordinates
cartX = (int) (touchX / movementRadius * movementRange);
cartY = (int) (touchY / movementRadius * movementRange);
radial = Math.sqrt((cartX * cartX) + (cartY * cartY));
angle = Math.atan2(cartY, cartX);
// Invert Y axis if requested
if (!yAxisInverted)
cartY *= -1;
if (userCoordinateSystem == COORDINATE_CARTESIAN) {
userX = cartX;
userY = cartY;
} else if (userCoordinateSystem == COORDINATE_DIFFERENTIAL) {
userX = cartY + cartX / 4;
userY = cartY - cartX / 4;
if (userX < -movementRange)
userX = (int) -movementRange;
if (userX > movementRange)
userX = (int) movementRange;
if (userY < -movementRange)
userY = (int) -movementRange;
if (userY > movementRange)
userY = (int) movementRange;
}
}
// Simple pressure click
private void reportOnPressure() {
// Log.d(TAG, String.format("touchPressure=%.2f", this.touchPressure));
if (clickListener != null) {
if (clicked && touchPressure < clickThreshold) {
clickListener.OnReleased();
this.clicked = false;
// Log.d(TAG, "reset click");
invalidate();
} else if (!clicked && touchPressure >= clickThreshold) {
clicked = true;
clickListener.OnClicked();
// Log.d(TAG, "click");
invalidate();
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
}
}
}
private void returnHandleToCenter() {
if (autoReturnToCenter) {
final int numberOfFrames = 5;
final double intervalsX = (0 - touchX) / numberOfFrames;
final double intervalsY = (0 - touchY) / numberOfFrames;
for (int i = 0; i < numberOfFrames; i++) {
final int j = i;
postDelayed(new Runnable() {
@Override
public void run() {
touchX += intervalsX;
touchY += intervalsY;
reportOnMoved();
invalidate();
if (moveListener != null && j == numberOfFrames - 1) {
moveListener.OnReturnedToCenter();
}
}
}, i * 40);
}
if (moveListener != null) {
moveListener.OnReleased();
}
}
}
public void setTouchOffset(int x, int y) {
offsetX = x;
offsetY = y;
}
}