Android 将手指绘画应用于我自己的视图
我有一个自定义视图,我想对其应用手指绘制。我如何做到这一点 我自己的视图是210x170像素,我想用手指在其中绘制 我真的很困惑如何做到这一点 请尝试以下代码:Android 将手指绘画应用于我自己的视图,android,canvas,paint,android-custom-view,Android,Canvas,Paint,Android Custom View,我有一个自定义视图,我想对其应用手指绘制。我如何做到这一点 我自己的视图是210x170像素,我想用手指在其中绘制 我真的很困惑如何做到这一点 请尝试以下代码: public class SignatureView extends View { private final String LOG_TAG = this.getClass().getSimpleName(); private float mSignatureWidth = 20f; //YOU CAN CHANGE
public class SignatureView extends View
{
private final String LOG_TAG = this.getClass().getSimpleName();
private float mSignatureWidth = 20f; //YOU CAN CHANGE SIZE OF LINE
private int mSignatureColor = Color.rgb(00, 119, 204); // SET RGB COLOR
private boolean mCapturing = true;
private Bitmap mSignature = null;
private static final boolean GESTURE_RENDERING_ANTIALIAS = true;
private static final boolean DITHER_FLAG = true;
private Paint mPaint = new Paint();
private Path mPath = new Path();
private final Rect mInvalidRect = new Rect();
private float mX;
private float mY;
private float mCurveEndX;
private float mCurveEndY;
private int mInvalidateExtraBorder = 10;
public SignatureView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public SignatureView(Context context) {
super(context);
init();
}
public SignatureView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setWillNotDraw(false);
mPaint.setAntiAlias(GESTURE_RENDERING_ANTIALIAS);
mPaint.setColor(mSignatureColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(mSignatureWidth);
mPaint.setDither(DITHER_FLAG);
mPath.reset();
}
@Override
protected void onDraw(Canvas canvas) {
if (mSignature != null) {
canvas.drawBitmap(mSignature, null, new Rect(0, 0, getWidth(),getHeight()), null);
} else {
canvas.drawPath(mPath, mPaint);
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (mCapturing) {
processEvent(event);
Log.d(VIEW_LOG_TAG, "dispatchTouchEvent");
return true;
} else {
return false;
}
}
private boolean processEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchDown(event);
invalidate();
return true;
case MotionEvent.ACTION_MOVE:
Rect rect = touchMove(event);
if (rect != null) {
invalidate(rect);
}
return true;
case MotionEvent.ACTION_UP:
touchUp(event, false);
invalidate();
return true;
case MotionEvent.ACTION_CANCEL:
touchUp(event, true);
invalidate();
return true;
}
return false;
}
private void touchUp(MotionEvent event, boolean b) {
// TODO Auto-generated method stub
}
private Rect touchMove(MotionEvent event) {
Rect areaToRefresh = null;
final float x = event.getX();
final float y = event.getY();
final float previousX = mX;
final float previousY = mY;
areaToRefresh = mInvalidRect;
// start with the curve end
final int border = mInvalidateExtraBorder;
areaToRefresh.set((int) mCurveEndX - border, (int) mCurveEndY - border,
(int) mCurveEndX + border, (int) mCurveEndY + border);
float cX = mCurveEndX = (x + previousX) / 2;
float cY = mCurveEndY = (y + previousY) / 2;
mPath.quadTo(previousX, previousY, cX, cY);
// union with the control point of the new curve
areaToRefresh.union((int) previousX - border, (int) previousY - border,
(int) previousX + border, (int) previousY + border);
// union with the end point of the new curve
areaToRefresh.union((int) cX - border, (int) cY - border, (int) cX
+ border, (int) cY + border);
mX = x;
mY = y;
return areaToRefresh;
}
private void touchDown(MotionEvent event) {
float x = event.getX();
float y = event.getY();
mX = x;
mY = y;
mPath.moveTo(x, y);
final int border = mInvalidateExtraBorder;
mInvalidRect.set((int) x - border, (int) y - border, (int) x + border,
(int) y + border);
mCurveEndX = x;
mCurveEndY = y;
}
/**
* Erases the signature.
*/
public void clear() {
mSignature = null;
mPath.rewind();
// Repaints the entire view.
invalidate();
}
public boolean isCapturing() {
return mCapturing;
}
public void setIsCapturing(boolean mCapturing) {
this.mCapturing = mCapturing;
}
public void setSignatureBitmap(Bitmap signature) {
mSignature = signature;
invalidate();
}
public Bitmap getSignatureBitmap() {
if (mSignature != null) {
return mSignature;
} else if (mPath.isEmpty()) {
return null;
} else {
Bitmap bmp = Bitmap.createBitmap(getWidth(), getHeight(),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bmp);
c.drawPath(mPath, mPaint);
return bmp;
}
}
public void setSignatureWidth(float width) {
mSignatureWidth = width;
mPaint.setStrokeWidth(mSignatureWidth);
invalidate();
}
public float getSignatureWidth() {
return mPaint.getStrokeWidth();
}
public void setSignatureColor(int color) {
mSignatureColor = color;
}
/**
* @return the byte array representing the signature as a PNG file format
*/
public byte[] getSignaturePNG() {
return getSignatureBytes(CompressFormat.PNG, 0);
}
/**
* @param quality
* Hint to the compressor, 0-100. 0 meaning compress for small
* size, 100 meaning compress for max quality.
* @return the byte array representing the signature as a JPEG file format
*/
public byte[] getSignatureJPEG(int quality) {
return getSignatureBytes(CompressFormat.JPEG, quality);
}
private byte[] getSignatureBytes(CompressFormat format, int quality) {
Log.d(LOG_TAG, "getSignatureBytes() path is empty: " + mPath.isEmpty());
Bitmap bmp = getSignatureBitmap();
if (bmp == null) {
return null;
} else {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
getSignatureBitmap().compress(format, quality, stream);
return stream.toByteArray();
}
}
}
在java代码中也使用此类,如:
SignatureView drawView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set full screen view
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
drawView = new SignatureView(this);
setContentView(drawView);
drawView.requestFocus();
}
希望这将对您有所帮助。请尝试以下代码:
public class SignatureView extends View
{
private final String LOG_TAG = this.getClass().getSimpleName();
private float mSignatureWidth = 20f; //YOU CAN CHANGE SIZE OF LINE
private int mSignatureColor = Color.rgb(00, 119, 204); // SET RGB COLOR
private boolean mCapturing = true;
private Bitmap mSignature = null;
private static final boolean GESTURE_RENDERING_ANTIALIAS = true;
private static final boolean DITHER_FLAG = true;
private Paint mPaint = new Paint();
private Path mPath = new Path();
private final Rect mInvalidRect = new Rect();
private float mX;
private float mY;
private float mCurveEndX;
private float mCurveEndY;
private int mInvalidateExtraBorder = 10;
public SignatureView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public SignatureView(Context context) {
super(context);
init();
}
public SignatureView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setWillNotDraw(false);
mPaint.setAntiAlias(GESTURE_RENDERING_ANTIALIAS);
mPaint.setColor(mSignatureColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(mSignatureWidth);
mPaint.setDither(DITHER_FLAG);
mPath.reset();
}
@Override
protected void onDraw(Canvas canvas) {
if (mSignature != null) {
canvas.drawBitmap(mSignature, null, new Rect(0, 0, getWidth(),getHeight()), null);
} else {
canvas.drawPath(mPath, mPaint);
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (mCapturing) {
processEvent(event);
Log.d(VIEW_LOG_TAG, "dispatchTouchEvent");
return true;
} else {
return false;
}
}
private boolean processEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchDown(event);
invalidate();
return true;
case MotionEvent.ACTION_MOVE:
Rect rect = touchMove(event);
if (rect != null) {
invalidate(rect);
}
return true;
case MotionEvent.ACTION_UP:
touchUp(event, false);
invalidate();
return true;
case MotionEvent.ACTION_CANCEL:
touchUp(event, true);
invalidate();
return true;
}
return false;
}
private void touchUp(MotionEvent event, boolean b) {
// TODO Auto-generated method stub
}
private Rect touchMove(MotionEvent event) {
Rect areaToRefresh = null;
final float x = event.getX();
final float y = event.getY();
final float previousX = mX;
final float previousY = mY;
areaToRefresh = mInvalidRect;
// start with the curve end
final int border = mInvalidateExtraBorder;
areaToRefresh.set((int) mCurveEndX - border, (int) mCurveEndY - border,
(int) mCurveEndX + border, (int) mCurveEndY + border);
float cX = mCurveEndX = (x + previousX) / 2;
float cY = mCurveEndY = (y + previousY) / 2;
mPath.quadTo(previousX, previousY, cX, cY);
// union with the control point of the new curve
areaToRefresh.union((int) previousX - border, (int) previousY - border,
(int) previousX + border, (int) previousY + border);
// union with the end point of the new curve
areaToRefresh.union((int) cX - border, (int) cY - border, (int) cX
+ border, (int) cY + border);
mX = x;
mY = y;
return areaToRefresh;
}
private void touchDown(MotionEvent event) {
float x = event.getX();
float y = event.getY();
mX = x;
mY = y;
mPath.moveTo(x, y);
final int border = mInvalidateExtraBorder;
mInvalidRect.set((int) x - border, (int) y - border, (int) x + border,
(int) y + border);
mCurveEndX = x;
mCurveEndY = y;
}
/**
* Erases the signature.
*/
public void clear() {
mSignature = null;
mPath.rewind();
// Repaints the entire view.
invalidate();
}
public boolean isCapturing() {
return mCapturing;
}
public void setIsCapturing(boolean mCapturing) {
this.mCapturing = mCapturing;
}
public void setSignatureBitmap(Bitmap signature) {
mSignature = signature;
invalidate();
}
public Bitmap getSignatureBitmap() {
if (mSignature != null) {
return mSignature;
} else if (mPath.isEmpty()) {
return null;
} else {
Bitmap bmp = Bitmap.createBitmap(getWidth(), getHeight(),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bmp);
c.drawPath(mPath, mPaint);
return bmp;
}
}
public void setSignatureWidth(float width) {
mSignatureWidth = width;
mPaint.setStrokeWidth(mSignatureWidth);
invalidate();
}
public float getSignatureWidth() {
return mPaint.getStrokeWidth();
}
public void setSignatureColor(int color) {
mSignatureColor = color;
}
/**
* @return the byte array representing the signature as a PNG file format
*/
public byte[] getSignaturePNG() {
return getSignatureBytes(CompressFormat.PNG, 0);
}
/**
* @param quality
* Hint to the compressor, 0-100. 0 meaning compress for small
* size, 100 meaning compress for max quality.
* @return the byte array representing the signature as a JPEG file format
*/
public byte[] getSignatureJPEG(int quality) {
return getSignatureBytes(CompressFormat.JPEG, quality);
}
private byte[] getSignatureBytes(CompressFormat format, int quality) {
Log.d(LOG_TAG, "getSignatureBytes() path is empty: " + mPath.isEmpty());
Bitmap bmp = getSignatureBitmap();
if (bmp == null) {
return null;
} else {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
getSignatureBitmap().compress(format, quality, stream);
return stream.toByteArray();
}
}
}
在java代码中也使用此类,如:
SignatureView drawView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set full screen view
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
drawView = new SignatureView(this);
setContentView(drawView);
drawView.requestFocus();
}
希望这能对您有所帮助。我的代码重点介绍了
onTouch
方法。视图
状态与缓存的位图一起保存在别处。触摸事件被写入保存位图的状态对象,位图被更新,然后更新的位图被写入View.onDraw
。另请注意对requestDisallowWinterCeptTouchEvent
的调用,否则如果屏幕当前允许滚动,触摸事件仍将尝试滚动屏幕。ImmutablePOint只是一个imutable Point类,因为当允许更改状态的点发生变化时,我在值的伸缩方面遇到了问题
hwr是类的实例,它可以记住点和笔划,可以撤消/重做并维护当前显示的一致位图
public boolean onTouchEvent(MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
this.getParent().requestDisallowInterceptTouchEvent(true);
this.hwr.addPoint(new ImmutablePoint((int) event.getX(), (int) event.getY()));
}
else if (event.getAction() == MotionEvent.ACTION_MOVE)
{
this.hwr.addPoint(new ImmutablePoint((int) event.getX(), (int) event.getY()));
}
else if (event.getAction() == MotionEvent.ACTION_UP)
{
this.getParent().requestDisallowInterceptTouchEvent(false);
this.hwr.stopDrawing(new ImmutablePoint((int) event.getX(), (int) event.getY()));
this.callback.pushStroke(this);
}
this.invalidate();
return true;
}
然后onDraw:
@Override
protected void onDraw(Canvas canvas)
{
// should already be the same size
canvas.drawBitmap(hwr.getDisplay(), matrix, paint);
}
我的代码关注的是onTouch
方法。视图
状态与缓存的位图一起保存在别处。触摸事件被写入保存位图的状态对象,位图被更新,然后更新的位图被写入View.onDraw
。另请注意对requestDisallowWinterCeptTouchEvent
的调用,否则如果屏幕当前允许滚动,触摸事件仍将尝试滚动屏幕。ImmutablePOint只是一个imutable Point类,因为当允许更改状态的点发生变化时,我在值的伸缩方面遇到了问题
hwr是类的实例,它可以记住点和笔划,可以撤消/重做并维护当前显示的一致位图
public boolean onTouchEvent(MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
this.getParent().requestDisallowInterceptTouchEvent(true);
this.hwr.addPoint(new ImmutablePoint((int) event.getX(), (int) event.getY()));
}
else if (event.getAction() == MotionEvent.ACTION_MOVE)
{
this.hwr.addPoint(new ImmutablePoint((int) event.getX(), (int) event.getY()));
}
else if (event.getAction() == MotionEvent.ACTION_UP)
{
this.getParent().requestDisallowInterceptTouchEvent(false);
this.hwr.stopDrawing(new ImmutablePoint((int) event.getX(), (int) event.getY()));
this.callback.pushStroke(this);
}
this.invalidate();
return true;
}
然后onDraw:
@Override
protected void onDraw(Canvas canvas)
{
// should already be the same size
canvas.drawBitmap(hwr.getDisplay(), matrix, paint);
}
@库玛和我已经把手指上的颜料弄出来了。问题是,我必须在特定布局的视图上执行此操作。对于如何实现这一目标,我没有找到解决办法this@kumaand我已经弄到手指油了。问题是,我必须在特定布局的视图上执行此操作。对于如何实现这一目标,我没有找到解决办法