平滑的手写签名View
来源:互联网 发布:jenkins windows 编辑:程序博客网 时间:2024/05/17 09:38
无意中看到了square的一位android工程师写的自定义签名View,链接:https://corner.squareup.com/2010/07/smooth-signatures.html ;
阅读完以后了解到:
Android 对点击事件是批处理的,所以系统在每次调用onTouchEvent() 的时候,
MotionEvent
里面都包含了坐标位置的历史记录
要想绘制平滑的签名,需要用到下面的几个方法
getHistorySize() // 仅使用于两个 ACTION_MOVE事件之间 ,其它触摸事件返回值为0
getHistoricalX(int) // 根据size 可以获取每个点的X值
getHistoricalY(int) // 根据size 可以获取每个点的y值
这样用path把所有的 坐标串联起来, 就可以绘制平滑的签名了;
// ================================ 一般的效果以及代码========================================
public class SignatureView extends View { private Paint paint = new Paint(); private Path path = new Path(); public SignatureView(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(5f); } @Override protected void onDraw(Canvas canvas) { canvas.drawPath(path, paint); } @Override public boolean onTouchEvent(MotionEvent event) { float eventX = event.getX(); float eventY = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: path.moveTo(eventX, eventY); return true; case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_UP: path.lineTo(eventX, eventY); break; default: return false; } // Schedules a repaint. invalidate(); return true; }}
// ================================ 最终的效果以及完全代码========================================
public class SignatureView extends View { private static final float STROKE_WIDTH = 5f; /** Need to track this so the dirty region can accommodate the stroke. **/ private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2; private Paint paint = new Paint(); private Path path = new Path(); /** * Optimizes painting by invalidating the smallest possible area. */ private float lastTouchX; private float lastTouchY; private final RectF dirtyRect = new RectF(); public SignatureView(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); } /** * Erases the signature. */ public void clear() { path.reset(); // Repaints the entire view. 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(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: path.moveTo(eventX, eventY); lastTouchX = eventX; lastTouchY = eventY; // There is no end point yet, so don't waste cycles invalidating. return true; case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_UP: // Start tracking the dirty region. resetDirtyRect(eventX, eventY); // When the hardware tracks events faster than they are delivered, the // event will contain a history of those skipped points. 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); } // After replaying history, connect the line to the touch point. path.lineTo(eventX, eventY); break; default: debug("Ignored touch event: " + event.toString()); return false; } // Include half the stroke width to avoid clipping. 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; } /** * Called when replaying history to ensure the dirty region includes all * points. */ 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; } } /** * Resets the dirty region when the motion event occurs. */ private void resetDirtyRect(float eventX, float eventY) { // The lastTouchX and lastTouchY were set when the ACTION_DOWN // motion event occurred. dirtyRect.left = Math.min(lastTouchX, eventX); dirtyRect.right = Math.max(lastTouchX, eventX); dirtyRect.top = Math.min(lastTouchY, eventY); dirtyRect.bottom = Math.max(lastTouchY, eventY); }}
0 0
- 平滑的手写签名View
- 【Android】手写优化-更为平滑的签名效果实现
- Android自定义View实现手写签名的功能
- Android 自定义View(手写签名)
- 手写签名
- Winform开发中手写签名的实现
- android 超简单的手写签名Demo
- iOS 手写签名的简单实用封装
- iOS 手写签名的简单实用封装
- Android应用中平滑的手写效果实现
- Android应用中平滑的手写效果实现
- Android应用中平滑的手写效果实现
- 保存手写签名
- 手势(手写)签名
- 手写电子签名板
- Android 手写签名 Demo
- Android自定义手写签名
- Android电子手写签名
- Java - Collection
- 中级题:二师弟的星际加法
- Android EditText清除光标
- Knuth-Morris-Pratt 字符串查找算法
- jsp page 提示[page] is not properly terminated
- 平滑的手写签名View
- 递归6_简单的0/1背包问题 去除相同的数
- Linux发行版制作总结
- 保存Activity的临时数据
- extern 与 attribute 的 hidden
- 对CardLayout和GridLayout的综合应用
- VB中列出10个数
- 程序bug导致了天大的损失,要枪毙程序猿吗?
- 一、关于Java循环中使用的临时变量定义在循环内、外的执行速度测试( Android )。