直接上代码了:
/**
*
*@ClassName:GraphicsView
*@author:WYL
*@Date:2022/9/29
*/
class GraphicsView : View {
private var mWidth = 0
private var mHeight = 0
/**
* 圆的半径
*/
private var radius = 80f
//默认的点
private val graphicsPoints = mutableListOf<GraphicsPoint>()
//选中的点
private val checkGraphicsPoints = mutableListOf<GraphicsPoint>()
private val mPaint: Paint by lazy {
Paint(Paint.ANTI_ALIAS_FLAG).apply {
isAntiAlias = true
style = Paint.Style.FILL
isDither = true
}
}
private val linePaint: Paint by lazy {
Paint(Paint.ANTI_ALIAS_FLAG).apply {
isAntiAlias = true
style = Paint.Style.FILL
isDither = true
strokeWidth = 10f
mPaint.pathEffect = CornerPathEffect(10f)
color = Color.parseColor("#FF575E")
strokeCap = Paint.Cap.ROUND
}
}
constructor(context: Context?) : this(context, null)
constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
) {
init()
}
private fun init() {
graphicsPoints.clear()
graphicsPoints.add(GraphicsPoint(1))
graphicsPoints.add(GraphicsPoint(2))
graphicsPoints.add(GraphicsPoint(3))
graphicsPoints.add(GraphicsPoint(4))
graphicsPoints.add(GraphicsPoint(5))
graphicsPoints.add(GraphicsPoint(6))
graphicsPoints.add(GraphicsPoint(7))
graphicsPoints.add(GraphicsPoint(8))
graphicsPoints.add(GraphicsPoint(9))
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val width = MeasureSpec.getSize(widthMeasureSpec)
val height = MeasureSpec.getSize(heightMeasureSpec)
mWidth = Math.min(width, height)
mHeight = mWidth
setMeasuredDimension(mWidth, mHeight)
}
/**
* 选中颜色
*/
private val selectColor = Color.parseColor("#FF575E")
private val selectColorTransparent = Color.parseColor("#32FF575E")
private val unselectColor = Color.parseColor("#BCC6CE")
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
val averageWidth = mWidth / 3f
val averageHeight = mHeight / 3f
for (i in 0 until 3) {
for (j in 0 until 3) {
graphicsPoints[i * 3 + j].apply {
x = (averageWidth * (j + 1)) - averageWidth / 2f
y = (averageHeight * (i + 1)) - averageHeight / 2f
}
}
}
var startX = 0f
var startY = 0f
var stopX = 0f
var stopY = 0f
checkGraphicsPoints.forEachIndexed { index, it ->
if (index > 0) {
stopX = it.x
stopY = it.y
canvas?.drawLine(startX, startY, stopX, stopY, linePaint)
startX = stopX
startY = stopY
} else {
startX = it.x
startY = it.y
}
}
if (continueJudge) {
canvas?.drawLine(startX, startY, currentX, currentY, linePaint)
}
graphicsPoints.forEach {
if (it.isSelect) {
mPaint.color = selectColorTransparent
canvas?.drawCircle(it.x, it.y, radius, mPaint)
mPaint.color = selectColor
canvas?.drawCircle(it.x, it.y, radius/3, mPaint)
} else {
mPaint.color = unselectColor
canvas?.drawCircle(it.x, it.y, radius/3, mPaint)
}
}
}
/**
* 判断滑动时是否去判断
*/
private var continueJudge = false
private var currentX = 0f
private var currentY = 0f
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
graphicsPoints.forEach {
if (judgeCircle(it, event.x, event.y)) {
//Log.e(GraphicsView::class.java.canonicalName, "在圆点里面!!!!!!!!!!!!!")
continueJudge = true
it.isSelect = true
checkGraphicsPoints.add(it)
currentX = event.x
currentY = event.y
invalidate()
return@forEach
}
}
}
MotionEvent.ACTION_MOVE -> {
if (continueJudge) {
currentX = event.x
currentY = event.y
invalidate()
}
graphicsPoints.forEach {
if (judgeCircle(it, event.x, event.y) && !it.isSelect) {
//Log.e(GraphicsView::class.java.canonicalName, "在圆点里面!!!!!!!!!!!!!")
it.isSelect = true
checkGraphicsPoints.add(it)
if (!continueJudge) {
currentX = event.x
currentY = event.y
continueJudge = true
}
invalidate()
return@forEach
}
}
}
MotionEvent.ACTION_UP -> {
val selects = checkGraphicsPoints.filter { it.isSelect }
if(selects.isNotEmpty()){
val subString = StringBuffer()
selects.forEach {
subString.append("${it.type}")
}
//ToastUtils.showShort(subString)
onResultListener?.onResult(subString.toString())
}
continueJudge = false
checkGraphicsPoints.clear()
graphicsPoints.forEach {
it.isSelect = false
}
invalidate()
}
}
return true
}
/**
* 判断触点是否在圆里面
*/
fun judgeCircle(p: GraphicsPoint, m_x: Float, m_y: Float): Boolean {
val c = Math.pow(
Math.pow(
p.x.toDouble() - m_x.toDouble(),
2.0
) + Math.pow(p.y.toDouble() - m_y.toDouble(), 2.0), 0.5
)
return (c < radius)
}
inner class GraphicsPoint {
var x = 0f
var y = 0f
var type: Int = -1
var isSelect = false
constructor(x: Float, y: Float, type: Int) {
this.x = x
this.y = y
this.type = type
}
constructor(type: Int) {
this.type = type
}
}
var onResultListener:OnResultListener? = null
interface OnResultListener{
fun onResult(password:String)
}
}
效果图: