2015-03-08 2 views
0

мне нужно:OnTouchListener не работает на холсте

  1. краска круг и
  2. получить координаты на точке

, где мой палец прикасается мнение.

Fragment

.. 
mPaintSurface = (PaintSurface) view.findViewById(R.id.image_body); 
// Paint a circle when touched 
mPaintSurface.setOnTouchListener(mPaintSurface); 
// Get coordinates when touched 
mPaintSurface.setOnTouchListener(new OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       if(event.getAction() == MotionEvent.ACTION_UP){ 
        // Do what you want 
        Log.d("Fragment_Point", "X: "+mPaintSurface.getRelativeXpos()+" Y: "+mPaintSurface.getRelativeYpos()); 
        return true; 
       } 
       return false; 
      } 
     }); 
.. 

PaintSurface

public class PaintSurface extends SurfaceView implements Runnable, OnTouchListener{ 

    // Surface holder allows to control and monitor the surface 
    private SurfaceHolder mHolder; 

    // A thread where the painting activities are taking place 
    private Thread mThread; 

    // A flag which controls the start and stop of the repainting of the SurfaceView 
    private boolean mFlag = false; 

    // X coordinate of the touched position 
    private float mX; 

    // Y Coordinate of the touched position 
    private float mY; 

    // Paint 
    private Paint mPaint; 

    // Widths and Heights 
    private int mWidth; 
    private int mHeight; 


    public PaintSurface(Context context, AttributeSet attrs) { 
     super(context, attrs); 

     // Getting the holder 
     mHolder = getHolder(); 

     // Initializing the X position 
     mX = -100; 

     // Initializing the Y position 
     mY = -100; 

     // Initializing the paint object mPaint 
     mPaint = new Paint(); 

     // Setting the color for the paint object 
     mPaint.setColor(Color.RED); 

    } 

    public void resume(){ 
     // Instantiating the thread 
     mThread = new Thread(this); 

     // setting the mFlag to true for start repainting 
     mFlag = true; 

     // Start repaint the SurfaceView 
     mThread.start(); 
    } 

    public void pause(){ 
     mFlag = false; 
    } 

    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     switch(event.getAction()){ 
      case MotionEvent.ACTION_DOWN: 
       // Getting the X-Coordinate of the touched position 
       mX = event.getX(); 
       // Getting the Y-Coordinate of the touched position 
       mY = event.getY(); 

       Log.d("PaintSurface", "getWidth(): " + getWidth() + " getHeight(): " + getHeight()); 
       Log.d("PaintSurface", "X: " + mX/getWidth() + " Y: " + mY/getHeight()); 

       break; 
     } 
     return true; 
    } 

    @Override 
    public void run() { 
     while(mFlag){ 
      // Check whether the object holds a valid surface 
      if(!mHolder.getSurface().isValid()) 
       continue; 
      // Start editing the surface 
      Canvas canvas = mHolder.lockCanvas(); 
      // Draw a body image from Drawables 
      Bitmap b=BitmapFactory.decodeResource(getResources(), R.drawable.body_50); 
      b = getResizedBitmap(b, getWidth(), getHeight()); 
      Paint p=new Paint(); 
      canvas.drawBitmap(b, 0, 0, p); 
      // Draw a circle at (mX,mY) with radius 5 
      canvas.drawCircle(mX, mY, 10, mPaint); 
      // Finish editing the canvas and show to the user 
      mHolder.unlockCanvasAndPost(canvas); 
     } 
    } 

    public float getRelativeXpos(){ 
     return mX/getWidth(); 
    } 

    public float getRelativeYpos(){ 
     return mX/getHeight(); 
    } 

    private Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) { 
     int width = bm.getWidth(); 
     int height = bm.getHeight(); 
     float scaleWidth = ((float) newWidth)/width; 
     float scaleHeight = ((float) newHeight)/height; 
     // CREATE A MATRIX FOR THE MANIPULATION 
     Matrix matrix = new Matrix(); 
     // RESIZE THE BIT MAP 
     matrix.postScale(scaleWidth, scaleHeight); 

     // "RECREATE" THE NEW BITMAP 
     Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false); 
     return resizedBitmap; 
    } 

} 

Есть 2 на сенсорных слушателях для выполнения этого действия. Первый сенсорный исполнитель работает (рисует круг в момент, когда я касаюсь). Тем не менее, второй сенсорный прослушиватель, который пытается прослушать события касания на пользовательском представлении, не работает (без регистрации при касании). OnTouch работает только внутри пользовательского вида Paint Surface, но не внутри моего фрагмента.

* Мне нужен способ извлечь координаты, которые касаются холста к моим фрагментам.

Я также пробовал onClickListeners, те же результаты. Возможно, я неправильно понял контактных лиц, но почему это так, что один touchlistener работает, а другой нет? Спасибо за любые подсказки. (:..

UPDATE Я пытался обернуть весь вид и установив его на OnClick слушателя Все остальное умеет слушать OnClick, за исключением холста Почему холст игнорируя OnClick события? есть ли способ обойти это?

Я думал, что способ обмануть это, который должен использовать SharedPref для передачи информации между обоими классами. Но я надеюсь, что это будет последняя альтернатива.

ответ

1

сделать следующий :

/** 
* @author Sergey Shustikov ([email protected]) 
*/ 
public class PaintSurface implements View.OnTouchListener { 

    private List<View.OnTouchListener> mOnTouchListenerList = new ArrayList<>(); 


    public void addOnTouchListener(View.OnTouchListener listener) { 
     mOnTouchListenerList.add(listener); 
    } 

    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     for (View.OnTouchListener listener : mOnTouchListenerList) { 
      listener.onTouch(v, event); 
     } 
     return true; 
    } 
} 

Использование:

// Paint a circle when touched 
mPaintSurface.addOnTouchListener(mPaintSurface); 
// Get coordinates when touched 
mPaintSurface.addOnTouchListener(new OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       if(event.getAction() == MotionEvent.ACTION_UP){ 
        // Do what you want 
        Log.d("Fragment_Point", "X: "+mPaintSurface.getRelativeXpos()+" Y: "+mPaintSurface.getRelativeYpos()); 
        return true; 
       } 
       return false; 
      } 
     }); 

если вы хотите отказаться от некоторых сенсорный заменить

@Override 
    public boolean onTouch(View v, MotionEvent event) { 
     for (View.OnTouchListener listener : mOnTouchListenerList) { 
      listener.onTouch(v, event); 
     } 
     return true; 
    } 

в

@Override 
    public boolean onTouch(View v, MotionEvent event) { 
     for (View.OnTouchListener listener : mOnTouchListenerList) { 
      if(!listener.onTouch(v, event))return false; 
     } 
     return true; 
    } 
+0

Это выглядит хорошо. Я попробую это скоро. Благодарю. (: – holyxiaoxin

+0

Но я сомневаюсь, что это сработает после второго взгляда, проблема в том, что пользовательский вид холста не регистрирует событие касания, тогда как другие части представления делают. – holyxiaoxin

+0

Я взял ваш код, изменил 'mPaintSurface.addOnTouchListener (mPaintSurface), 'to' mPaintSurface.setOnTouchListener (mPaintSurface); 'и добавление моих предыдущих реализаций поверх onTouch в PaintSurface, и это сработало. Спасибо! (: – holyxiaoxin