Android 自定义视图onTouch在其他视图中断开onTouch(如果使用XML布局添加)
我正在开发一个游戏,我有一个自定义视图Android 自定义视图onTouch在其他视图中断开onTouch(如果使用XML布局添加),android,android-view,touch-event,ontouch,xml-layout,Android,Android View,Touch Event,Ontouch,Xml Layout,我正在开发一个游戏,我有一个自定义视图操纵杆,其中有一个onTouch事件。我也有一个图像视图,它也有一个用于拍摄的接口 如果我使用java代码以编程方式将视图添加到主相对布局中,那么两个视图的onTouch可以完美地同时工作 问题是,如果我使用XML布局文件添加视图,那么,如果您触摸自定义视图操纵杆,则另一个视图的onTouch不起作用。只有使用XML布局文件创建布局时才会发生这种情况 我怎样才能解决这个问题 布局: <?xml version="1.0" encoding="utf-8
操纵杆
,其中有一个onTouch事件。我也有一个图像视图,它也有一个用于拍摄的接口
如果我使用java代码以编程方式将视图添加到主相对布局中,那么两个视图的onTouch可以完美地同时工作
问题是,如果我使用XML布局文件添加视图,那么,如果您触摸自定义视图操纵杆
,则另一个视图的onTouch不起作用。只有使用XML布局文件创建布局时才会发生这种情况
我怎样才能解决这个问题
布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/shootImageView"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:src="@drawable/shoot"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<com.myapp.uiviews.Joystick
android:id="@+id/joystick"
android:layout_width="wrap_content"
android:layout_height="150dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
使用该代码不起作用,但如果我使用下一个代码,它将非常有效。。。为什么?
shootImageView = new ImageView(this);
shootImageView.setId(102);
RelativeLayout.LayoutParams shootImageViewParams = new RelativeLayout.LayoutParams(sw/8, sw/8);
shootImageViewParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
shootImageViewParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
shootImageViewParams.setMargins(0, 0, sh/15, sh/15);
shootImageView.setLayoutParams(shootImageViewParams);
shootImageView.setImageDrawable(getResources().getDrawable(R.drawable.shoot));
shootImageView.setAlpha(0.4f);
shootImageView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
touchX=sw/2;
touchY=sh/2;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
LaserManager.getInstance().startLaserThread();
break;
case MotionEvent.ACTION_UP:
LaserManager.getInstance().stopLaserThread();
break;
}
return true;
}
});
main.addView(shootImageView);
joystickOnScreen = new Joystick(this);
int factor = GameState.getInstance().getSpaceship().getSpeedFactorCorrespondence();
joystickOnScreen.setMovementRange(sh/factor);
joystickOnScreen.setInnerPadding(sh/30);
joystickOnScreen.setOnJostickMovedListener(joystickListener);
RelativeLayout.LayoutParams joystickParams = new RelativeLayout.LayoutParams(sh/3, sh/3);
joystickParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
joystickParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
joystickParams.setMargins(sh/100, 0, 0, sh/100);
joystickOnScreen.setLayoutParams(joystickParams);
joystickOnScreen.setAlpha(0.3f);
main.addView(joystickOnScreen);
这是操纵杆类:
public class Joystick extends View {
public static final int INVALID_POINTER = -1;
private JoystickMovedListener moveListener;
//# of pixels moveWithAcceleration required between reporting to the listener
private float moveResolution;
//Max range of moveWithAcceleration in user coordinate system
private float movementRange;
//Last touch point in view coordinates
private int pointerId = INVALID_POINTER;
private float touchX;
private float touchY;
private float touchXDelayedMovement;
private float touchYDelayedMovement;
//Handle center in view coordinates
private float handleX;
private float handleY;
//Last reported position in view coordinates (allows different reporting sensitivities)
private float reportX;
private float reportY;
//Center of the view in view coordinates
private int cX;
private int cY;
//Size of the view in view coordinates
private int dimX;
private int dimY;
private int innerPadding;
private int bgRadius;
private int handleRadius;
private int movementRadius;
private int handleInnerBoundaries;
//Cartesian coordinates of last touch point - joystick center is (0,0)
private int cartX;
private int cartY;
//User coordinates of last touch point
private int userX;
private int userY;
//Offset co-ordinates (used when touch events are received from parent's coordinate origin)
private int offsetX;
private int offsetY;
private Paint bgPaint;
private Paint handlePaint;
boolean disabled;
Handler handler;
Handler handlerDelayedMovement;
public Joystick(Context context, AttributeSet attrs) {
super(context, attrs);
initJoystickView();
}
public Joystick(Context context) {
super(context);
initJoystickView();
}
private void initJoystickView() {
setFocusable(true);
handlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
handlePaint.setColor(Color.RED);
handlePaint.setStrokeWidth(1);
handlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bgPaint.setColor(Color.DKGRAY);
bgPaint.setStrokeWidth(1);
bgPaint.setStyle(Paint.Style.FILL_AND_STROKE);
this.moveResolution = 1.0f;
handler = new Handler();
handlerDelayedMovement = new Handler();
}
public void setMovementRange(float movementRange) {
this.movementRange = movementRange;
}
public void setOnJostickMovedListener(JoystickMovedListener listener) {
this.moveListener = listener;
}
@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.2);
handleInnerBoundaries = handleRadius;
movementRadius = Math.min(cX, cY) - handleInnerBoundaries;
}
@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);
}
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) {
result = 200; // Return a default size of 200 if no bounds are specified.
} else {
result = specSize; // As you want to fill the available space always return the full available bounds.
}
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);
canvas.restore();
}
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: {
if (disabled==true)
break;
return processMoveEvent(ev);
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
if ( pointerId != INVALID_POINTER ) {
returnHandleToCenterVisually();
returnHandleToCenterAcceleratedMovement();
setPointerId(INVALID_POINTER);
}
break;
}
case MotionEvent.ACTION_POINTER_UP: {
if ( pointerId != INVALID_POINTER ) {
final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if ( pointerId == this.pointerId ) {
returnHandleToCenterVisually();
returnHandleToCenterAcceleratedMovement();
setPointerId(INVALID_POINTER);
return true;
}
}
break;
}
case MotionEvent.ACTION_DOWN: {
handlerDelayedMovement.removeCallbacksAndMessages(null);
if ( pointerId == INVALID_POINTER ) {
int x = (int) ev.getX();
if ( x >= offsetX && x < offsetX + dimX ) {
setPointerId(ev.getPointerId(0));
if (disabled==true){
return true;
}
return processMoveEvent(ev);
}
}
break;
}
case MotionEvent.ACTION_POINTER_DOWN: {
if ( pointerId == INVALID_POINTER ) {
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 ) {
setPointerId(pointerId);
return true;
}
}
break;
}
}
return false;
}
private boolean processMoveEvent(MotionEvent ev) {
if ( pointerId != INVALID_POINTER ) {
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;
moveWithAcceleration();
invalidate();
return true;
}
return false;
}
private void moveWithAcceleration() {
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);
}
final int numberOfFrames = 5;
final double intervalsX = (touchX - touchXDelayedMovement) / numberOfFrames;
final double intervalsY = (touchY - touchYDelayedMovement) / numberOfFrames;
handlerDelayedMovement.removeCallbacksAndMessages(null);
for (int i = 0; i <= numberOfFrames; i++) {
handlerDelayedMovement.postDelayed(new Runnable() {
@Override
public void run() {
touchXDelayedMovement += intervalsX;
touchYDelayedMovement += intervalsY;
reportOnMoved();
}
}, i * 50);
}
}
private void reportOnMoved() {
//We calc user coordinates
//First convert to cartesian coordinates
cartX = (int)(touchXDelayedMovement / movementRadius * movementRange);
cartY = (int)(touchYDelayedMovement / movementRadius * movementRange);
//Cartesian Coordinates
userX = cartX;
userY = cartY;
if (moveListener != null) {
boolean rx = Math.abs(touchXDelayedMovement - reportX) >= moveResolution;
boolean ry = Math.abs(touchYDelayedMovement - reportY) >= moveResolution;
if (rx || ry) {
this.reportX = touchXDelayedMovement;
this.reportY = touchYDelayedMovement;
moveListener.OnMoved(userX, userY);
}
}
}
private void returnHandleToCenterVisually() {
final int numberOfFrames = 2;
final double intervalsX = (0 - touchX) / numberOfFrames;
final double intervalsY = (0 - touchY) / numberOfFrames;
handler.removeCallbacksAndMessages(null);
for (int i = 0; i < numberOfFrames; i++) {
final int j = i;
handler.postDelayed(new Runnable() {
@Override
public void run() {
touchX += intervalsX;
touchY += intervalsY;
invalidate();
if (moveListener != null && j == numberOfFrames - 1) {
moveListener.OnReturnedToCenter();
}
}
}, i * 15);
}
if (moveListener != null) {
moveListener.OnReleased();
}
}
private void returnHandleToCenterAcceleratedMovement() {
final int numberOfFrames = 10;
final double intervalsX = (0 - touchXDelayedMovement) / numberOfFrames;
final double intervalsY = (0 - touchYDelayedMovement) / numberOfFrames;
handlerDelayedMovement.removeCallbacksAndMessages(null);
for (int i = 0; i < numberOfFrames; i++) {
handlerDelayedMovement.postDelayed(new Runnable() {
@Override
public void run() {
touchXDelayedMovement += intervalsX;
touchYDelayedMovement += intervalsY;
reportOnMoved();
}
}, i * 50);
}
}
public void setInnerPadding(int innerPadding){
this.innerPadding=innerPadding;
}
public void disable(){
disabled=true;
}
public void enable(){
disabled=false;
}
public interface JoystickMovedListener {
public void OnMoved(int pan, int tilt);
public void OnReleased();
public void OnReturnedToCenter();
}
}
公共类操纵杆扩展视图{
公共静态final int无效_指针=-1;
私用JoystickMovedListener-moveListener;
//#在向侦听器报告之间需要加速的像素数
私人决议;
//用户坐标系中加速度移动的最大范围
私人浮动范围;
//视图坐标中的最后一个接触点
private int pointerId=无效的\u指针;
私人浮动触摸屏;
私人浮动敏感;
私人浮动触摸延时移动;
私人浮动触摸屏移动;
//控制柄在视图坐标中居中
私人浮动手柄;
私人浮球;
//视图坐标中上次报告的位置(允许不同的报告灵敏度)
私人浮动报告x;
私人流动报道;
//视图坐标中的视图中心
私人int cX;
私密性;
//视图坐标中视图的大小
私有int dimX;
私密性模糊;
私有内部填充;
私用内特半径;
私人住宅;
私有int-movementRadius;
私人int Handleinerboundary;
//最后一个接触点的笛卡尔坐标-操纵杆中心为(0,0)
私人int cartX;
私家车;
//最后一个接触点的用户坐标
私有int-userX;
私有用户;
//偏移坐标(从父坐标原点接收触摸事件时使用)
私人国际贸易抵销;
私人内部网外;
私人涂料;
私人油漆手绘;
布尔禁用;
处理者;
处理手延迟移动;
公共操纵杆(上下文、属性集属性){
超级(上下文,attrs);
initJoystickView();
}
公共操纵杆(上下文){
超级(上下文);
initJoystickView();
}
私有void initJoystickView(){
设置聚焦(真);
handlePaint=新油漆(油漆.防油漆别名标志);
手绘。设置颜色(颜色。红色);
手刷设置行程宽度(1);
手绘。设置样式(绘制。样式。填充和笔划);
bgPaint=新油漆(油漆.防油漆别名标志);
bgPaint.setColor(Color.DKGRAY);
bgPaint.设置行程宽度(1);
bgPaint.setStyle(Paint.Style.FILL_和_笔划);
此分辨率为1.0f;
handler=新的handler();
handlerDelayedMovement=新处理程序();
}
公共void设置移动范围(浮动移动范围){
this.movementRange=movementRange;
}
公共无效设置JoystickMovedListener(JoystickMovedListener侦听器){
this.moveListener=listener;
}
@凌驾
仅限受保护的空心布局(布尔值已更改、整数左侧、整数顶部、整数右侧、整数底部){
超级。仅限布局(已更改、左、上、右、下);
int d=Math.min(getMeasuredWidth(),getMeasuredHeight());
dimX=d;
dimY=d;
cX=d/2;
cY=d/2;
bgRadius=dimX/2-内部填充;
handleRadius=(int)(d*0.2);
handleInnerBoundaries=handleRadius;
movementRadius=数学最小值(cX,cY)-手动基准;
}
@凌驾
测量时的保护空隙(内部宽度测量等级、内部高度测量等级){
//在这里,我们确保我们有一个完美的圆
int MEASUREDWITH=测量值(widthMeasureSpec);
int measuredHeight=测量值(heightMeasureSpec);
设置测量尺寸(测量宽度、测量高度);
}
私有整数度量(整数度量){
int结果=0;
//解码测量规格。
int specMode=MeasureSpec.getMode(MeasureSpec);
int specSize=MeasureSpec.getSize(MeasureSpec);
if(specMode==MeasureSpec.UNSPECIFIED){
result=200;//如果未指定边界,则返回默认大小200。
}否则{
result=specSize;//如果要填充可用空间,请始终返回完整的可用边界。
}
返回结果;
}
@凌驾
受保护的void onDraw(画布){
canvas.save();
//画背景
画布.画圈(cX、cY、bgRadius、bgPaint);
//拉手
handleX=touchX+cX;
汉德利=敏感+cY;
帆布拉丝圈(handleX、handleY、handleRadius、handlePaint);
canvas.restore();
}
public void setPointerId(int-id){
this.pointerId=id;
}
public int getPointerId(){
返回指针ID;
}
@凌驾
公共事件(MotionEvent ev){
final int action=ev.getAction();
开关(动作和动作事件.动作屏蔽){
case MotionEvent.ACTION\u移动:{
if(disabled==true)
打破
返回事件(ev);
}
case MotionEvent.ACTION\u取消:
case MotionEvent.ACTION\u UP:{
if(pointerId!=无效的\u指针){
returnHandletoCenter();
ReturnHandleToCenter加速移动();
setPointerId(无效的_指针);
}
public class Joystick extends View {
public static final int INVALID_POINTER = -1;
private JoystickMovedListener moveListener;
//# of pixels moveWithAcceleration required between reporting to the listener
private float moveResolution;
//Max range of moveWithAcceleration in user coordinate system
private float movementRange;
//Last touch point in view coordinates
private int pointerId = INVALID_POINTER;
private float touchX;
private float touchY;
private float touchXDelayedMovement;
private float touchYDelayedMovement;
//Handle center in view coordinates
private float handleX;
private float handleY;
//Last reported position in view coordinates (allows different reporting sensitivities)
private float reportX;
private float reportY;
//Center of the view in view coordinates
private int cX;
private int cY;
//Size of the view in view coordinates
private int dimX;
private int dimY;
private int innerPadding;
private int bgRadius;
private int handleRadius;
private int movementRadius;
private int handleInnerBoundaries;
//Cartesian coordinates of last touch point - joystick center is (0,0)
private int cartX;
private int cartY;
//User coordinates of last touch point
private int userX;
private int userY;
//Offset co-ordinates (used when touch events are received from parent's coordinate origin)
private int offsetX;
private int offsetY;
private Paint bgPaint;
private Paint handlePaint;
boolean disabled;
Handler handler;
Handler handlerDelayedMovement;
public Joystick(Context context, AttributeSet attrs) {
super(context, attrs);
initJoystickView();
}
public Joystick(Context context) {
super(context);
initJoystickView();
}
private void initJoystickView() {
setFocusable(true);
handlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
handlePaint.setColor(Color.RED);
handlePaint.setStrokeWidth(1);
handlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bgPaint.setColor(Color.DKGRAY);
bgPaint.setStrokeWidth(1);
bgPaint.setStyle(Paint.Style.FILL_AND_STROKE);
this.moveResolution = 1.0f;
handler = new Handler();
handlerDelayedMovement = new Handler();
}
public void setMovementRange(float movementRange) {
this.movementRange = movementRange;
}
public void setOnJostickMovedListener(JoystickMovedListener listener) {
this.moveListener = listener;
}
@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.2);
handleInnerBoundaries = handleRadius;
movementRadius = Math.min(cX, cY) - handleInnerBoundaries;
}
@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);
}
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) {
result = 200; // Return a default size of 200 if no bounds are specified.
} else {
result = specSize; // As you want to fill the available space always return the full available bounds.
}
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);
canvas.restore();
}
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: {
if (disabled==true)
break;
return processMoveEvent(ev);
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
if ( pointerId != INVALID_POINTER ) {
returnHandleToCenterVisually();
returnHandleToCenterAcceleratedMovement();
setPointerId(INVALID_POINTER);
}
break;
}
case MotionEvent.ACTION_POINTER_UP: {
if ( pointerId != INVALID_POINTER ) {
final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if ( pointerId == this.pointerId ) {
returnHandleToCenterVisually();
returnHandleToCenterAcceleratedMovement();
setPointerId(INVALID_POINTER);
return true;
}
}
break;
}
case MotionEvent.ACTION_DOWN: {
handlerDelayedMovement.removeCallbacksAndMessages(null);
if ( pointerId == INVALID_POINTER ) {
int x = (int) ev.getX();
if ( x >= offsetX && x < offsetX + dimX ) {
setPointerId(ev.getPointerId(0));
if (disabled==true){
return true;
}
return processMoveEvent(ev);
}
}
break;
}
case MotionEvent.ACTION_POINTER_DOWN: {
if ( pointerId == INVALID_POINTER ) {
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 ) {
setPointerId(pointerId);
return true;
}
}
break;
}
}
return false;
}
private boolean processMoveEvent(MotionEvent ev) {
if ( pointerId != INVALID_POINTER ) {
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;
moveWithAcceleration();
invalidate();
return true;
}
return false;
}
private void moveWithAcceleration() {
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);
}
final int numberOfFrames = 5;
final double intervalsX = (touchX - touchXDelayedMovement) / numberOfFrames;
final double intervalsY = (touchY - touchYDelayedMovement) / numberOfFrames;
handlerDelayedMovement.removeCallbacksAndMessages(null);
for (int i = 0; i <= numberOfFrames; i++) {
handlerDelayedMovement.postDelayed(new Runnable() {
@Override
public void run() {
touchXDelayedMovement += intervalsX;
touchYDelayedMovement += intervalsY;
reportOnMoved();
}
}, i * 50);
}
}
private void reportOnMoved() {
//We calc user coordinates
//First convert to cartesian coordinates
cartX = (int)(touchXDelayedMovement / movementRadius * movementRange);
cartY = (int)(touchYDelayedMovement / movementRadius * movementRange);
//Cartesian Coordinates
userX = cartX;
userY = cartY;
if (moveListener != null) {
boolean rx = Math.abs(touchXDelayedMovement - reportX) >= moveResolution;
boolean ry = Math.abs(touchYDelayedMovement - reportY) >= moveResolution;
if (rx || ry) {
this.reportX = touchXDelayedMovement;
this.reportY = touchYDelayedMovement;
moveListener.OnMoved(userX, userY);
}
}
}
private void returnHandleToCenterVisually() {
final int numberOfFrames = 2;
final double intervalsX = (0 - touchX) / numberOfFrames;
final double intervalsY = (0 - touchY) / numberOfFrames;
handler.removeCallbacksAndMessages(null);
for (int i = 0; i < numberOfFrames; i++) {
final int j = i;
handler.postDelayed(new Runnable() {
@Override
public void run() {
touchX += intervalsX;
touchY += intervalsY;
invalidate();
if (moveListener != null && j == numberOfFrames - 1) {
moveListener.OnReturnedToCenter();
}
}
}, i * 15);
}
if (moveListener != null) {
moveListener.OnReleased();
}
}
private void returnHandleToCenterAcceleratedMovement() {
final int numberOfFrames = 10;
final double intervalsX = (0 - touchXDelayedMovement) / numberOfFrames;
final double intervalsY = (0 - touchYDelayedMovement) / numberOfFrames;
handlerDelayedMovement.removeCallbacksAndMessages(null);
for (int i = 0; i < numberOfFrames; i++) {
handlerDelayedMovement.postDelayed(new Runnable() {
@Override
public void run() {
touchXDelayedMovement += intervalsX;
touchYDelayedMovement += intervalsY;
reportOnMoved();
}
}, i * 50);
}
}
public void setInnerPadding(int innerPadding){
this.innerPadding=innerPadding;
}
public void disable(){
disabled=true;
}
public void enable(){
disabled=false;
}
public interface JoystickMovedListener {
public void OnMoved(int pan, int tilt);
public void OnReleased();
public void OnReturnedToCenter();
}
}