OnTouchListener不在canvas上工作

时间:2015-03-08 10:37:07

标签: android android-canvas ontouchlistener

我需要:

  1. 画一个圆圈
  2. 获取点上的坐标
  3. 我的手指触摸视图。

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

    有两个触控侦听器可以执行此操作。第一个touchlistener正在工作(在我触摸的点上绘制圆圈)。但是,尝试在自定义视图上侦听触摸事件的第二个触摸侦听器不起作用(触摸时不记录)。 OnTouch仅适用于Paint Surface自定义视图,但不再在我的片段内部。

    *我需要一种方法来将画布上触摸的坐标提取到我的片段。

    我也试过onClickListeners,结果相同。也许我错误地理解了touchlisteners,但为什么一个touchlistener正在工作但另一个不是?谢谢你的任何提示。 (:

    更新 我试图包装整个视图并将其设置为onclick监听器。除画布外,其他所有东西都能听到onclick。为什么画布忽略onclick事件?有没有办法绕过这个?

    我想过一种欺骗这种方法的方法,即使用SharedPref在两个类之间传递信息。但我希望这将是最后的选择。

1 个答案:

答案 0 :(得分:1)

下一步:

/**
 * @author Sergey Shustikov (pandarium.shustikov@gmail.com)
 */
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;
    }