繁体   English   中英

OnTouchListener在画布上不起作用

[英]OnTouchListener not working on canvas

我需要:

  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,结果相同。 也许我听错了触摸监听器,但是为什么一个触摸监听器正在工作而另一个却不能呢? 感谢您的任何提示。 (:

更新我试图包装整个视图并将其设置为onclick侦听器。 除了画布,其他所有内容都可以监听onclick。 为什么画布忽略onclick事件? 有没有办法绕过这个?

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

接下来:

/**
 * @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;
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM