Android叠加双RecyclerView ScaleGestureDetector AnimatorSet动态放大缩小,Kotlin(1)

ops/2024/11/29 22:29:40/

Android叠加双RecyclerView ScaleGestureDetector AnimatorSet动态放大缩小,Kotlin(1)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/rv2"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@android:color/holo_red_light" /><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/rv1"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@null" /><com.tran.myapp.MyTouchViewandroid:id="@+id/touch_view"android:layout_width="match_parent"android:layout_height="match_parent" />
</RelativeLayout>

import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import androidx.recyclerview.widget.RecyclerViewclass MyTouchView : androidx.appcompat.widget.AppCompatImageView {private var mContext: Context? = nullprivate var mRV1: RecyclerView? = nullprivate var mRV2: RecyclerView? = nullprivate var mScaleGestureDetector: ScaleGestureDetector? = null//缩放因子private var mScaleFactor = 1.0fprivate var mIsScaling = falseprivate val BIG = 0private val SMALL = 1private var mGridStatus = BIGconstructor(ctx: Context, attributeSet: AttributeSet) : super(ctx, attributeSet) {mContext = ctxmScaleGestureDetector = ScaleGestureDetector(mContext!!, object : ScaleGestureDetector.SimpleOnScaleGestureListener() {override fun onScaleBegin(detector: ScaleGestureDetector): Boolean {return super.onScaleBegin(detector)}override fun onScale(detector: ScaleGestureDetector): Boolean {mScaleFactor = detector.scaleFactorLog.d(MainActivity.TAG, "onScale scaleFactor=${detector.scaleFactor}")return super.onScale(detector)}})}fun bindRV(rv1: RecyclerView, rv2: RecyclerView) {mRV1 = rv1mRV2 = rv2}override fun onTouchEvent(event: MotionEvent?): Boolean {var bRet = falseval pointerId = event?.getPointerId(event.actionIndex)if (pointerId!! > 0) {this.postDelayed({mScaleGestureDetector?.onTouchEvent(event!!)}, 10)if (mScaleFactor < 1f) {if (!mIsScaling && mGridStatus != SMALL) {mIsScaling = trueLog.d(MainActivity.TAG, "to small mScaleFactor=$mScaleFactor")val animatorSet = AnimatorSet()animatorSet.addListener(object : Animator.AnimatorListener {override fun onAnimationStart(animation: Animator) {}override fun onAnimationEnd(animation: Animator) {mIsScaling = falsemScaleFactor = 1fmGridStatus = SMALL}override fun onAnimationCancel(animation: Animator) {mIsScaling = falsemScaleFactor = 1fmGridStatus = SMALL}override fun onAnimationRepeat(animation: Animator) {}})val x1 = ObjectAnimator.ofFloat(mRV1, "scaleX", 1f, 0.01f).apply {duration = 2000}val y1 = ObjectAnimator.ofFloat(mRV1, "scaleY", 1f, 0.01f).apply {duration = 2000}val a1 = ObjectAnimator.ofFloat(mRV1, "alpha", 1f, 0f).apply {duration = 2000}val x2 = ObjectAnimator.ofFloat(mRV2, "scaleX", 0.01f, 1f).apply {duration = 2000}val y2 = ObjectAnimator.ofFloat(mRV2, "scaleY", 0.01f, 1f).apply {duration = 2000}val a2 = ObjectAnimator.ofFloat(mRV2, "alpha", 0f, 1f).apply {duration = 2000}animatorSet.playTogether(x1, y1, a1, x2, y2, a2)animatorSet.start()}} else if (mScaleFactor > 1f && mGridStatus != BIG) {if (!mIsScaling) {Log.d(MainActivity.TAG, "to big mScaleFactor=$mScaleFactor")mIsScaling = trueval animatorSet = AnimatorSet()animatorSet.addListener(object : Animator.AnimatorListener {override fun onAnimationStart(animation: Animator) {}override fun onAnimationEnd(animation: Animator) {mIsScaling = falsemScaleFactor = 1fmGridStatus = BIG}override fun onAnimationCancel(animation: Animator) {mIsScaling = falsemScaleFactor = 1fmGridStatus = BIG}override fun onAnimationRepeat(animation: Animator) {}})val x1 = ObjectAnimator.ofFloat(mRV1, "scaleX", 0.01f, 1f).apply {duration = 2000}val y1 = ObjectAnimator.ofFloat(mRV1, "scaleY", 0.01f, 1f).apply {duration = 2000}val a1 = ObjectAnimator.ofFloat(mRV1, "alpha", 0f, 1f).apply {duration = 2000}val x2 = ObjectAnimator.ofFloat(mRV2, "scaleX", 1f, 0.01f).apply {duration = 2000}val y2 = ObjectAnimator.ofFloat(mRV2, "scaleY", 1f, 0.01f).apply {duration = 2000}val a2 = ObjectAnimator.ofFloat(mRV2, "alpha", 1f, 0f).apply {duration = 2000}animatorSet.playTogether(x1, y1, a1, x2, y2, a2)animatorSet.start()}}bRet = true} else {bRet = false}return bRet}
}

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


http://www.ppmy.cn/ops/137759.html

相关文章

手机设置了卡2上网,卡1禁止上网,但是卡1还是会偷偷跑流量,这是什么情况???

双卡双待手机&#xff0c;卡2设置为默认上网卡&#xff0c;卡1却会偷偷跑流量&#xff0c;这就很迷。 双卡双待手机&#xff0c;不管是哪个牌子&#xff08;网上有小米&#xff0c;华为&#xff0c;vivo出现这种情况&#xff0c;我的是华为mate20&#xff09;&#xff0c;都存在…

c++设计模式模块与系统

c 中lambda 本质就是一个匿名(没有名)的函数&#xff1b; 可以用一个数组元素存储一个函数的指针&#xff1b; 通过数组下标来使用函数&#xff1b; 高内聚低耦合 如何理解设计模式中的高内聚低耦合 高内聚: 用于指导如何组织和划分软件设计。 **定义&#xff1a;**高内聚指的…

使用Hugo和GitHub Pages创建静态网站个人博客

不需要服务器&#xff0c;不需要域名&#xff0c;不需要数据库&#xff0c;可以选择模版&#xff0c;内容为Markdown格式。 Hugo&#xff1a;https://gohugo.io 文档&#xff1a;https://gohugo.io/getting-started/quick-start/ 中文文档&#xff1a;https://www.gohugo.or…

云计算基础-期末复习

第一章&#xff1a;云计算概论 一、云计算的定义与特征 1. 定义&#xff1a; 云计算是一种通过网络以按需、可扩展的方式获取计算资源和服务的模式。它将计算资源视为一种公用事业&#xff0c;用户可以根据需求动态获取和释放资源&#xff0c;而无需了解底层基础设施的细节。…

AIGC时代:如何快速搞定Spring Boot+Vue全栈开发

文章目录 一、Spring Boot基础二、Vue.js基础三、Spring Boot与Vue.js集成四、性能优化与最佳实践《快速搞定Spring BootVue全栈开发》内容简介作者简介目录前言/序言本书内容本书特点读者对象 随着人工智能生成内容&#xff08;AIGC&#xff09;技术的迅速发展&#xff0c;内容…

200. 岛屿数量【 力扣(LeetCode) 】

文章目录 零、LeetCode 原题一、题目描述二、测试用例三、解题思路四、参考代码 零、LeetCode 原题 200. 岛屿数量 一、题目描述 给你一个由 ‘1’&#xff08;陆地&#xff09;和 ‘0’&#xff08;水&#xff09;组成的的二维网格&#xff0c;请你计算网格中岛屿的数量。 …

ajax基础

一&#xff1a;express框架 在终端输入nodejs文件名 // 引入express const express require(express); //创建应用对象 const app express(); //创建路由规则 app.get(/,(request,response) > {//设置响应response.send(Hello Express); }); // 监听3000端口 app.lis…

新潮传媒集团创始人张继学将出席创客匠人创始人IP领袖高峰论坛

正式官宣&#xff01;中国最大的社区数字化媒体平台——新潮传媒集团创始人张继学&#xff0c;已确认受邀出席创客匠人5000人“全球创始人IP领袖高峰论坛”&#xff0c;与我们共赴一场知识服务行业的盛宴&#xff01; 由创客匠人发起的“全球创始人IP领袖高峰论坛”将在2024年…