我使用下面的代码在屏幕上拖动一个视图,它起作用了.但是,当用户第一次touch moveIcon时,floatingView突然移动到屏幕的中心,尽管我希望它保持在原来的位置.我怎么才能解决这个问题呢?我怀疑问题出在updatePosition()方法中.

    windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
    val layoutInflater = LayoutInflater.from(this)
    floatingView = layoutInflater.inflate(R.layout.floating_layout, null)

    // Set up the layout parameters for the floating view
    val params = WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.WRAP_CONTENT,
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
        } else {
            @Suppress("DEPRECATION")
            WindowManager.LayoutParams.TYPE_PHONE
        },
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
        PixelFormat.TRANSLUCENT
    )


    windowManager!!.addView(floatingView, params)

    // Moving the views:
    moveIcon = floatingView!!.findViewById(R.id.moveIcon)

    moveIcon.setOnTouchListener { view, event ->
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                // Save the initial touch coordinates relative to the moveIcon view
                initialTouchX = event.rawX - view.x
                initialTouchY = event.rawY - view.y
            }
            MotionEvent.ACTION_MOVE -> {
                // Calculate the new position based on the movement and initial touch coordinates
                val newX = event.rawX - initialTouchX
                val newY = event.rawY - initialTouchY

                updatePosition(newX.toInt(), newY.toInt())
            }
        }
        true
    }
}

private fun updatePosition(x: Int, y: Int) {
    val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager

    val layoutParams = floatingView!!.layoutParams as WindowManager.LayoutParams
    layoutParams.x = x
    layoutParams.y = y
    windowManager.updateViewLayout(floatingView, layoutParams)
}

enter image description here

推荐答案

视图的X/Y坐标以documentation为单位定义为translationX/Ythe current left/top的属性.视图Left/Top位置相对于其父视图.

但是,你的floatingView是直接通过WindowManger相加的;在这里,它的父项是ViewRootImpl.因此,您不会期望该视图的左/上位置具有所需的真值,因为ViewRootImpl是开发人员无法访问的系统范围根视图;因此,如果您登录view.x/y,您将看到它们始终是0.

他们没有直接从视图访问ViewRootImpl,而是为此提供了WindowMangerAPI.也就是说,当floatingView加到ViewRootImpl的时候,我们没有做ViewRootImpl.addView(),但我们做了windowManager.addView().

同样,我们还需要使用WindowManager.LayoutParams获取WindowManager中的x/y参数,以获得正确的值:

....
MotionEvent.ACTION_DOWN -> {

//    initialTouchX = event.rawX - view.x // Remove this
//    initialTouchY = event.rawY - view.y // Remove this

    (floatingView.layoutParams as WindowManager.LayoutParams).let { params ->
        initialTouchX = event.rawX - params.x
        initialTouchY = event.rawY - params.y
    }

}

Android相关问答推荐

KMM项目生成错误-';在项目';中找不到测试类:共享';

NativeScript在`ns run android`上重复Kotlin类

避免在按下肯定按钮时自动取消AlertDialog

try 用Jetpack Compose理解视图模型和导航

使用Kotline绑定时,ViewHolder无法识别文本视图

在Jetpack Compose中实现自动换行

为什么Kotlin允许将非空值类型化为可空类型,但又将其视为非空值?

如何在DownloadManager Android中显示ProgressBar和Complete Listener

仅当先前输入为 yes 时,Android 才会要求下一个输入

FFmpeg Android 错误

使用 Gadle kotlin 为多模块 Android 代码库设置 jacoco

如何删除 Jetpack Compose 中按钮的左边框?

如何仅使用您的 Android 应用程序定位平板电脑?

我的自定义小吃店不适合我的全宽屏幕尺寸

如何在 Android 的 ViewModel 中使用 LiveData

导航组件中预期的函数调用map(...)

有什么方法可以确定正在使用哪个 Android 手机的麦克风进行录音?

Hilt 依赖注入重复绑定错误

如何对齐文本和图标可组合,以便即使在文本溢出后它们也能保持在一起?

升级到 android studio 花栗鼠后,应用程序未安装在模拟器中