如何正确创建可拖动的浮动视图?

问题描述 投票:0回答:1

我使用以下代码在屏幕上拖动视图,它可以工作。但是,当用户第一次触摸

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)
}
android kotlin android-windowmanager android-window
1个回答
0
投票

视图的 X/Y 坐标在 documentation 中定义为

translationX/Y
current
left/top
属性。视图的 Left/Top 位置是相对于其父视图的。

但是,你的

floatingView
是直接通过
WindowManger
添加的;它的父级是
ViewRootImpl
。因此,您不会期望该视图的左侧/顶部位置具有您需要的真实值,因为
ViewRootImpl
是开发人员无法访问的系统范围根视图;因此,如果您登录
view.x/y
,您将始终看到它们
0

他们没有直接从视图访问

ViewRootImpl
,而是为此提供了
WindowManger
API。即,当
floatingView
添加到
ViewRootImpl
时;我们没有做
ViewRootImpl.addView()
,但我们做了
windowManager.addView()

同样,我们需要通过

WindowManager
获取 x/y 参数,并使用
WindowManager.LayoutParams
来获取正确的值:

....
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
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.