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