Android视图不响应绘制
Posted
技术标签:
【中文标题】Android视图不响应绘制【英文标题】:Android view doesn't respond to draw 【发布时间】:2013-12-02 07:03:07 【问题描述】:我目前正在尝试在 android 中使用我的第一个自定义视图,并一直尝试通过 onTouchEvent
在画布上绘制点,但多次尝试后都失败了。 View 确实检测到我的触摸并在触摸时成功打印出 System.out.println
消息,但它仍然没有在画布上绘制。
经过几次不同的尝试,这是我想出的:
package com.techdigy.testapp;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class DrawingBoard extends View
Canvas canvas;
Bitmap bmp;
BitmapDrawable temp;
public DrawingBoard(Context context, AttributeSet attributeSet)
super(context,attributeSet);
// TODO Auto-generated constructor stub
protected void onSizeChanged(int w, int h, int oldw, int oldh)
super.onSizeChanged(w, h, oldw, oldh);
bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
canvas = new Canvas();
protected void onDraw(Canvas canvas)
//draw view
public boolean onTouchEvent(MotionEvent event)
//detect user touch
float touchX = event.getX();
float touchY = event.getY();
Paint paint = new Paint();
System.out.println("test");
this.canvas.drawPoint(touchX, touchY, paint);
temp = new BitmapDrawable(this.bmp);
this.setBackground(this.temp);
invalidate();
return true;
【问题讨论】:
【参考方案1】:将此代码用于绘制点或画布上的任何东西...
public class signature extends View
private static final float STROKE_WIDTH = 5f;
private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2;
private Paint paint = new Paint();
private Path path = new Path();
private float lastTouchX;
private float lastTouchY;
private final RectF dirtyRect = new RectF();
public signature(Context context, AttributeSet attrs)
super(context, attrs);
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(STROKE_WIDTH);
public void save(View v)
Log.v("log_tag", "Width: " + v.getWidth());
Log.v("log_tag", "Height: " + v.getHeight());
if (mBitmap == null)
mBitmap = Bitmap.createBitmap(mContent.getWidth(),
mContent.getHeight(), Bitmap.Config.RGB_565);
;
Canvas canvas = new Canvas(mBitmap);
try
FileOutputStream mFileOutStream = new FileOutputStream(new File(Environment.getExternalStorageDirectory().toString()
, "sign.png"));
v.draw(canvas);
mBitmap.compress(Bitmap.CompressFormat.PNG, 90, mFileOutStream);
mFileOutStream.flush();
mFileOutStream.close();
String url = Images.Media.insertImage(getContentResolver(),
mBitmap, "title", null);
Log.v("log_tag", "url: " + url);
// In case you want to delete the file
// boolean deleted = mypath.delete();
// Log.v("log_tag","deleted: " + mypath.toString() + deleted);
// If you want to convert the image to string use base64
// converter
catch (Exception e)
Log.v("log_tag", e.toString());
public void clear()
path.reset();
invalidate();
@Override
protected void onDraw(Canvas canvas)
canvas.drawPath(path, paint);
@Override
public boolean onTouchEvent(MotionEvent event)
float eventX = event.getX();
float eventY = event.getY();
mGetSign.setEnabled(true);
switch (event.getAction())
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY);
lastTouchX = eventX;
lastTouchY = eventY;
return true;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
resetDirtyRect(eventX, eventY);
int historySize = event.getHistorySize();
for (int i = 0; i < historySize; i++)
float historicalX = event.getHistoricalX(i);
float historicalY = event.getHistoricalY(i);
expandDirtyRect(historicalX, historicalY);
path.lineTo(historicalX, historicalY);
path.lineTo(eventX, eventY);
break;
default:
debug("Ignored touch event: " + event.toString());
return false;
invalidate((int) (dirtyRect.left - HALF_STROKE_WIDTH),
(int) (dirtyRect.top - HALF_STROKE_WIDTH),
(int) (dirtyRect.right + HALF_STROKE_WIDTH),
(int) (dirtyRect.bottom + HALF_STROKE_WIDTH));
lastTouchX = eventX;
lastTouchY = eventY;
return true;
private void debug(String string)
private void expandDirtyRect(float historicalX, float historicalY)
if (historicalX < dirtyRect.left)
dirtyRect.left = historicalX;
else if (historicalX > dirtyRect.right)
dirtyRect.right = historicalX;
if (historicalY < dirtyRect.top)
dirtyRect.top = historicalY;
else if (historicalY > dirtyRect.bottom)
dirtyRect.bottom = historicalY;
private void resetDirtyRect(float eventX, float eventY)
dirtyRect.left = Math.min(lastTouchX, eventX);
dirtyRect.right = Math.max(lastTouchX, eventX);
dirtyRect.top = Math.min(lastTouchY, eventY);
dirtyRect.bottom = Math.max(lastTouchY, eventY);
【讨论】:
【参考方案2】:试试这个...
public class DrawingBoard extends View
private Bitmap bmp;
private float touchX;
private float touchY;
private Paint paint;
public DrawingBoard(Context context, AttributeSet attributeSet)
super(context, attributeSet);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
protected void onSizeChanged(int w, int h, int oldw, int oldh)
super.onSizeChanged(w, h, oldw, oldh);
bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
setBackgroundDrawable(new BitmapDrawable(getResources(), bmp));
protected void onDraw(Canvas canvas)
super.onDraw(canvas);
canvas.drawPoint(touchX, touchY, paint);
public boolean onTouchEvent(MotionEvent event)
// detect user touch
touchX = event.getX();
touchY = event.getY();
System.out.println("test");
invalidate();
return true;
【讨论】:
感谢您的帮助。这有效,但只是暂时保留该值,当您单击其他位置时,它会被移动。还有关于我在原始代码中做错了什么的任何想法? 您正在创建的画布上绘制点。此画布与视图无关。当您想绘制任何东西时,请在 onDraw() 方法中作为参数获取的画布上绘制以上是关于Android视图不响应绘制的主要内容,如果未能解决你的问题,请参考以下文章
MFC 对话框中的 QWinWidget 不重新绘制或响应 Tab/箭头键