Android Matrix剪切clipPath缩放scale图片postTranslate圆形放大镜,Kotlin(2)

Android Matrix剪切clipPath缩放scale图片postTranslate圆形放大镜,Kotlin(2)

在 Android Matrix剪切clipPath缩放scale图片postTranslate圆形放大镜,Kotlin(1) Android Matrix剪切clipPath缩放scale图片postTranslate圆形放大镜,Kotlin(1)-CSDN博客 基础上,改进,使得ImageView的scaleType为fitCenter高度match_parent后,顶部留出空白,也能准确的在手指触点显示放大镜:

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.Path
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 android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatImageViewclass MainActivity : AppCompatActivity() {private var image: MyImage? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)image = findViewById(R.id.image)}
}class MyImage : AppCompatImageView {private val TAG = "fly"private var mIsDraw = falseprivate var curX: Float = 0fprivate var curY: Float = 0fprivate var originBmp: Bitmap = (drawable as BitmapDrawable).bitmapconstructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)override fun onTouchEvent(event: MotionEvent?): Boolean {when (event?.actionMasked) {MotionEvent.ACTION_DOWN -> {mIsDraw = truecurX = event.xcurY = event.yinvalidate()}MotionEvent.ACTION_MOVE -> {curX = event.xcurY = event.yinvalidate()}MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {mIsDraw = falseinvalidate()}}return true}override fun draw(canvas: Canvas) {super.draw(canvas)if (canDraw()) {myDraw(canvas)}}private fun canDraw(): Boolean {return mIsDraw}/*** Matrix放大矩阵,通过clipPath剪切一块圆形区域作为放大镜区域,然后直接在clipPath的区域上绘制放大后的图。*/private fun myDraw(canvas: Canvas) {Log.d(TAG, "ImageView w=${width} h=${height} Bitmap w=${originBmp.width} h=${originBmp.height}")val path = Path()val radius = 250fval factor = 4fval paint = Paint(Paint.ANTI_ALIAS_FLAG)paint.color = Color.REDpaint.style = Paint.Style.STROKEpaint.strokeWidth = 10fpath.addCircle(curX, curY, radius, Path.Direction.CW)canvas.drawPath(path, paint) //画红色的圆圈,圆心是手指在屏幕上的触点。canvas.clipPath(path) //剪切出来一片圆形区域。//特别注意,这里固定以手机屏幕的宽度为基准等比例放大Bitmap。val scaleW: Float = resources.displayMetrics.widthPixels.toFloat()val scaleH: Float = (originBmp.height.toFloat() / originBmp.width.toFloat()) * scaleWLog.d(TAG, "display w=${scaleW} h=${scaleH}")val matrix = Matrix()matrix.setScale(factor, factor)//canvas.concat(matrix)val rectF = getBitmapBound(this)val dx = (rectF.left - curX) * factor + curXval dy = (rectF.top - curY) * factor + curY//上下左右移动矩阵,使得放大后的矩阵处于圆圈的内容刚好是手指触点为中心的圆图。matrix.postTranslate(dx, dy)canvas.drawBitmap(Bitmap.createScaledBitmap(originBmp, scaleW.toInt(), scaleH.toInt(), true),matrix,paint)}private fun getBitmapBound(imageView: ImageView): RectF {val bounds = RectF()val drawable = imageView.drawableif (drawable != null) {imageView.imageMatrix.mapRect(bounds, RectF(drawable.bounds))}return bounds}
}

    <com.pkg.MyImageandroid:id="@+id/image"android:layout_width="match_parent"android:layout_height="match_parent"android:adjustViewBounds="true"android:scaleType="fitCenter"android:src="@mipmap/p2" />

ImageView由于高度在xml布局设置match_parent,撑满整个屏幕,但由于图像的Bitamp缩放为fitCenter没有充满整个ImageView。主要是计算ImageView里面Bitmap的RectF区域,然后顶部和坐标做一定偏移,对准手指触点位置。

Android Matrix剪切clipPath缩放scale图片postTranslate圆形放大镜,Kotlin(1)-CSDN博客文章浏览阅读807次,点赞16次,收藏14次。需要注意的,因为在xml布局里面特别设置了ImageView的高度为wrap_content,手指在屏幕触点的位置是放大镜里面放大图片后准确圆心位置,但是,如果ImageView设置成match_parent,则因为ImageView里面的Bitmap被缩放(此处Bitmap其实小于ImageView,被拉伸了),拉伸后的Bitmap水平方向坐标与ImageView一直重合,但竖直方向,Bitmap坐标与ImageView不一致,会造成一种现象,手指触点放大镜放大后,水平方向是正确的,但竖直方向有偏移量。https://blog.csdn.net/zhangphil/article/details/135172744

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

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

相关文章

LCR 174. 寻找二叉搜索树中的目标节点

解题思路&#xff1a; 二叉搜索树一般采用中序遍历&#xff08;从小到大排列&#xff09;。 class Solution {int res, cnt;public int findTargetNode(TreeNode root, int cnt) {this.cnt cnt;dfs(root);return res;}void dfs(TreeNode root) {if(root null) return;dfs(ro…

Docker 入门 ------容器互通以及Dockerfile

1. 端口映射以及容器互联 Docker 除了通过网络访问&#xff0c;还提供了两种很方便的功能来满足服务访问的基本需求&#xff1a; 允许映射容器内应用的服务端口到本地宿主主机互联机制实现多个容器间通过容器名来快速访问 1.1 容器映射实现访问容器 1.1.1 从外部访问容器应…

Python 标准库中的 csv 包

0. Abstract 官方文档很罗嗦&#xff0c;长篇大论例子少。本文将举例说明 csv 包的用法&#xff0c;然后补充一些必要的说明。 1.0 CSV 文件 CSV(Comma-Separated Values,逗号分隔值)文件是一种常见的以纯文本形式存储数据的文件格式。它使用逗号作为字段之间的分隔符&#…

解决docker容器内无法连接宿主redis

背景 小程序的发短信服务挂了&#xff0c;随查看日志&#xff0c;该报错日志如下 Error 111 connecting to 127.0.0.1:6379. Connection refused. 6379是监听redis服务的端口&#xff0c;那大概是redis出错了。 首先查看了redis是否正常启动&#xff0c;检查出服务正常。 由于小…

Flappy Bird QDN PyTorch博客 - 代码解读

Flappy Bird QDN PyTorch博客 - 代码解读 介绍环境配置项目目录结构QDN算法重要函数解读preprocess(observation)DeepNetWork(nn.Module)BirdDQN类主程序部分 介绍 在本博客中&#xff0c;我们将介绍如何使用QDN&#xff08;Quantile Dueling Network&#xff09;算法&#xf…

【Mybatis】我抄袭了Mybatis,手写一套MyMybatis框架:编写一个引入MyMybatis框架的正常项目

上一篇文章中&#xff0c;我们学习了使用mybatis框架连接mysql。在这篇文章中&#xff0c;我们将聚焦于我们的调用方&#xff0c;即相应的实际项目&#xff0c;其中包含了对mymybatis框架的引用。以一个常见而又典型的例子来说明这一点——制作一款学生管理系统&#xff08;伪&…

部署清华ChatGLM-6B(Linux版)

引言 前段时间,清华公布了中英双语对话模型 ChatGLM-6B,具有60亿的参数,初具问答和对话功能。最!最!最重要的是它能够支持私有化部署,大部分实验室的服务器基本上都能跑起来。因为条件特殊,实验室网络不通,那么如何进行离线部署呢? 「部署环境」:CUDA Version 11.0,…

Maven简介及环境搭建和基本使用(Java开发中的实用工具)

一、概述 Maven 是 Apache 软件基金会的一个开源项目,是一个优秀的项目构建工具,它 用来帮助开发者管理项目中的 jar,以及 jar 之间的依赖关系、完成项目的编译、 测试、打包和发布等工作。 Maven的相关概念 pom.xml文件&#xff1a;里面可以配置相关信息&#xff0c;指导ma…

【SpringBoot开发】之商城项目案例(沙箱支付)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《SpringBoot开发之商城项目系列》。&#x1f3af…

MySQL数据库索引优化实战

目录 一、前言 二、准备工作 2.1 用户表&#xff08;TB_USER) 2.2 商品表&#xff08;TB_SKU) 2.3 订单表&#xff08;TB_ORDER&#xff09; 三、实例分析 3.1 索引提升查询性能 3.2 多表查询 3.3 索引失效 四、总结 一、前言 在数据库的应用中&#xff0c;性能优化…

类加载机制之双亲委派模型、作用、源码、SPI打破双亲委派模型

双亲委派模型 双亲委派工作机制双亲委派的作用双亲委派的实现源码SPI打破双亲委派 应用程序是由三种类加载器相互配合&#xff0c;从而实现类加载&#xff0c;除此之外还可以加入自己定义的类的加载器。 类加载器之间的层次关系&#xff0c;称为双亲委派模型&#xff08;Parent…

2024最全面且有知识深度的web3开发工具、web3学习项目资源平台

在Web3技术迅速发展的时代&#xff0c;寻找一个综合且深入的Web3开发工具和学习项目资源平台变得至关重要。今天&#xff0c;我将向大家介绍一个非常有价值的网站&#xff0c;它就是https://web3x.world 。 Web3X是一个全面而深入的Web3开发者社区&#xff0c;为开发者们提供了…

【深度学习】各领域常用的损失函数汇总(2024最新版)

目录 1、L1 损失、平均绝对误差&#xff08;L1 Loss、Mean Absolute Error&#xff0c;MAE&#xff09; 2、L2 损失、均方误差&#xff08;L2 Loss、Mean Squared Error&#xff0c;MSE&#xff09; 3、交叉熵损失&#xff08;Cross-Entropy Loss&#xff09; 4、混合损失&…

webpack的深入学习与实战(持续更新)

一、何为Webpack Webpack是 一个开源的JavaScript模块打包工具&#xff0c;其最核心的功能是解决模块之间的依赖&#xff0c;把各个模块按照特定的规则和顺序组织在一起&#xff0c;最终合并为一个JS文件或多个。 二、带宽的换算 目前我们的云服务器带宽为5M 三 、bundle 体…

【算法挨揍日记】day34——647. 回文子串、5. 最长回文子串

647. 回文子串 647. 回文子串 题目描述&#xff1a; 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串&am…

202365读书笔记|《温暖和百感交集的旅程》——时间帮助着一个人的一生在几千字的篇幅里栩栩如生

202365读书笔记|《温暖和百感交集的旅程》——时间帮助着一个人的一生在几千字的篇幅里栩栩如生 我能否相信自己温暖和百感交集的旅程前言和后记 《温暖和百感交集的旅程》作者余华&#xff0c;之前读完的一本书&#xff0c;已经不太记得内容了&#xff0c;看着笔记整理的这篇书…

【进程间通信】

什么是进程通信 进程通信&#xff08; InterProcess Communication&#xff0c;IPC&#xff09;就是指进程之间的信息的传播和交换。 进程是分配系统资源的单位&#xff0c;包括内存地址空间&#xff0c;为了保证安全&#xff0c;一个进程不能直接访问另一个进程的地址空间&a…

CMake入门教程【核心篇】属性管理set_property和get_property

&#x1f608;「CSDN主页」&#xff1a;传送门 &#x1f608;「Bilibil首页」&#xff1a;传送门 &#x1f608;「本文的内容」&#xff1a;CMake入门教程 &#x1f608;「动动你的小手」&#xff1a;点赞&#x1f44d;收藏⭐️评论&#x1f4dd; 文章目录 1.概述2.设置属性 - …

FPGA设计时序约束十五、Set_Bus_Skew

目录 一、序言 二、Set Bus Skew 2.1 基本概念 2.2 设置界面 2.3 命令语法 2.4 报告分析 三、工程示例 3.1 工程代码 3.2 时序报告 四、参考资料 一、序言 在时序约束中&#xff0c;对时钟的约束除了set clock latency,set clock uncertainty,set input jitter外&…

51、全连接 - 特征的全局融合

Resnet50 中的核心算法,除了卷积、池化、bn、relu之外,在最后一层还有一个全连接。 下图是 Resnet50 网络结构结尾的部分,最后一层 Gemm(通用矩阵乘法)实现的就是全连接操作。而矩阵乘法我们之前介绍过,传送门在:矩阵乘。 卷积也好,矩阵乘法也好,其目的都是为了完成神…