如何在WebView中绘制Canvas?
How to draw Canvas in WebView?
我正在制作一个应用程序,人们可以在其中将圆圈放置在 WebView 中。所以我的
算法是:
- 检测长按
- 在 WebView 上获取手指坐标
- 在Canvas
中画圆
所以起初我能够编写一个代码在 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);
}
}
我正在制作一个应用程序,人们可以在其中将圆圈放置在 WebView 中。所以我的 算法是:
- 检测长按
- 在 WebView 上获取手指坐标
- 在Canvas 中画圆
所以起初我能够编写一个代码在 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);
}
}