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; } } 

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"); } 
  • Canvas.drawVertices (...) no dibuja nada
  • Inclinar una vista de texto en Android
  • ¿Cómo utilizar el lienzo de android para dibujar un rectángulo con sólo topleft y las esquinas verticales alrededor?
  • Coloque un rectángulo alrededor de una cadena en un lienzo de Android
  • ¿Cómo puedo traducir correctamente coordenadas de píxeles a coordenadas de lienzo en Android?
  • Escala de lienzo para cambiar el tamaño de SVG en Android
  • Cómo utilizar matrix.preScale (x, y)
  • Mal rendimiento de Android Canvas.drawBitmap - cambiar a OpenGL?
  • Rutas de Android para gráficos en tiempo real
  • Cómo dibujar Arco entre dos puntos en el lienzo?
  • Cómo dibujar la imagen en la esquina inferior derecha del lienzo?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.