Android矩阵Matrix动画缩放Bitmap移动手指触点到ImageView中心位置,Kotlin

news2025/3/13 7:24:17

Android矩阵Matrix动画缩放Bitmap移动手指触点到ImageView中心位置,Kotlin

 

 

 

借鉴 Android双指缩放ScaleGestureDetector检测放大因子大图移动到双指中心点ImageView区域中心,Kotlin(2)-CSDN博客 在此基础上实现手指在屏幕上点击后,动画放大图片,在放大过程中,移动手指触点位置到ImageView的中心。

 

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Matrix
import android.graphics.Paint
import android.graphics.RectF
import android.graphics.drawable.BitmapDrawable
import android.os.Bundle
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatImageView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch


class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

class MyImageView : AppCompatImageView {
    private var mCurX = 0f
    private var mCurY = 0f
    private var mCanDrawBitmap = false

    private var W = 0
    private var H = 0

    private val SCALE_FACTOR: Float = 5.5f
    private var mOriginBmp: Bitmap? = null

    private var mCirclePaint = Paint()

    private var mDeltaScaleFactor: Float = 0f
    private var mAnimScaleBmp: Bitmap? = null

    private var mCanDrawTouchPoint = false
    private var mTouchPointX = 0f
    private var mTouchPointY = 0f

    constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) {
        mCirclePaint.style = Paint.Style.STROKE
        mCirclePaint.strokeWidth = 10f
        mCirclePaint.isAntiAlias = true
        mCirclePaint.color = Color.RED

        mOriginBmp = (this.drawable as BitmapDrawable).bitmap
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)

        W = w
        H = h
        Log.d("fly", "W=$W H=$H")
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        if (event == null) {
            return false
        }

        mCurX = event.x
        mCurY = event.y

        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                //启动动画。
                startScaleAnim()
            }
        }

        return false
    }

    /**
     * Bitmap.createScaledBitmap耗时加剧卡顿。
     * 优化方案,基于原图setRectToRect缩放到给定宽w高h的放大图。
     */
    private fun getScaleBmp(w: Int, h: Int): Bitmap {
        val bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
        val c = Canvas(bmp)
        c.drawColor(Color.BLUE)

        val src = RectF(0f, 0f, mOriginBmp!!.width.toFloat(), mOriginBmp!!.height.toFloat())
        val dst = RectF(0f, 0f, w.toFloat(), h.toFloat())
        val mx = Matrix()
        mx.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER)
        c.drawBitmap(mOriginBmp!!, mx, null)

        return bmp
    }

    private fun startScaleAnim() {
        val step = 50f //经过step后,完成缩放动画。
        val delta = (SCALE_FACTOR - 1) / step

        CoroutineScope(Dispatchers.IO).launch {
            //绘制在原图上手的触点。
            mTouchPointX = mCurX
            mTouchPointY = mCurY
            mCanDrawTouchPoint = true
            myPostInvalidate()
            delay(500) //延时,观察手指触点。
            mCanDrawTouchPoint = false


            mCanDrawBitmap = true
            for (i in 0 until step.toInt()) {
                mDeltaScaleFactor = 1f + delta * i

                /*
                mAnimScaleBmp = Bitmap.createScaledBitmap(
                    mOriginBmp!!,
                    (W * mDeltaScaleFactor + 1).toInt(), //注意精度损失,造成坐标偏移。
                    (H * mDeltaScaleFactor + 1).toInt(),//注意精度损失,造成坐标偏移。
                    true
                )
                 */
                mAnimScaleBmp = getScaleBmp((W * mDeltaScaleFactor + 0.5).toInt(), (H * mDeltaScaleFactor + 0.5).toInt())

                //触发重绘。
                myPostInvalidate()
            }


            //for循环完成后,绘制最终图片动画放大完成后的中心圆点。
            mTouchPointX = W / 2f
            mTouchPointY = H / 2f
            mCanDrawTouchPoint = true
            myPostInvalidate()
        }
    }

    private fun myPostInvalidate() {
        this.postInvalidate()
    }

    private fun drawTouchPoint(c: Canvas) {
        c.drawCircle(mTouchPointX, mTouchPointY, 50f, mCirclePaint)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        if (mCanDrawBitmap) {
            val mx = Matrix()
            mx.setScale(mDeltaScaleFactor, mDeltaScaleFactor)
            mx.setTranslate(W / 2f - mCurX * mDeltaScaleFactor, H / 2f - mCurY * mDeltaScaleFactor)
            canvas.drawBitmap(mAnimScaleBmp!!, mx, null)
        }

        if (mCanDrawTouchPoint) {
            drawTouchPoint(canvas)
        }
    }
}

 

 

 

 

 

 

 

 

Android双指缩放ScaleGestureDetector检测放大因子大图移动到双指中心点ImageView区域中心,Kotlin(2)-CSDN博客文章浏览阅读613次,点赞4次,收藏5次。需要注意的,因为在xml布局里面特别设置了ImageView的高度为wrap_content,手指在屏幕触点的位置是放大镜里面放大图片后准确圆心位置,但是,如果ImageView设置成match_parent,则因为ImageView里面的Bitmap被缩放(此处Bitmap其实小于ImageView,被拉伸了),拉伸后的Bitmap水平方向坐标与ImageView一直重合,但竖直方向,Bitmap坐标与ImageView不一致,会造成一种现象,手指触点放大镜放大后,水平方向是正确的,但竖直方向有偏移量。https://blog.csdn.net/zhangphil/article/details/135701608Android矩阵setRectToRect裁剪Bitmap原图Matrix放大,mapRect标记中心区域,Kotlin-CSDN博客文章浏览阅读229次,点赞3次,收藏5次。【代码】Android矩阵setRectToRect裁剪Bitmap原图Matrix放大,mapRect标记中心区域,Kotlin。https://blog.csdn.net/zhangphil/article/details/135960921

Android ScaleGestureDetector检测双指缩放Bitmap基于Matrix动画移动到双指捏合中心点ImageView区域中心,Kotlin_android的两指捏合-CSDN博客文章浏览阅读256次,点赞5次,收藏11次。需要注意的,因为在xml布局里面特别设置了ImageView的高度为wrap_content,手指在屏幕触点的位置是放大镜里面放大图片后准确圆心位置,但是,如果ImageView设置成match_parent,则因为ImageView里面的Bitmap被缩放(此处Bitmap其实小于ImageView,被拉伸了),拉伸后的Bitmap水平方向坐标与ImageView一直重合,但竖直方向,Bitmap坐标与ImageView不一致,会造成一种现象,手指触点放大镜放大后,水平方向是正确的,但竖直方向有偏移量。_android的两指捏合https://blog.csdn.net/zhangphil/article/details/135705931

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1442212.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

物资捐赠管理系统

文章目录 物资捐赠管理系统一、项目演示二、项目介绍三、系统部分功能截图四、部分代码展示五、底部获取项目(9.9¥带走) 物资捐赠管理系统 一、项目演示 爱心捐赠系统 二、项目介绍 基于springboot的爱心捐赠管理系统 开发语言&#xff1a…

动态SQl简单创建

创建pojo实体类,使用lombok注解 package com.example.pojo;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;import java.time.LocalDate; import java.time.LocalDateTime;Data NoArgsConstructor AllArgsConstructor pu…

攻防世界——re2-cpp-is-awesome

64位 我先用虚拟机跑了一下这个程序,结果输出一串字符串flag ——没用 IDA打开后 F5也没有什么可看的 那我们就F12查看字符串找可疑信息 这里一下就看见了 __int64 __fastcall main(int a1, char **a2, char **a3) {char *v3; // rbx__int64 v4; // rax__int64 v…

【java苍穹外卖项目实战二】苍穹外卖环境搭建

文章目录 1、前端环境搭建2、后端环境搭建1、项目结构搭建2、Git版本控制3、数据库创建 开发环境搭建主要包含前端环境和后端环境两部分。 前端的页面我们只需要导入资料中的nginx, 前端页面的代码我们只需要能看懂即可。 1、前端环境搭建 前端运行环境的nginx&am…

【洛谷题解】P1075 [NOIP2012 普及组] 质因数分解

题目链接:[NOIP2012 普及组] 质因数分解 - 洛谷 题目难度:入门 涉及知识点:枚举(优化) 题意: 输入样例:21 输出样例:7 分析:枚举到小因数,再除a&#x…

关于CSDN的原力分增长规则,一点个人经验

本文章编写于 2024年2月9日 从2022年开始到现在,官方的原力分增减规则已经改过好几版了,有一些规则描述比较模糊,这里总结了一些个人经验。 原力值增长点: 1.每日发布文章一篇10分,两篇15分,上限15分&am…

微软AD域替代方案,助力企业摆脱hw期间被攻击的窘境

在红蓝攻防演练(hw行动)中,AD域若被攻击成功,是其中一个扣分最多的一项内容。每年,宁盾都会接到大量AD在hw期间被攻击,甚至是被打穿的企业客户。过去,企业还会借助2FA双因子认证加强OA、Exchang…

【漏洞复现】狮子鱼CMS某SQL注入漏洞

Nx01 产品简介 狮子鱼CMS(Content Management System)是一种网站管理系统,它旨在帮助用户更轻松地创建和管理网站。该系统拥有用户友好的界面和丰富的功能,包括页面管理、博客、新闻、产品展示等。通过简单直观的管理界面&#xf…

Python 数据可视化之山脊线图 Ridgeline Plots

文章目录 一、前言二、主要内容三、总结 🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 一、前言 JoyPy 是一个基于 matplotlib pandas 的单功能 Python 包,它的唯一目的是绘制山脊线图 Joyplots(也称为 Ridgeline Plots&…

计算机速成课Crash Course - 30. 万维网

今天继续计算机速成课Crash Course的系列讲解。 更多技术文章,全网首发公众号 “摸鱼IT” 锁定 -上午11点 - ,感谢大家关注、转发、点赞! 计算机速成课Crash Course - 30. 万维网 (qq.com) 30. 万维网 前两集我们深入讨论了电线、信号、交…

EasyExcel操作Excel表格

一、EasyExcel介绍 1.1 介绍 EasyExcel 是一个基于 Java 的简单易用的 Excel 文件读写工具,它提供了一种简单而又高效的方式来读取、写入和操作 Excel 文件。EasyExcel 是阿里巴巴开源的项目,它旨在简化开发人员处理 Excel 文件的流程,使得…

Python春节倒计时:用代码迎接新年的到来!

使用Python实现春节倒计时程序 一、引言 随着科技的不断发展,编程已经渗透到我们生活的方方面面。今天,我们将使用Python编写一个春节倒计时程序,来感受编程与传统文化的巧妙结合。该程序将能够显示距离农历2024年春节(大年初一…

运维高级篇-分库分表(拆分策略详解)

分库分表 介绍 问题分析 随着互联网及移动互联网的发展,应用系统的数据量也是成指数式增长,若采用单数据库进行数据存 储,存在以下性能瓶颈: IO瓶颈:热点数据太多,数据库缓存不足,产生大量磁盘…

企业级人脸属性检测解决方案

在当今数字化、智能化的时代背景下,人脸识别技术已经成为众多行业不可或缺的一部分。美摄科技,作为人脸识别技术的领先者,为企业提供了一整套先进且高效的人脸属性检测解决方案。 美摄科技的人脸属性检测解决方案,基于深度学习算…

24 SEMC相关

文章目录 24.1 SEMC 简介24.2 SEMC 框图剖析24.2.1 通讯引脚24.2.1.1 SEMC 的片选信号24.2.1.2 数据选通信号 DQS 24.2.2 存储器控制器24.2.3 IP 命令和 AXI 命令24.2.4 驱动时钟 24.4 SEMC 初始化配置结构体24.4.1 dqsMode24.4.2 cmdTimeoutCycles24.4.3 busTimeoutCycles24.4…

Android开发 button 按钮点击两次 响应onclick方法

问题 Android开发 button 按钮点击两次 响应onclick方法 详细问题 笔者xml代码 <!-- 一个按钮 --> <Button android:id"id/button1" android:layout_width"wrap_conten…

排序算法的时间复杂度存在下界问题

对于几种常用的排序算法&#xff0c;无论是归并排序、快速排序、以及更加常见的冒泡排序等&#xff0c;这些排序算法的时间复杂度都是大于等于O(n*lg(n))的&#xff0c;而这些排序算法存在一个共同的行为&#xff0c;那就是这些算法在对元素进行排序的时候&#xff0c;都会进行…

imazing是啥?imazing有什么用

iMazing 是一款用于管理 iOS 设备的第三方软件。它支持在 Windows 或 Mac 电脑上对连接的 iPhone、iPad 或 iPod 进行数据传输、备份和管理工作。用户可以通过 iMazing 传输和备份包括照片、音乐、铃声、视频、电子书和通讯录等在内的多种信息。iMazing 的功能与苹果官方的 iTu…

C#上位机与三菱PLC的通信03--MC协议之A-1E报文解析

1、MC协议帧 MC协议可以在串口通信&#xff0c;也可以在以太网通信&#xff0c;有A-1E和Qna-3E两种模式&#xff0c;这两种都是三菱PLC通信协议中比较常用的两种&#xff0c;一般我们使用比较多的是以太网通信&#xff0c;对于FX5U系列/Q系列/Qna系列/L系列的PLC&#xff0c;…

求职|基于Springboot的校园求职招聘系统设计与实现(源码+数据库+文档)

校园求职招聘系统目录 目录 基于Springboot的校园求职招聘系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户信息管理 2、企业信息管理 3、公告类型管理 4、公告信息管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选…