一个跟随手指滑动的图片 -- 单点触摸
本篇为系列文章
一个跟随手指滑动的图片 – 单点触摸
自定义 View:多点触控 (一)— 手指接力
自定义View:多点触控(二)— 多指协作
自定义 View:多点触控 (三)— 各自为战
首先,先创建一个view
import android.content.Context
import android.util.AttributeSet
import android.view.View
class DragView(context: Context, attrs: AttributeSet?) : View(context, attrs) {
}
实现一个自定义的图片绘制,直接重写 onDraw() 方法,使用 drawBitmap 来绘制一个图片
import android.content.Context
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
import com.example.viewtest.R
class DragView(context: Context, attrs: AttributeSet?) : View(context, attrs) {
private val bitmap = BitmapFactory.decodeResource(resources, R.drawable.ic_launcher_foreground)
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
canvas?.drawBitmap(bitmap, 0f, 0f, paint)
}
}
xml中使用我们定义的 view
<?xml version="1.0" encoding="utf-8"?>
<com.example.viewtest.view.DragView 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" />
这个时候就完成了一个图片出现在左上角的操作
然后我们需要在移动事件中去时时更新我们的图片位置,就可以实现一个图片随手指拖动的效果了
import android.content.Context
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.example.viewtest.R
class DragView(context: Context, attrs: AttributeSet?) : View(context, attrs) {
private val bitmap = BitmapFactory.decodeResource(resources, R.drawable.ic_launcher_foreground)
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
private var offsetX = 0f
private var offsetY = 0f
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
// 绘制时候使用更新后的坐标
canvas?.drawBitmap(bitmap, offsetX, offsetY, paint)
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
when(event?.action) {
MotionEvent.ACTION_MOVE -> {
// 记录最新的手指位置
offsetX = event.x
offsetY = event.y
// 触发重绘
invalidate()
}
}
return true
}
}
在上面代码中,我们在移动事件中,将移动的坐标实时保存在变量当中,然后触发重绘,在绘制方法中,也配合使用更改后的坐标变量
这样我们就实现了一个随手指移动的view效果
但是实际运行中会发现,拖动刚开始会闪一下,而且总是图片的左上角在我们手指的位置跟随手指移动,而不是我们按下的位置跟随手指移动。
这是因为我们的手指坐标传递给的是图片的左上角,如果要实现按下的位置跟随手指移动,
图片的左上角应该向左移动我们按下的距离和到左边的距离差,并且向上移动我们按下的距离和到上面的距离差
所以说我们要记录下按下的坐标,在移动的时候减掉
import android.content.Context
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.example.viewtest.R
class DragView(context: Context, attrs: AttributeSet?) : View(context, attrs) {
private val bitmap = BitmapFactory.decodeResource(resources, R.drawable.ic_launcher_foreground)
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
private var offsetX = 0f
private var offsetY = 0f
private var downX = 0f
private var downY = 0f
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
// 绘制时候使用更新后的坐标
canvas?.drawBitmap(bitmap, offsetX, offsetY, paint)
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
when(event?.action) {
MotionEvent.ACTION_DOWN -> {
// 记录手指按下的坐标
downX = event.x
downY = event.y
}
MotionEvent.ACTION_MOVE -> {
// 记录最新的手指位置
offsetX = event.x - downX
offsetY = event.y - downY
// 触发重绘
invalidate()
}
}
return true
}
}
运行以上代码,会发现在第二次进行拖动操作的时候,图片会跳到左上角,开始跟随手指移动,并不是从上一次拖动的结束位置继续的,所以说我们还要计算下结束时的位置,在移动的时候加上上次的位置,可以在抬起时计算结束时的位置,也可以在下次按下时计算,这里选择在按下时计算,方便后续讲多指操作时候的理解
import android.content.Context
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.example.viewtest.R
class DragView(context: Context, attrs: AttributeSet?) : View(context, attrs) {
private val bitmap = BitmapFactory.decodeResource(resources, R.drawable.ic_choice_select)
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
private var offsetX = 0f
private var offsetY = 0f
private var downX = 0f
private var downY = 0f
private var originOffsetX = 0f
private var originOffsetY = 0f
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
// 绘制时候使用更新后的坐标
canvas?.drawBitmap(bitmap, offsetX, offsetY, paint)
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
when (event?.action) {
MotionEvent.ACTION_DOWN -> {
// 记录手指按下的坐标
downX = event.x
downY = event.y
originOffsetX = offsetX
originOffsetY = offsetY
}
MotionEvent.ACTION_MOVE -> {
// 记录最新的手指位置
offsetX = event.x - downX + originOffsetX
offsetY = event.y - downY + originOffsetY
// 触发重绘
invalidate()
}
}
return true
}
}
好了,以上上最重代码,实现了一个随手指移动的 View 的效果
还没有评论,来说两句吧...