Android图片涂鸦,Kotlin(1)
Kotlin
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.graphics.PointF
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import androidx.appcompat.widget.AppCompatImageView
class PaintView @JvmOverloads constructor(
context: Context?,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : AppCompatImageView(context!!, attrs, defStyleAttr) {
class DrawPath {
var id: Long = 0L
var path: Path? = null
var paint: Paint? = null
var points = ArrayList<PointF>()
}
private var mPaint: Paint? = null
private var mPath: Path? = null
private var mDownX = 0f
private var mDownY = 0f
private var mTempX = 0f
private var mTempY = 0f
//默认的画笔宽度
private var mPaintWidth = 10
//默认画笔的颜色
private var mColor = Color.RED
private val mDrawPathList: ArrayList<DrawPath>?
private val mSavePathList: ArrayList<DrawPath>?
companion object {
var WIDTH_INCREMENT = 15
const val TAG = "PaintView"
}
init {
mDrawPathList = ArrayList()
mSavePathList = ArrayList()
initPaint()
}
private fun initPaint() {
mPaint = Paint()
mPaint?.color = mColor
mPaint?.isAntiAlias = true
mPaint?.strokeWidth = mPaintWidth.toFloat()
mPaint?.style = Paint.Style.STROKE
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
if (!mDrawPathList.isNullOrEmpty()) {
for (drawPath in mDrawPathList) {
if (drawPath.path != null) {
canvas.drawPath(drawPath.path!!, drawPath.paint!!)
}
drawPath.points.forEach {
Log.d(TAG, "onDraw ${drawPath.id} ${it.x} ${it.y}")
}
}
}
}
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
Log.d(TAG, "ACTION_DOWN ${event.x} ${event.y}")
mDownX = event.x
mDownY = event.y
//每次手指点下去作为一条新路径。
mPath = Path()
mPath?.moveTo(mDownX, mDownY)
val drawPath = DrawPath()
drawPath.id = System.currentTimeMillis()
drawPath.paint = mPaint
drawPath.path = mPath
mDrawPathList?.add(drawPath)
//新一轮绘制开始,保存点。
drawPath.points.add(PointF(event.x, event.y))
invalidate()
mTempX = mDownX
mTempY = mDownY
}
MotionEvent.ACTION_MOVE -> {
//Log.d(TAG, "ACTION_MOVE ${event.x} ${event.y}")
val moveX = event.x
val moveY = event.y
mPath?.quadTo(mTempX, mTempY, moveX, moveY)
mDrawPathList?.filter {
it.path == mPath
}?.forEach {
it.points.add(PointF(event.x, event.y))
}
invalidate()
mTempX = moveX
mTempY = moveY
}
//每次手指抬起重置画笔,不然画笔会保存之前设置的属性会引起bug。
MotionEvent.ACTION_UP -> {
Log.d(TAG, "ACTION_UP ${event.x} ${event.y}")
initPaint()
}
}
return true
}
/**
* 撤销。
*/
fun undo() {
if (mDrawPathList != null && mDrawPathList.size >= 1) {
mSavePathList?.add(mDrawPathList[mDrawPathList.size - 1])
mDrawPathList.removeAt(mDrawPathList.size - 1)
invalidate()
}
}
/**
* 反撤销,重新生效。
*/
fun reundo() {
if (!mSavePathList.isNullOrEmpty()) {
mDrawPathList?.add(mSavePathList[mSavePathList.size - 1])
mSavePathList.removeAt(mSavePathList.size - 1)
invalidate()
}
}
/**
* 画笔颜色。
*
* @param color
*/
fun setPaintColor(color: Int) {
this.mColor = color
mPaint?.color = this.mColor
}
/**
* 画笔的宽度。
*/
fun setPaintWidth(size: Int) {
mPaintWidth += size
mPaint?.strokeWidth = mPaintWidth.toFloat()
}
/**
* 放大,改变画笔的宽度。线条变粗。
*/
fun enlargePaintWidth() {
mPaintWidth += WIDTH_INCREMENT
mPaint?.strokeWidth = mPaintWidth.toFloat()
}
fun getDrawPath(): ArrayList<DrawPath>? {
return mDrawPathList
}
}
XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.pkg1115.PaintView
android:id="@+id/paint_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
android:src="@mipmap/p1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<RelativeLayout
android:id="@+id/rl_left"
android:layout_width="100dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<Button
android:id="@+id/btn_undo"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="撤销" />
<Button
android:id="@+id/btn_red"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_below="@id/btn_undo"
android:text="红色" />
<Button
android:id="@+id/btn_green"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_below="@id/btn_red"
android:text="绿色" />
<Button
android:id="@+id/btn_enlarge"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_below="@id/btn_green"
android:text="放大" />
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>