android 悬浮窗

简介: android 悬浮窗

android 悬浮窗

现在很多应用都使用到悬浮窗,例如微信在视频的时候,点击Home键,视频小窗口仍然会在屏幕上显示。这个功能在很多情况下都非常有用。

1、申请权限

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
    <uses-permission android:name="android.permission.GET_TASKS" />
class MainActivity : AppCompatActivity() {    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_layout)
        startFloatingService()
    }
    @RequiresApi(api = Build.VERSION_CODES.M)
    fun startFloatingService() {
        if (!Settings.canDrawOverlays(this)) {
            startActivityForResult(
                Intent(
                    Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse(
                        "package:$packageName"
                    )
                ), 0x0002
            )
        } else {
            try {
                startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS))
            } catch (e: Exception) {
                Log.i(TAG, "start ACTION_ACCESSIBILITY_SETTINGS fail: " + e.message)  
                startActivity(Intent(Settings.ACTION_SETTINGS))
            }
        }
    }
    // 显示悬浮窗
    fun Show(view: View?) {
        FloatingClickService.showFloat(this)
    }
    // 隐藏悬浮窗
    fun Hide(view: View?) {
        FloatingClickService.hideFloat()
    }
}

2、创建悬浮窗服务

class FloatingClickService : Service() {
    private var manager: WindowManager? = null
    private var mFloatLayout: LinearLayout? = null
    private var settings: ImageView? = null  
    private var tip: TextView? = null
    private var params: WindowManager.LayoutParams? = null
    private var animation: AnimationF? = null
    private val inflater by lazy { LayoutInflater.from(application) }
    override fun onCreate() {
        super.onCreate()
        mInstance = this
        setFloatView()
    }
    override fun onBind(intent: Intent): IBinder? {
        return null
    }
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        //适配android8以上
        val builder = Notification.Builder(this.getApplicationContext()); //获取一个Notification构造器
        val nfIntent = Intent(this, MainActivity::class.java)
        builder.setContentIntent(PendingIntent.getActivity(this, 0, nfIntent, 0)) // 设置PendingIntent    
           builder.setContentText("后台运行")
        startForeground(110, builder.build())
        return super.onStartCommand(intent, flags, startId)
    }
    /**
     * 移除悬浮窗,停止服务
     */
    fun hide() {
        mInstance = null
        manager!!.removeView(mFloatLayout) // 移除悬浮窗
        if (mapView.size > 0 && mapViewPos > 0) {
            mapView.forEach { t, u ->
                manager?.removeView(u)
                mapViewPos--
            }
        }
        this.stopSelf() // 停止服务
        onDestroy()
    }     
    private fun setFloatView() {
        // 从布局文件,生成悬浮窗
        mFloatLayout = inflater.inflate(R.layout.float_view, null) as LinearLayout      
        // 添加悬浮窗至系统服务
        params = getParams()
        manager = application.getSystemService(WINDOW_SERVICE) as WindowManager
        manager!!.addView(mFloatLayout, params)
         // 浮动窗口按钮
        settings = mFloatLayout!!.findViewById<View>(R.id.setting) as ImageView
        mFloatLayout!!.measure(
            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
        )        settings!!.setOnTouchListener(touchListener) //
        settings!!.setOnClickListener(clickListener) // 添加setting按钮响应逻辑,其他按钮可以类似添加
        tip = mFloatLayout!!.findViewById<View>(R.id.tip) as TextView        // 为按钮添加动画效果
        val ids = intArrayOf(R.id.setting, R.id.search, R.id.note, R.id.link, R.id.alarm)
        animation = AnimationF(mFloatLayout!!, ids)
}
    // 拖动浮标时修改浮标位置
    var touchListener = OnTouchListener { v, event ->
        params!!.x = event.rawX.toInt() - settings!!.measuredWidth / 2
        params!!.y = event.rawY.toInt() - settings!!.measuredHeight / 2
        manager!!.updateViewLayout(mFloatLayout, params)
        false // 此处必须返回false,否则OnClickListener获取不到监听
    }
 var clickListener = View.OnClickListener { v ->
        if (v === settings) {
            animation!!.Setting(null) // 切换悬浮窗显示效果
        }
}
    private fun getParams(): WindowManager.LayoutParams {
        val wmParams = WindowManager.LayoutParams()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            wmParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
        } else {
            wmParams.type = WindowManager.LayoutParams.TYPE_PHONE
        } // 设置window type
        wmParams.format = PixelFormat.RGBA_8888 // 设置图片格式,效果为背景透明
        wmParams.flags =
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE // 设置浮动窗口不可聚焦(实现操作除浮动窗口外的其他可见窗口的操作)
        wmParams.gravity = Gravity.LEFT or Gravity.TOP // 调整悬浮窗显示的停靠位置为左侧置顶
        // 以屏幕左上角为原点,设置x、y初始值(10,10),相对于gravity
        wmParams.x = 10
        wmParams.y = 10
        // 设置悬浮窗口长宽数据
        wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT
        wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT
        return wmParams
    }
    companion object {
        /**
         * 显示悬浮窗
         */
        fun showFloat(context: Context) {
            if (mInstance == null) {
                val intent = Intent(context, FloatingClickService::class.java)
                intent.putExtra("inputExtra", "startService")
                ContextCompat.startForegroundService(context, intent)
            }
        }
        /**
         * 关闭悬浮窗
         */
        fun hideFloat() {
            if (mInstance != null) {
                mInstance!!.hide()
            }
        }
        private var mInstance: FloatingClickService? = null
    }
)


目录
相关文章
|
6月前
|
API Android开发 容器
33. 【Android教程】悬浮窗:PopupWindow
33. 【Android教程】悬浮窗:PopupWindow
739 2
|
Java API Android开发
Android免权限悬浮窗组件 - FloatingX
FloatingX ,一个强大的免权限悬浮窗组件,支持全局,以及局部悬浮窗。
853 0
Android免权限悬浮窗组件 - FloatingX
|
存储 消息中间件 API
下沉式通知的一种实现 | Android悬浮窗Window应用
当你浏览公众号时来了一条新消息,通知在屏幕顶部会以自顶向下动画的形式入场,而且它是跨界面的全局浮窗(效果如下图)。虽然上一篇中抽象的浮窗工具类已经能实现这个需求。但本文在此基础上再封装一些更加友好的
373 0
下沉式通知的一种实现 | Android悬浮窗Window应用
|
存储 Android开发 Kotlin
悬浮窗的一种实现 | Android悬浮窗Window应用
本文以业务应用为出发点,从零开始抽象一个浮窗工具类,它用于在任意业务界面上展示悬浮窗。它可以同时管理多个浮窗,而且浮窗可以响应触摸事件,可拖拽,有贴边动画。
841 0
悬浮窗的一种实现 | Android悬浮窗Window应用
|
Java Android开发 开发者
Android 悬浮窗功能的实现
Android 悬浮窗功能的实现
1383 2
Android 悬浮窗功能的实现
|
程序员 Android开发
Android各版本查询和开启悬浮窗权限
Android各版本查询和开启悬浮窗权限
753 0
|
开发工具 Android开发 图形学
Android 悬浮窗层级/WindowManager Type限制适配
众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!
1313 0
|
缓存 Android开发 数据安全/隐私保护
Android 悬浮窗、悬浮球开发
原文:Android 悬浮窗、悬浮球开发 1、权限管理 直接看我另外一篇博客吧,传送门: https://my.
1855 0
|
Android开发
Android 悬浮窗权限校验
原文:Android 悬浮窗权限校验 悬浮窗权限: 权限检验和请求: //检查是否已经授予权限,大于6.
1737 0