在工作中,需要记录的某项测试的具体操作时间,可以在系统桌面上显示实时的具体时间,以便具体分析发生这个行为的日志
TextView 可拖动悬浮窗
package com.lujianfei.showtime
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.AttributeSet
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
import android.view.View.OnTouchListener
import android.view.WindowManager
import android.widget.TextView
import java.text.SimpleDateFormat
import kotlin.math.abs
/**
* Author: lujianfei
* Date: 2025/1/23 16:25
* Description:
*/
class ShowTimeWindow @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
) : TextView(context, attrs) {
private var mWindowManager: WindowManager? = null
private var mLayoutParams: WindowManager.LayoutParams? = null
private val handler = Handler(Looper.getMainLooper(), this::handleMessage)
private var showTime = false
private var mTouchStartX = 0f
private var mTouchStartY = 0f
private var mX = 0f
private var mY = 0f
private val mOnTouchListener = OnTouchListener { v: View, event: MotionEvent ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
// 获取相对View的坐标,即以此View左上角为原点
mTouchStartX = event.x
mTouchStartY = event.y
return@OnTouchListener true
}
MotionEvent.ACTION_MOVE -> {
mX = event.rawX
mY = event.rawY - getStatusBarHeight() // 系统状态栏的高度
updateViewPosition()
return@OnTouchListener true
}
MotionEvent.ACTION_UP -> {
updateViewPosition()
mTouchStartX = 0f
mTouchStartY = 0f
if (abs((event.rawX - mTouchStartX).toDouble()) < 10 && abs(
(event.rawY - mTouchStartY).toDouble()
) < 10
) {
v.performClick()
}
return@OnTouchListener true
}
}
false
}
init {
mLayoutParams = WindowManager.LayoutParams()
mLayoutParams?.width = WindowManager.LayoutParams.WRAP_CONTENT
mLayoutParams?.height = WindowManager.LayoutParams.WRAP_CONTENT
mLayoutParams?.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
mLayoutParams?.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
mLayoutParams?.gravity = Gravity.START or Gravity.TOP
val displayMetrics = resources.displayMetrics
mLayoutParams?.x = displayMetrics.widthPixels / 2
mLayoutParams?.y = displayMetrics.heightPixels / 2
setBackgroundColor(0x80000000.toInt())
setTextColor(0xFFFFFFFF.toInt())
textSize = 30f
setOnTouchListener(mOnTouchListener)
}
fun showWindow() {
if (mWindowManager == null) {
mWindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
}
text = "显示时间"
kotlin.runCatching {
mWindowManager?.addView(this, mLayoutParams)
}
showTime = true
handler.sendEmptyMessageDelayed(0, 1000)
}
fun hideWindow() {
kotlin.runCatching {
mWindowManager?.removeView(this)
}
showTime = false
handler.removeMessages(0)
}
private fun handleMessage(msg: Message): Boolean {
val timeStr = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(System.currentTimeMillis())
text = "当前时间:${timeStr}"
if (showTime) {
handler.sendEmptyMessageDelayed(0, 10)
}
return true
}
private fun updateViewPosition() {
// 更新浮动窗口位置参数
mLayoutParams?.let {
it.x = (mX - mTouchStartX).toInt()
it.y = (mY - mTouchStartY).toInt()
mWindowManager?.updateViewLayout(this, it)
}
}
private fun getStatusBarHeight(): Int {
var result = 0
val resourceId: Int =
resources.getIdentifier("status_bar_height", "dimen", "android")
if (resourceId > 0) {
result = resources.getDimensionPixelSize(resourceId)
}
return result
}
}
使用方法
在使用的地方放两个按钮, 分别用于显示/隐藏
package com.lujianfei.showtime
import android.app.Activity
import android.os.Bundle
import android.view.View
/**
* Author: lujianfei
* Date: 2025/1/23 16:24
* Description:
*/
class MainActivity:Activity() {
private var showTimeWindow:ShowTimeWindow ?= null
private fun checkShowTimeWindow() {
if (showTimeWindow == null) {
showTimeWindow = ShowTimeWindow(this)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
requestPermissions(arrayOf(android.Manifest.permission.SYSTEM_ALERT_WINDOW , "android.permission.SYSTEM_OVERLAY_WINDOW"), 100)
findViewById<View>(R.id.showTimeButton).setOnClickListener {
checkShowTimeWindow()
showTimeWindow?.showWindow()
}
findViewById<View>(R.id.hideTimeButton).setOnClickListener {
showTimeWindow?.hideWindow()
}
}
}