如何在WebView中绘制Canvas?

How to draw Canvas in WebView?

我正在制作一个应用程序,人们可以在其中将圆圈放置在 WebView 中。所以我的 算法是:

  1. 检测长按
  2. 在 WebView 上获取手指坐标
  3. 在Canvas
  4. 中画圆

所以起初我能够编写一个代码在 LongClick 上画一个圆圈,唯一的问题是当我改变比例(缩放)时,圆圈从它的位置移动了。在 karaokyo 回答的帮助下,我通过添加 scale float Canvas.drawCircle(x * scale, y * scale, 10, p),其中 scale = getScale() 解决了这个移动问题)。 不幸的是,新问题出现了——当我画圆时,它画出了错误的坐标。这张图片显示了我的意思:

public DrawWebView (Context context, AttributeSet attrs)
{
    super (context, attrs);
    wv1 = (DrawWebView) findViewById(R.id.webView1);
    wv1.loadUrl("file://" + Environment.getExternalStorageDirectory() + "/Pictures/ScolDetectPics/boxes.jpg");
    wv1.getSettings().setBuiltInZoomControls(true);
    wv1.getSettings().setDisplayZoomControls(false);
    wv1.getSettings().setSupportZoom(true);
    wv1.getSettings().setUseWideViewPort(true);
    wv1.getSettings().setLoadWithOverviewMode(true); 
    wv1.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);
    mContext = context;





public boolean onTouch(View v, MotionEvent event) {

    int action = event.getAction(); 


    switch (action) { 
    case MotionEvent.ACTION_DOWN:
        draw = true;
        this.invalidate();
        break;
    case MotionEvent.ACTION_MOVE:   
        this.invalidate();
        break;

    case MotionEvent.ACTION_UP: 
        this.invalidate();
        break;
    case MotionEvent.ACTION_CANCEL:

        break; 

    default: 
        break; 
    }
    return true;
}


@Override
protected void onDraw(Canvas canvas) 
{

    super.onDraw (canvas);
    text = MainActivity.text;

    zoomPos = MainActivity.zoomPos;
    Paint p = new Paint();
    p.setColor (Color.RED);

    if(initScale == 0){
        initScale = getScale();
    }

    float scale = getScale();

    float refScale = scale/initScale;

    if(MainActivity.drawConfirm){
    zoomPos = MainActivity.zoomPos;
    draw1 = true;
    }
    canvas.drawCircle(330 * refScale, 618 * refScale, 10, p);
    //text.setText(Float.toString(scale));
    text.setText(Float.toString(initScale));
    canvas.drawCircle(330, 618, 10, p);
    if(draw1){
    canvas.drawCircle(zoomPos.x * refScale, zoomPos.y * refScale, 10, p);
    }

}

}

此外,如果我多次双击圆圈(两个)出现在错误的位置,请在我单击时移动到正确的位置。

如果您知道如何执行此操作或知道好的教程 - 将不胜感激。

[karaokyo 的回答更新]

我已经复制了你的代码,但是圆圈还是在错误的地方,事实上,initialScale 值是 2.0。在这张图片上可以清楚地看到。 1. 有移动问题但坐标正确的圆。 2.圆圈不动问题,坐标乘以scale = getScale。 3.圆圈不动问题,坐标乘以scale/initScale

要解决圆圈移动问题,您必须根据 WebView 的缩放比例调整坐标。对于长按,设置一个 GestureDetector 保存点击位置和当前比例 onLongPress 以在你的 onDraw:

中使用
public class DrawWebView extends WebView {
    private GestureDetector mDetector;
    private float mInitialScale;
    private int mX;
    private int mY;

    public DrawWebView(Context context) {
        super(context);
        init();
    }

    public DrawWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public DrawWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public void init(){
        loadUrl("file://" + Environment.getExternalStorageDirectory() + "/Pictures/boxes.jpg");
        setWebViewClient(new WebViewClient());
        getSettings().setBuiltInZoomControls(true);
        getSettings().setDisplayZoomControls(false);
        getSettings().setSupportZoom(true);
        getSettings().setUseWideViewPort(true);
        getSettings().setLoadWithOverviewMode(true);
        getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);

        mDetector = new GestureDetector(getContext(), new GestureDetector.OnGestureListener() {
            @Override
            public boolean onDown(MotionEvent e) {
                return false;
            }

            @Override
            public void onShowPress(MotionEvent e) {

            }

            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return false;
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                return false;
            }

            @Override
            public void onLongPress(MotionEvent e) {
                mX = (int) e.getX() + getScrollX();
                mY = (int) e.getY() + getScrollY();
                mInitialScale = getScale();
            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                return false;
            }
        });

        setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return mDetector.onTouchEvent(event);
            }
        });
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw (canvas);

        float scale = getScale() / mInitialScale;

        Paint p = new Paint();

        p.setColor(Color.RED);
        canvas.drawCircle(mX * scale, mY * scale, 10, p);

        p.setColor(Color.GREEN);
        canvas.drawCircle(mX, mY, 5, p);
    }
}