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

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

XML 复制代码
<?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.RecyclerView
        android:id="@+id/rv2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/holo_red_light" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@null" />

    <com.tran.myapp.MyTouchView
        android:id="@+id/touch_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>
Kotlin 复制代码
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.RecyclerView


class MyTouchView : androidx.appcompat.widget.AppCompatImageView {
    private var mContext: Context? = null

    private var mRV1: RecyclerView? = null
    private var mRV2: RecyclerView? = null

    private var mScaleGestureDetector: ScaleGestureDetector? = null

    //缩放因子
    private var mScaleFactor = 1.0f
    private var mIsScaling = false

    private val BIG = 0
    private val SMALL = 1
    private var mGridStatus = BIG

    constructor(ctx: Context, attributeSet: AttributeSet) : super(ctx, attributeSet) {
        mContext = ctx

        mScaleGestureDetector = ScaleGestureDetector(mContext!!, object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
            override fun onScaleBegin(detector: ScaleGestureDetector): Boolean {
                return super.onScaleBegin(detector)
            }

            override fun onScale(detector: ScaleGestureDetector): Boolean {
                mScaleFactor = detector.scaleFactor
                Log.d(MainActivity.TAG, "onScale scaleFactor=${detector.scaleFactor}")
                return super.onScale(detector)
            }
        })
    }

    fun bindRV(rv1: RecyclerView, rv2: RecyclerView) {
        mRV1 = rv1
        mRV2 = rv2
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        var bRet = false
        val pointerId = event?.getPointerId(event.actionIndex)

        if (pointerId!! > 0) {
            this.postDelayed({
                mScaleGestureDetector?.onTouchEvent(event!!)
            }, 10)

            if (mScaleFactor < 1f) {
                if (!mIsScaling && mGridStatus != SMALL) {
                    mIsScaling = true
                    Log.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 = false
                            mScaleFactor = 1f
                            mGridStatus = SMALL
                        }

                        override fun onAnimationCancel(animation: Animator) {
                            mIsScaling = false
                            mScaleFactor = 1f
                            mGridStatus = 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 = true

                    val animatorSet = AnimatorSet()
                    animatorSet.addListener(object : Animator.AnimatorListener {
                        override fun onAnimationStart(animation: Animator) {

                        }

                        override fun onAnimationEnd(animation: Animator) {
                            mIsScaling = false
                            mScaleFactor = 1f
                            mGridStatus = BIG
                        }

                        override fun onAnimationCancel(animation: Animator) {
                            mIsScaling = false
                            mScaleFactor = 1f
                            mGridStatus = 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

相关推荐
2501_9400940218 分钟前
mig烧录卡资源 Mig-Switch游戏合集 烧录卡 1.75T
android·游戏·安卓·switch
渡我白衣28 分钟前
深入理解 OverlayFS:用分层的方式重新组织 Linux 文件系统
android·java·linux·运维·服务器·开发语言·人工智能
2501_9151063243 分钟前
iOS性能调优的系统化实践,从架构分层到多工具协同的全流程优化指南(开发者深度版)
android·ios·小程序·架构·uni-app·iphone·webview
stevenzqzq2 小时前
android recyclerview缓存_缓存问题解决办法
android·java·缓存
下位子2 小时前
『OpenGL学习滤镜相机』- Day10: 相机预览与 OpenGL 结合
android·opengl
那就逆流而上吧2 小时前
Android AIDL 的详细讲解和实践指南
android
TDengine (老段)4 小时前
TDengine 字符串函数 POSITION 用户手册
android·java·大数据·数据库·物联网·时序数据库·tdengine
2501_937154935 小时前
神马影视 8.8 源码 2025 版,HDR + 杜比音效 + 零卡顿
android·源码·源代码管理·机顶盒
asjhan5 小时前
Android framework强制修改系统属性
android
雨白13 小时前
Jetpack Compose Navigation 2.x 详解
android·android jetpack