View->可拖拽滑动的ImagaView

XML文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center">
    <com.gallery20.app.MyImageView
        android:id="@+id/real_iv"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_marginTop="30dp"
        android:layout_marginBottom="30dp"
        android:layout_marginLeft="30dp"
        android:layout_marginRight="30dp"
        android:background="#00000000"/>
</LinearLayout>

Activity代码

const val TAG = "Yang"
class MainActivity : AppCompatActivity() {
    var mRealView: MyImageView? = null
    var tempBitmap: Bitmap? = null
    var screenWidth = 0
    var screenHeight = 0
    var mDestRect = RectF()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mRealView = findViewById(R.id.real_iv)
        // 屏幕宽高的一半作为临时RectF, 用于压缩Bitmap
        screenWidth = resources.displayMetrics.widthPixels
        screenHeight = resources.displayMetrics.heightPixels
        val tempRect = RectF(0f, 0f, screenWidth.toFloat() / 2, screenHeight.toFloat() / 2)


        CoroutineScope(Dispatchers.IO).launch {
            tempBitmap = getBitmap(resources, tempRect, R.drawable.fake)
            withContext(Dispatchers.Main) {
                mRealView?.setImageBitmap(tempBitmap)
            }
        }
    }
}
fun getBitmap(resources : Resources, destRect : RectF, imageId: Int): Bitmap? {
    var imageWidth = -1
    var imageHeight = -1
    val preOption = BitmapFactory.Options().apply {
        // 只获取图片的宽高
        inJustDecodeBounds = true
        BitmapFactory.decodeResource(resources, imageId, this)
    }
    imageWidth = preOption.outWidth
    imageHeight = preOption.outHeight
    // 计算缩放比例
    val scaleMatrix = Matrix()
    // 确定未缩放Bitmap的RectF
    var srcRect = RectF(0f, 0f, imageWidth.toFloat(), imageHeight.toFloat())
    // 通过目标RectF, 确定缩放数值,存储在scaleMatrix中
    scaleMatrix.setRectToRect(srcRect, destRect, Matrix.ScaleToFit.CENTER)
    // 缩放数值再映射到原始Bitmap上,得到缩放后的RectF
    scaleMatrix.mapRect(srcRect)

    val finalOption = BitmapFactory.Options().apply {
        if (imageHeight > 0 && imageWidth > 0) {
            inPreferredConfig = Bitmap.Config.ARGB_8888
            inSampleSize = calculateInSampleSize(
                imageWidth,
                imageHeight,
                srcRect.width().toInt(),
                srcRect.height().toInt()
            )
        }
    }
    return BitmapFactory.decodeResource(resources, imageId, finalOption)
}

fun calculateInSampleSize(fromWidth: Int, fromHeight: Int, toWidth: Int, toHeight: Int): Int {
    var bitmapWidth = fromWidth
    var bitmapHeight = fromHeight
    if (fromWidth > toWidth|| fromHeight > toHeight) {
        var inSampleSize = 1
        // 计算最大的inSampleSize值,该值是2的幂,并保持原始宽高大于目标宽高
        while (bitmapWidth >= toWidth && bitmapHeight >= toHeight) {
            bitmapWidth /= 2
            bitmapHeight /= 2
            inSampleSize *= 2
        }
        return inSampleSize 
    }
    return 1
}

自定义View代码

class MyImageView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr){

    private var lastX = 0f
    private var lastY = 0f
    
    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                lastX = event.rawX
                lastY = event.rawY
            }
            MotionEvent.ACTION_MOVE -> {
                // 计算移动的水平和垂直方向的距离
                val dx = event.rawX - lastX
                val dy = event.rawY - lastY
                // 修改View的布局参数
                val left = left + dx.toInt()
                val top = top + dy.toInt()
                val right = right + dx.toInt()
                val bottom = bottom + dy.toInt()
                // 重新布局绘制
                layout(left, top, right, bottom)
                lastX = event.rawX
                lastY = event.rawY
            }
        }
        return true
    }
}
  • event.xevent.y 返回的是触摸点相对于当前View左上角(0, 0)的坐标, event.rawXevent.rawY 返回的是触摸位置相对于整个屏幕左上角的坐标
  • ACTION_DOWNACTION_MOVE事件中使用event.rawXevent.rawY 计算的水平和垂直方向移动的距离是相对整个屏幕左上角的移动距离,以整个屏幕为参照系,用于需要以屏幕为基准进行操作的情况,比如移动或者拖拽一个View
  • ACTION_DOWNACTION_MOVE事件中使用event.Xevent.Y 计算的水平和垂直方向移动的距离是相对当前View左上角(0, 0)的移动距离,以当前View为参照系,用于在固定不移动的View内部进行操作,比如处理一个ViewGroup的里某个View的旋转、平移、缩放

效果图

-

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值