EasyFloat源码解析:从Builder模式到窗口管理核心架构

EasyFloat源码解析:从Builder模式到窗口管理核心架构 EasyFloat源码解析从Builder模式到窗口管理核心架构【免费下载链接】EasyFloat EasyFloat浮窗从未如此简单Android可拖拽悬浮窗口支持页面过滤、自定义动画可设置单页面浮窗、前台浮窗、全局浮窗浮窗权限按需自动申请...项目地址: https://gitcode.com/gh_mirrors/ea/EasyFloatEasyFloat源码深度解析掌握Android悬浮窗框架的核心设计思想与实现原理作为一款功能强大的Android悬浮窗框架EasyFloat以其简洁的API设计和灵活的架构赢得了众多开发者的青睐。本文将带你深入探索EasyFloat的源码架构从Builder模式的应用到窗口管理的核心实现全面解析这个优秀开源项目的设计精髓。 核心架构概览EasyFloat采用分层架构设计主要分为以下几个核心模块API层(EasyFloat.kt) - 提供简洁的链式调用接口配置层(FloatConfig.kt) - 统一管理浮窗配置参数窗口管理层(FloatingWindowManager.kt,FloatingWindowHelper.kt) - 负责窗口的创建、管理和销毁工具层(TouchUtils.kt,AnimatorManager.kt) - 提供拖拽、动画等辅助功能权限层(PermissionUtils.kt) - 处理系统浮窗权限申请图EasyFloat的拖拽边界功能演示 Builder模式优雅的配置构建器EasyFloat最引人注目的特性之一就是其流畅的链式调用API这得益于Builder模式的巧妙应用。让我们先看看核心的Builder类实现// 在EasyFloat.kt中 class Builder(private val activity: Context) : OnPermissionResult { private val config FloatConfig() fun setSidePattern(sidePattern: SidePattern) apply { config.sidePattern sidePattern } fun setShowPattern(showPattern: ShowPattern) apply { config.showPattern showPattern } fun setLayout(layoutId: Int, invokeView: OnInvokeView? null) apply { config.layoutId layoutId config.invokeView invokeView } fun show() when { config.layoutId null config.layoutView null - callbackCreateFailed(WARN_NO_LAYOUT) config.showPattern ShowPattern.CURRENT_ACTIVITY - createFloat() PermissionUtils.checkPermission(activity) - createFloat() else - requestPermission() } }Builder模式的优势在于配置隔离所有配置参数都封装在FloatConfig对象中链式调用每个配置方法都返回this支持.setXxx().setYyy().show()的流畅写法延迟执行配置完成后才调用show()方法真正创建浮窗类型安全使用Kotlin的枚举类确保参数有效性 FloatConfig统一配置管理FloatConfig是一个数据类它集中管理了浮窗的所有配置参数// 在FloatConfig.kt中 data class FloatConfig( var layoutId: Int? null, var layoutView: View? null, var floatTag: String? null, var dragEnable: Boolean true, var sidePattern: SidePattern SidePattern.DEFAULT, var showPattern: ShowPattern ShowPattern.CURRENT_ACTIVITY, var gravity: Int 0, var offsetPair: PairInt, Int Pair(0, 0), var locationPair: PairInt, Int Pair(0, 0), // ... 更多配置参数 )这种设计的好处是单一职责配置管理与业务逻辑分离易于扩展新增配置只需在数据类中添加字段不可变状态使用val关键字确保配置在创建后不被意外修改️ 窗口管理核心FloatingWindowManager窗口管理器是EasyFloat的核心它采用单例模式管理所有浮窗实例// 在FloatingWindowManager.kt中 internal object FloatingWindowManager { private const val DEFAULT_TAG default val windowMap ConcurrentHashMapString, FloatingWindowHelper() fun create(context: Context, config: FloatConfig) { if (!checkTag(config)) { val helper FloatingWindowHelper(context, config) helper.createWindow(object : FloatingWindowHelper.CreateCallback { override fun onCreate(success: Boolean) { if (success) windowMap[config.floatTag!!] helper } }) } else { // 存在相同的tag直接创建失败 config.callbacks?.createdResult(false, WARN_REPEATED_TAG, null) } } fun dismiss(tag: String? null, force: Boolean false) getHelper(tag)?.run { if (force) remove(force) else exitAnim() } }关键设计要点并发安全使用ConcurrentHashMap管理多个浮窗实例标签管理每个浮窗都有唯一标识符支持多浮窗场景生命周期管理统一处理浮窗的创建、显示、隐藏和销毁图EasyFloat的状态回调机制演示 窗口创建流程详解FloatingWindowHelper负责具体的窗口创建和视图管理// 在FloatingWindowHelper.kt中 internal class FloatingWindowHelper(val context: Context, var config: FloatConfig) { lateinit var windowManager: WindowManager lateinit var params: WindowManager.LayoutParams private fun createWindowInner(): Boolean try { touchUtils TouchUtils(context, config) initParams() addView() config.isShow true true } catch (e: Exception) { false } private fun initParams() { windowManager context.getSystemService(Service.WINDOW_SERVICE) as WindowManager params WindowManager.LayoutParams().apply { if (config.showPattern ShowPattern.CURRENT_ACTIVITY) { type TYPE_APPLICATION_PANEL token getToken() } else { type if (Build.VERSION.SDK_INT Build.VERSION_CODES.O) TYPE_APPLICATION_OVERLAY else TYPE_PHONE } // ... 更多参数设置 } } }窗口类型选择策略当前Activity浮窗使用TYPE_APPLICATION_PANEL与Activity绑定系统全局浮窗Android O使用TYPE_APPLICATION_OVERLAY低版本使用TYPE_PHONE 拖拽与动画系统EasyFloat的拖拽系统基于策略模式设计支持多种贴边模式// 在SidePattern.kt中 enum class SidePattern { DEFAULT, // 默认不贴边 LEFT, RIGHT, TOP, BOTTOM, // 四个方向固定 AUTO_HORIZONTAL, AUTO_VERTICAL, AUTO_SIDE, // 自动贴边 RESULT_LEFT, RESULT_RIGHT, RESULT_TOP, RESULT_BOTTOM, // 拖拽结束贴边 RESULT_HORIZONTAL, RESULT_VERTICAL, RESULT_SIDE }动画系统同样采用策略模式允许开发者自定义入场和出场动画// 在AnimatorManager.kt中 internal class AnimatorManager( private val view: View, private val params: WindowManager.LayoutParams, private val windowManager: WindowManager, private val config: FloatConfig ) { fun enterAnim(): Animator? config.floatAnimator?.enterAnim(view, params, windowManager, config.sidePattern) fun exitAnim(): Animator? config.floatAnimator?.exitAnim(view, params, windowManager, config.sidePattern) }图EasyFloat的拖拽功能演示 权限管理机制EasyFloat的权限系统设计得非常智能支持自动权限检测和申请// 在EasyFloat.kt的Builder类中 fun show() when { config.layoutId null config.layoutView null - callbackCreateFailed(WARN_NO_LAYOUT) config.showPattern ShowPattern.CURRENT_ACTIVITY - createFloat() PermissionUtils.checkPermission(activity) - createFloat() else - requestPermission() }权限处理流程当前Activity浮窗无需权限直接创建系统浮窗先检查权限有权限则创建无权限则自动申请权限回调申请结果通过OnPermissionResult接口回调 多浮窗支持与生命周期管理EasyFloat支持多个浮窗同时存在每个浮窗通过唯一的tag进行管理// 使用示例 EasyFloat.with(this) .setTag(chatHead) .setLayout(R.layout.float_chat) .show() EasyFloat.with(this) .setTag(musicPlayer) .setLayout(R.layout.float_music) .show()生命周期管理策略Activity浮窗随Activity销毁自动移除系统浮窗需要手动管理或结合应用生命周期前台/后台显示通过ShowPattern控制浮窗的显示时机 DSL支持与回调系统EasyFloat为Kotlin用户提供了DSL领域特定语言支持EasyFloat.with(this) .setLayout(R.layout.float_app) .registerCallback { createResult { isCreated, msg, view - // 创建结果回调 } show { // 显示回调 } hide { // 隐藏回调 } drag { view, motionEvent - // 拖拽过程回调 } } .show()这种设计让代码更加简洁和类型安全同时保持了与Java的兼容性。 扩展性与自定义EasyFloat的架构设计极具扩展性自定义动画实现OnFloatAnimator接口自定义拖拽逻辑重写TouchUtils类自定义视图通过setLayout()方法传入自定义View自定义权限处理扩展PermissionUtils类 最佳实践与性能优化基于源码分析我们总结出以下最佳实践合理使用Tag多浮窗场景必须设置不同的tag选择合适的显示模式根据需求选择CURRENT_ACTIVITY、FOREGROUND或ALL_TIME内存优化及时调用dismiss()释放资源权限处理在适当时机申请系统浮窗权限 总结通过深入分析EasyFloat的源码我们可以看到其优秀的设计理念清晰的架构分层各模块职责单一耦合度低灵活的配置系统Builder模式 FloatConfig数据类强大的窗口管理支持多浮窗、多种显示模式完善的权限处理自动检测、申请和回调良好的扩展性策略模式支持自定义动画和拖拽逻辑EasyFloat的成功不仅在于其功能的完备性更在于其优雅的设计和清晰的代码结构。无论是学习Android窗口系统还是在实际项目中使用悬浮窗功能EasyFloat都是一个值得深入研究和借鉴的优秀开源项目。源码路径参考核心API类EasyFloat.kt配置管理类FloatConfig.kt窗口管理类FloatingWindowManager.kt窗口助手类FloatingWindowHelper.kt拖拽工具类TouchUtils.kt【免费下载链接】EasyFloat EasyFloat浮窗从未如此简单Android可拖拽悬浮窗口支持页面过滤、自定义动画可设置单页面浮窗、前台浮窗、全局浮窗浮窗权限按需自动申请...项目地址: https://gitcode.com/gh_mirrors/ea/EasyFloat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考