Created
June 18, 2019 09:39
-
-
Save seanghay/f992ee0f83f0e252d95268c06f5c492c to your computer and use it in GitHub Desktop.
PaintView
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class PaintView: View, View.OnTouchListener { | |
@ColorInt | |
var penColor: Int = Color.BLACK | |
@ColorInt | |
var paperColor: Int = Color.WHITE | |
var penSize: Int = 16f.dp.toInt() | |
private var bitmapSize = 0 to 0 | |
private val penPaint = Paint(ANTI_ALIAS_FLAG).also { | |
it.color = penColor | |
it.strokeCap = Paint.Cap.ROUND | |
it.style = Paint.Style.STROKE | |
it.strokeJoin = Paint.Join.MITER | |
it.strokeWidth = 4f | |
} | |
private val bitmapPaint = Paint(Paint.DITHER_FLAG) | |
private val penPath: Path = Path() | |
private var _dx: Float = 0f | |
private var _dy: Float = 0f | |
private lateinit var bitmap: Bitmap | |
private lateinit var bitmapCanvas: Canvas | |
constructor(context: Context): super(context) | |
constructor(context: Context, attributeSet: AttributeSet): super(context, attributeSet) | |
constructor(context: Context, attributeSet: AttributeSet, defStyle: Int): super(context, attributeSet, defStyle) | |
init { | |
setOnTouchListener(this) | |
setBackgroundColor(paperColor) | |
} | |
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { | |
super.onSizeChanged(w, h, oldw, oldh) | |
bitmapSize = w to h | |
clear() | |
} | |
fun clear() { | |
bitmap = Bitmap.createBitmap(bitmapSize.first, bitmapSize.second, Bitmap.Config.ARGB_8888) | |
bitmapCanvas = Canvas(bitmap) | |
invalidate() | |
} | |
fun saveAsImage(): Bitmap { | |
return Bitmap.createScaledBitmap(bitmap, bitmapSize.first, bitmapSize.second, true) | |
} | |
override fun onDraw(canvas: Canvas?) { | |
super.onDraw(canvas) | |
canvas ?: return | |
canvas.apply { | |
drawBitmap(bitmap, 0f, 0f, bitmapPaint) | |
drawPath(penPath, penPaint) | |
} | |
} | |
private fun touchMove(x: Float, y: Float) { | |
val dx = Math.abs(x - _dx) | |
val dy = Math.abs(y - _dy) | |
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { | |
penPath.quadTo(_dx, _dy, (x + _dx)/2, (y + _dy)/2) | |
_dx = x | |
_dy = y | |
} | |
} | |
private fun touchStart(x: Float, y: Float) { | |
with(penPath) { | |
reset() | |
moveTo(x, y) | |
} | |
_dx = x | |
_dy = y | |
} | |
private fun touchUp() { | |
penPath.lineTo(_dx, _dy) | |
bitmapCanvas.drawPath(penPath, penPaint) | |
penPath.reset() | |
} | |
override fun onTouch(v: View?, event: MotionEvent?): Boolean { | |
return when(event?.action) { | |
MotionEvent.ACTION_DOWN -> { | |
touchStart(event.x, event.y) | |
invalidate() | |
true | |
} | |
MotionEvent.ACTION_UP -> { | |
touchUp() | |
invalidate() | |
true | |
} | |
MotionEvent.ACTION_MOVE -> { | |
touchMove(event.x, event.y) | |
invalidate() | |
true | |
} | |
else -> false | |
} | |
} | |
private val Float.dp: Float get() | |
= TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, toFloat(), resources.displayMetrics) | |
companion object { | |
const val TOUCH_TOLERANCE = 4f | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment