Android悬浮窗的简单实现,移动app软件开发工程师就业前景

}

}

3. 创建View并添加到

private lateinit var floatingView: View

override fun onStartCommand(intent: Intentflags: Int, startId: Int): Int {

if (Settings.canDrawOverlays(this)) {

floatingView = LayoutInflater.from(this).inflate(R.layout.layout_floating_window.xml, null)

windowManager.addView(floatingView, layoutParams)

}

return super.onStartCommand(intent, flags, startId)

}

4. 实现悬浮窗的拖拽和关闭功能

// 浮窗的坐标

private var x = 0

private var y = 0

override fun onStartCommand(intent: Intentflags: Int, sta

Android悬浮窗的简单实现,移动app软件开发工程师就业前景
rtId: Int): Int {

if (Settings.canDrawOverlays(this)) {

floatingView = LayoutInflater.from(this).inflate(R.layout.layout_floating_window.xml, null)

windowManager.addView(floatingView, layoutParams)

// 点击浮窗的右上角关闭按钮可以关闭浮窗

floatingView.findViewById(R.id.iv_close).setOnClickListener {

windowManager.removeView(floatingView)

}

// 实现浮窗的拖动功能, 通过改变layoutParams来实现

floatingView.findViewById(R.id.layout_drag).setOnTouchListener { v, event ->

when (event.action) {

MotionEvent.ACTION_DOWN -> {

x = event.rawX.toInt()

y = event.rawY.toInt()

}

MotionEvent.ACTION_MOVE -> {

val currentX = event.rawX.toInt()

val currentY = event.rawY.toInt()

val offsetX = currentX – x

val offsetY = currentY – y

x = currentX

y = currentY

layoutParams.x = layoutParams.x + offsetX

layoutParams.y = layoutParams.y + offsetY

// 更新floatingView

windowManager.updateViewLayout(floatingView, layoutParams)

}

}

true

}

return super.onStartCommand(intent, flags, startId)

}

5. 利用广播进行通信

private var receiver: MyReceiver= null

override fun onCreate() {

// 注册广播

receiver = MyReceiver()

val filter = IntentFilter()

filter.addAction(“android.intent.action.MyReceiver”)

registerReceiver(receiver, filter)

}

inner class MyReceiver : BroadcastReceiver() {

override fun onReceive(context: Context, intent: Intent) {

val content = intent.getStringExtra(“content”) “”

// 通过Handler更新UI

val message = Message.obtain()

message.what = 0

message.obj = content

handler.sendMessage(message)

}

}

val handler = Handler(this.mainLooper) { msg ->

tvContent.text = msg.obj as String

false

}

可以在Activity中通过广播给Service发送信息

fun sendMessage(view: View{

Intent(“android.intent.action.MyReceiver”).apply {

putExtra(“content”, “Hello, World!”)

sendBroadcast(this)

}

}

6. 设置权限

悬浮窗的显示需要权限,在中添加:

此外,还要通过来让动态设置权限,在Activity中设置。

// MainActivity.kt

fun startWindow(view: View{

if (!Settings.canDrawOverlays(this)) {

startActivityForResult(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse(“package:$packageName”)), 0)

} else {

startService(Intent(this@MainActivity, FloatingWindowService::class.java))

}

}

/p>

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent{

super.onActivityResult(requestCode, resultCode, data)

if (requestCode == 0) {

if (Settings.canDrawOverlays(this)) {

Toast.makeText(this, “悬浮窗权限授权成功”, Toast.LENGTH_SHORT).show()

startService(Intent(this@MainActivity, FloatingWindowService::class.java))

}

}

}

3.3 完整代码

class FloatingWindowService : Service() {

private lateinit var windowManager: WindowManager

private lateinit var layoutParams: WindowManager.LayoutParams

private lateinit var tvContent: AppCompatTextView

private lateinit var handler: Handler

private var receiver: MyReceiver= null

private var floatingView: View= null

private val stringBuilder = StringBuilder()

private var x = 0

private var y = 0

// 用来判断floatingView是否attached 到 window manager,防止二次removeView导致崩溃

private var attached = false

override fun onCreate() {

super.onCreate()

// 注册广播

receiver = MyReceiver()

val filter = IntentFilter()

filter.addAction(“android.intent.action.MyReceiver”)

registerReceiver(receiver, filter);

// 获取windowManager并设置layoutParams

windowManager = getSystemService(WINDOW_SERVICE) as WindowManager

layoutParams = WindowManager.LayoutParams().apply {

type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY

} else {

WindowManager.LayoutParams.TYPE_PHONE

}

format = PixelFormat.RGBA_8888

// format = PixelFormat.TRANSPARENT

gravity = Gravity.START or Gravity.TOP

flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE

width = 600

height = 600

x = 300

y = 300

}

handler = Handler(this.mainLooper) { msg ->

tvContent.text = msg.obj as String

// 当文本超出屏幕自动滚动,保证文本处于最底部

val offset = tvContent.lineCount * tvContent.lineHeight

floatingViewapply {

if (offset > height) {

tvContent.scrollTo(0, offset – height)

}

}

false

}

}

override fun onBind(intent: Intent: IBinder{

return null

}

@SuppressLint(“ClickableViewAccessibility”)

override fun onStartCommand(intent: Intentflags: Int, startId: Int): Int {

if (Settings.canDrawOverlays(this)) {

floatingView = LayoutInflater.from(this).inflate(R.layout.layout_show_log, null)

tvContent = floatingView!!.findViewById(R.id.tv_log)

floatingView!!.findViewById(R.id.iv_close).setOnClickListener {

stringBuilder.clear()

windowManager.removeView(floatingView)

attached = false

}

// 设置TextView滚动

tvContent.movementMethod = ScrollingMovementMethod.getInstance()
{

floatingView = LayoutInflater.from(this).inflate(R.layout.layout_show_log, null)

tvContent = floatingView!!.findViewById(R.id.tv_log)

floatingView!!.findViewById(R.id.iv_close).setOnClickListener {

stringBuilder.clear()

windowManager.removeView(floatingView)

attached = false

}

// 设置TextView滚动

tvContent.movementMethod = ScrollingMovementMethod.getInstance()

来源:普通网友

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年1月9日
下一篇 2022年1月9日

相关推荐