一个跟随手指滑动的图片 -- 单点触摸

本篇为系列文章
一个跟随手指滑动的图片 – 单点触摸
自定义 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 的效果

猜你喜欢

转载自blog.csdn.net/qq_35178391/article/details/132694395