androidkotlinmobile

How to get the actual position of a motion event for a system overlay button


When showing an application overlay button in android via display over other apps permission, I set a motion event listener to allow the user to drag the button around onscreen, but the position that I get from event.rawY isn't actually accurate and appears to have the status bars and maybe navigation bars subtracted from the resulting y position.

As a result the button is always below where the user is actually touching by approx 80 dp even though I have calculated in the buttons height, and the width is spot on

val displayMetrics = displayData.getInstance()
cursorView = Button(context)
val cursorSize = displayMetrics.screenSizeX / 10
cursorView?.setBackgroundResource(R.drawable.cursor)
cursorParams = WindowManager.LayoutParams(
    cursorSize, cursorSize,
    WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
            WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
            WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
    PixelFormat.TRANSLUCENT
)
cursorParams?.gravity = Gravity.START or Gravity.TOP

cursorParams?.x = (displayMetrics.screenSizeX - cursorSize) / 2
cursorParams?.y = (displayMetrics.screenSizeY - cursorSize) / 2

cursorView?.setOnTouchListener { _, event ->
    when (event.action) {
        MotionEvent.ACTION_MOVE -> {
            cursorParams?.x = (event.rawX - cursorSize / 2).toInt()
            cursorParams?.y = (event.rawY - cursorSize / 2).toInt()
            Tools.logMessage(message ="Screen Size: ${displayMetrics.screenSizeX} x ${displayMetrics.screenSizeY}")
            Tools.logMessage(message ="Calculated Cursor Position: ${cursorParams?.x}, ${cursorParams?.y}")

            windowManager.updateViewLayout(cursorView, cursorParams)
            true
        }
        else -> false
    }
}

windowManager.addView(cursorView, cursorParams)

is there a better way of getting the actual movement position relative to the actual screen size, besides calculating the height of the status and navigation bars?

The displayData class is where I have the actual screen size stored, and it is accurate, which I have confirmed


Solution

  • Got it figured out, as I suspected the coordinates returned from the motion event were relative to the screen minus the staus and navigation bars, passing in FLAG_LAYOUT_IN_SCREEN flag to the window manager resolves that and gives the actual event position

        cursorView = Button(context)
        cursorSize = displayMetrics.screenSizeX / 10
        cursorView?.setBackgroundResource(R.drawable.target)
        cursorParams = WindowManager.LayoutParams(
                cursorSize, cursorSize,
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
                        WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
                        WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or
                        WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, // Add this flag
                PixelFormat.TRANSLUCENT
        )
    
        cursorParams?.gravity = Gravity.START or Gravity.TOP
    
    
        cursorParams?.x = (displayMetrics.screenSizeX - cursorSize) / 2
        cursorParams?.y = (displayMetrics.screenSizeY - cursorSize) / 2
    
    
        cursorView?.setOnTouchListener { _, event ->
            when (event.action) {
                MotionEvent.ACTION_MOVE -> {
                    cursorParams?.x = (event.rawX - cursorSize / 2).toInt()
                    cursorParams?.y = (event.rawY - cursorSize / 2).toInt()
                    Tools.logMessage(message ="Screen Size: ${displayMetrics.screenSizeX} x ${displayMetrics.screenSizeY}")
                    Tools.logMessage(message ="Calculated Cursor Position: ${cursorParams?.x}, ${cursorParams?.y}")
    
                    windowManager.updateViewLayout(cursorView, cursorParams)
                    true
                }
                else -> false
            }
        }