Cómo establecer el listener de ontouch para algo dibujado con lienzo: Android

Tengo una vista personalizada en la que estoy dibujando un gran círculo y un pequeño círculo en el borde de este gran círculo.

Quisiera mover el pequeño círculo y así quisiera tener un oyente del ontouch solamente para el círculo pequeño.

¿Podría alguno por favor decirme cómo establecer el oyente ontouch sólo para el pequeño círculo.

public class ThermoView extends View{ private ImageView mThermostatBgrd; private ImageView mCurTempArrow; private ImageView mSetPointIndicator; public static final int THEMROSTAT_BACKGROUND = 0; public static final int THEMROSTAT_CURR_TEMP = 1; public static final int THEMROSTAT_SET_POINT = 2; private float mViewCentreX; private float mViewCentreY; private float mThermostatRadius; private Canvas mCanvas; private Paint mPaint; private Paint mPaintCurTemp; private Paint mPaintSetTemp; private Paint mPaintOverrideTemp; private Paint mPaintCurTempIndicator; private Boolean mManualOverride = false; private double mManualOverrideAngle; private int mMaxTemp = 420; private int mMinTemp = 120; private RectF mCurrTempBox; private float mCurTempCircleX; private float mCurTempCircleY; private Matrix mMatrix; public double getManualOverrideAngle() { return mManualOverrideAngle; } public void setManualOverrideAngle(double mManualOverrideAngle) { this.mManualOverrideAngle = mManualOverrideAngle; } public RectF getCurrTempBox() { if (mCurrTempBox == null){ mCurrTempBox = new RectF(); } return mCurrTempBox; } public void setCurrTempBox(RectF mCurrTempBox) { this.mCurrTempBox = mCurrTempBox; } public Boolean getManualOverride() { return mManualOverride; } public void setManualOverride(Boolean mManualOverride) { this.mManualOverride = mManualOverride; } public ThermoView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Path smallCirle = new Path(); int viewWidth = getMeasuredWidth(); int viewHeight = getMeasuredHeight(); mViewCentreX = viewWidth/2; mViewCentreY = viewHeight/2; float paddingPercent = 0.2f; int thermostatThickness = 20; mThermostatRadius = (int) ((Math.min(mViewCentreX, mViewCentreY)*(1- paddingPercent))); if (mPaint == null){ mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); } mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(thermostatThickness); mPaint.setColor(0xffff0000); Path arcPath = new Path(); RectF container = new RectF(); container.set(mViewCentreX - mThermostatRadius, mViewCentreY - mThermostatRadius, mViewCentreX + mThermostatRadius, mViewCentreY + mThermostatRadius); arcPath.addArc(container, 120, 300); canvas.drawPath(arcPath, mPaint); int dummyCurTemp = 200; if (mPaintCurTemp == null){ mPaintCurTemp = new Paint(Paint.ANTI_ALIAS_FLAG); } mPaintCurTemp.setTextAlign(Align.CENTER); mPaintCurTemp.setTextSize(100); canvas.drawText(String.valueOf(dummyCurTemp), mViewCentreX, mViewCentreY, mPaintCurTemp); if (this.mManualOverride == false){ double angle = (360-120-(300/(mMaxTemp - mMinTemp))*(dummyCurTemp-mMinTemp))*(Math.PI/180); this.mCurTempCircleX = (float) (mViewCentreX + mThermostatRadius*(Math.cos(angle))); this.mCurTempCircleY = (float) (mViewCentreY - mThermostatRadius*(Math.sin(angle))); if (mCurrTempBox == null){ mCurrTempBox = new RectF(); } if (mPaintCurTempIndicator == null){ mPaintCurTempIndicator = new Paint(Paint.ANTI_ALIAS_FLAG); } mPaintCurTempIndicator.setStyle(Paint.Style.STROKE); mPaintCurTempIndicator.setStrokeWidth(thermostatThickness/2); mPaintCurTempIndicator.setColor(Color.GREEN); mCurrTempBox.set(mCurTempCircleX-50, mCurTempCircleY-50, mCurTempCircleX+50, mCurTempCircleY+50); smallCirle.addCircle(mCurTempCircleX, mCurTempCircleY, 50, Direction.CW); canvas.drawPath(smallCirle, mPaintCurTempIndicator); }else{ if (mCurrTempBox == null){ mCurrTempBox = new RectF(); } if (mPaintCurTempIndicator == null){ mPaintCurTempIndicator = new Paint(Paint.ANTI_ALIAS_FLAG); } if (mMatrix == null){ mMatrix = new Matrix(); } //mMatrix.reset(); mMatrix.postRotate((float) (mManualOverrideAngle), mViewCentreX,mViewCentreY); //mMatrix.postTranslate(mViewCentreX, mViewCentreY); mPaintCurTempIndicator.setStyle(Paint.Style.STROKE); mPaintCurTempIndicator.setStrokeWidth(thermostatThickness/2); mPaintCurTempIndicator.setColor(Color.GREEN); canvas.concat(mMatrix); smallCirle.addCircle(mCurTempCircleX, mCurTempCircleY, 50, Direction.CW); canvas.drawPath(smallCirle, mPaintCurTempIndicator); } } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mInitialX = event.getX(); mInitialY = event.getY(); RectF touchedAt = new RectF(mInitialX-10, mInitialY-10, mInitialX+10, mInitialY+10); RectF indicatorAt = mThermoStatView.getCurrTempBox(); if (RectF.intersects(indicatorAt, touchedAt)){ this.isIndicatorSelected = true; mThermoStatView.setManualOverride(true); } break; case MotionEvent.ACTION_MOVE: if (this.isIndicatorSelected == true){ float angle = (float) (180*Math.atan2(event.getY() - mThermostatHeight/2, event.getX() - mThermostatWidth/2) / Math.PI); mThermoStatView.setManualOverrideAngle(angle); mThermoStatView.invalidate(); //mThermoStatView.requestLayout(); } break; case MotionEvent.ACTION_UP: if (this.isIndicatorSelected == true){ this.isIndicatorSelected = false; } break; } return true; } } 

2 Solutions collect form web for “Cómo establecer el listener de ontouch para algo dibujado con lienzo: Android”

Intenta esto (esta es una pequeña versión modificada de MyView i ya publicado como respuesta a tu pregunta anterior):

 public class MyView extends View { private final static String TAG = "Main.MyView"; private static final float CX = 0; private static final float CY = 0; private static final float RADIUS = 20; private static final float BIGRADIUS = 50; private static final int NORMAL_COLOR = 0xffffffff; private static final int PRESSED_COLOR = 0xffff0000; private Paint mPaint; private Path mSmallCircle; private Path mCircle; private Matrix mMatrix; private float mAngle; private int mSmallCircleColor; public MyView(Context context) { super(context); mPaint = new Paint(); mSmallCircle = new Path(); mSmallCircle.addCircle(BIGRADIUS + RADIUS + CX, CY, RADIUS, Direction.CW); mSmallCircleColor = NORMAL_COLOR; mCircle = new Path(); mCircle.addCircle(0, 0, BIGRADIUS, Direction.CW); mMatrix = new Matrix(); } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_UP) { mSmallCircleColor = NORMAL_COLOR; invalidate(); return false; } float w2 = getWidth() / 2f; float h2 = getHeight() / 2f; float r = 0; if (action == MotionEvent.ACTION_DOWN) { float[] pts = { BIGRADIUS + RADIUS + CX, CY }; mMatrix.mapPoints(pts); r = (float) Math.hypot(event.getX() - pts[0], event.getY() - pts[1]); } if (r < RADIUS) { mSmallCircleColor = PRESSED_COLOR; mAngle = (float) (180 * Math.atan2(event.getY() - h2, event.getX() - w2) / Math.PI); invalidate(); return true; } return false; } @Override protected void onDraw(Canvas canvas) { float w2 = getWidth() / 2f; float h2 = getHeight() / 2f; mMatrix.reset(); mMatrix.postRotate(mAngle); mMatrix.postTranslate(w2, h2); canvas.concat(mMatrix); mPaint.setColor(0x88ffffff); canvas.drawPath(mCircle, mPaint); mPaint.setColor(mSmallCircleColor); canvas.drawPath(mSmallCircle, mPaint); } } 

Puede obtener el rectángulo de su punto de contacto y el rectángulo (posición) de su círculo interno y comprobar si se cruzan con el método Intersects.

http://docs.oracle.com/javase/7/docs/api/java/awt/Rectangle.html#intersects(java.awt.Rectangle)

Su canvas onTouchListener puede hacer lo que necesite hacer si el punto de contacto intersecta su círculo.

p.ej:

  // Create a rectangle from the point of touch Rect touchpoint = new Rect(x,y,10,10); // Create a rectangle from the postion of the circle. Rect myCircle=new Rect(10,10,20,20); if (Rect.intersects(myCircle,touchpoint)){ Log.d("The circle was touched"); } 
  • ¿Por qué Google utiliza Canvas en la vista de la lista de conversaciones de aplicaciones de Gmail?
  • Android - ¿Cómo circular zoom / ampliar parte de la imagen?
  • Dibujar texto dentro de un arco utilizando lienzo
  • ¿Cómo mostrar tanto MarkerIcon como Title en google map como Google Apps?
  • Dibuje mapas de bits a escala sin problemas en la lona
  • Android AvoidXfermode está obsoleto desde la API 16, ¿hay un reemplazo?
  • Error de GL de OpenGLRenderer: 0x502
  • Aplicación lenta con imagen de fondo
  • ¿Cómo crear un círculo clippath de una imagen?
  • Aplicación de Android - ¿Cómo guardar un dibujo de mapa de bits en lienzo como imagen? ¿Código de verificación?
  • Problema de hilo simple con la animación de Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.