简体   繁体   English

OnTouchListener在画布上不起作用

[英]OnTouchListener not working on canvas

I need to: 我需要:

  1. Paint a circle and 画一个圆圈
  2. get the coordinates on the point 得到该点的坐标

where my finger is touching the view. 我的手指触摸视图的位置。

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

}

There are 2 on touch listeners to perform this action. 有2个触摸监听器可以执行此操作。 The first touchlistener is working (paints the circle on the point I touch). 第一个触摸侦听器正在工作(在我触摸的点上绘制圆圈)。 However, the second touch listeners that tries to listen to touch events on the custom view doesn't work (No logging when touched). 但是,尝试在自定义视图上监听触摸事件的第二个触摸监听器不起作用(触摸时不记录日志)。 OnTouch only works inside Paint Surface custom view but not inside my fragment anymore. OnTouch仅在Paint Surface自定义视图中起作用,而在我的片段中不再起作用。

*I need a way to extract the coordinates that is touching on the canvas to my fragments. *我需要一种将画布上接触的坐标提取到片段的方法。

I've also tried onClickListeners, same results. 我也尝试过onClickListeners,结果相同。 Maybe I've understood touchlisteners wrongly, but why is it that one touchlistener is working but the other isn't? 也许我听错了触摸监听器,但是为什么一个触摸监听器正在工作而另一个却不能呢? Thanks for any hints. 感谢您的任何提示。 (: (:

UPDATE I've tried to wrap the entire view and setting it to an onclick listener. 更新我试图包装整个视图并将其设置为onclick侦听器。 Everything else is able to listen for onclick, except for the canvas. 除了画布,其他所有内容都可以监听onclick。 Why is the canvas ignoring onclick events? 为什么画布忽略onclick事件? Is there a way to bypass this? 有没有办法绕过这个?

I've thought a way to cheat this, which is to use SharedPref to pass information between both classes. 我想过一种作弊的方法,就是使用SharedPref在两个类之间传递信息。 But I hope that this would be the final alternative. 但是我希望这将是最终的选择。

Make next : 接下来:

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

Usage : 用法:

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

if you want to reject some touch replace 如果您想拒绝触摸更换

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

to

    @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