Giter VIP home page Giter VIP logo

easyfloat's Introduction

前言

全局悬浮窗是项目中的一个常见需求,目前比较常见的实现是将要悬浮的View添加到WindowManager

这种方案的主要痛点在于需要用户申请TYPE_SYSTEM_ALERT权限,并且需要用户去设置中手动打开,使用起来很不方便,同时需要申请权限可能会劝退用户.

针对这种情况下面介绍一种不需要权限的悬浮窗方案

效果图

首先看下最终的效果图

特性

  • 1.不需要申请权限,可以直接打开悬浮窗,使用便捷
  • 2.支持自定义布局,自定义显示样式,自定义初始显示位置
  • 3.支持拖拽,可自动吸附到屏幕边缘
  • 4.可过滤不需要显示悬浮窗的黑名单界面
  • 5.支持自定义点击事件,可支持展开折叠等功能
  • 6.API链式调用,使用简洁优雅
  • 7.添加是否可拖动,是否自动靠边的配置和对应状态的获取

集成

第 1 步:在工程的 build.gradle 中添加:

allprojects {
	repositories {
		...
		mavenCentral()
	}
}

第2步:在应用的 build.gradle 中添加:

dependencies {
        implementation 'io.github.shenzhen2017:easyfloat:1.0.2'
}

使用

API链式调用,使用起来非常方便

1.初始化

    EasyFloat
        .layout(R.layout.layout_float_view)
        .blackList(mutableListOf(ThirdActivity::class.java))
        .layoutParams(initLayoutParams())
        .listener {
            initListener(it)
        }
        .show(this)

如上所示:

1.通过layout指定自定义布局

2.通过blackList指定不展示悬浮窗界面

3.通过layoutParams指定初始展示位置

4.通过listener处理自定义点击事件

2.销毁悬浮窗

	EasyFloat.dismiss(this)

直接调用dismiss销毁即可

主要原理

我们都知道,当我们需要设置布局的时候,是通过setContentView设置的

setContentView实际上是将我们的布局添加到了DecoreView上,布局层级如下所示:

1.Activity 类似于一个框架,负责容器生命周期及活动,窗口通过 Window 来管理;

2.Window 负责窗口管理(实际是子类 PhoneWindow),窗口的绘制和渲染交给 DecorView完成;

3.DecorViewView 树的根,开发人员为 Activity 定义的 layout 将成为 DecorView 的子视图 ContentParent 的子视图;

4.layout.xml 是开发人员定义的布局文件,最终 inflateDecorView 的子组件;

由上我们可以想到一个方案: 我们在Activity onStart时,将要悬浮的View添加到ContentParent上就可以实现不需要权限的悬浮窗了

当然我们还需要注意以下几点

1.因为我们需要在多个页面展示悬浮窗,可以通过ActivityLifecycleCallbacks监听所有Activity的生命周期,onStart时添加,onStop时移除

2.因为要在多个页面共享状态,所以应该有一个单例类管理View,做到只创建一个View,页面切换时只做添加与移除

3.因为要添加到ContentParent中,持有了Activity的引用,所以要注意处理内存泄漏的问题,在项目中我们使用了弱引用来防止内存泄漏

部分代码如下:

object EasyFloat : Application.ActivityLifecycleCallbacks {
    override fun onActivityStarted(activity: Activity) {
         FloatingView.get().attach(it)
    }

    override fun onActivityStopped(activity: Activity) {
        FloatingView.get().detach(activity)
    }

    fun show(activity: Activity) {
        initShow(activity)
        activity.application.registerActivityLifecycleCallbacks(this)
    }

    fun dismiss(activity: Activity) {
        FloatingView.get().remove()
        FloatingView.get().detach(activity)
        activity.application.unregisterActivityLifecycleCallbacks(this)
    }
}

总结

特别鸣谢

在实现这个开源框架的过程中,主要借鉴了EnFloatingView的一些思路

并在其基础上进行了一定的封装,优化了API调用并解决了滑动冲突等一些问题

项目地址

EasyFloat

开源不易,如果项目对你有所帮助,欢迎点赞,Star,收藏~

easyfloat's People

Contributors

ricardojiang avatar sposer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

easyfloat's Issues

关于悬浮窗显示了两个的问题

作者你好,我是一个Android开发者,首先感谢你的开源项目。
这里描述一个非常令人费解的问题。

页面上悬浮窗的实例显示了两个。

需求:
首页MainActivity 5个tab栏,viewpager2 + fragment实现,需要在跳转到第三个tab时显示悬浮窗,跳转到其他tab页或进入到其它页面关闭即可。

逻辑:
在MainActivity 中的 onResume() 中 判断是第三个tab 显示悬浮窗。在 onPause() 中关闭悬浮窗。
在viewpager切换到第三个 tab显示悬浮窗,切换到其它的关闭悬浮窗。

现象:
目前可知项目使用了大于几千次,出现了两次实例出现了两次的异常情况,亲眼所见,且后台无异常信息。异常时,一个实例一直存在,切换页面,拖动,点击事件等此实例都是没问题的,且 切换页面后可以记录位置,可证明是同一个实例,另一个跟随正常逻辑显示和关闭。即当切换到第三个tab栏时,会显示两个(应该只有一个)两个都拥有正常功能,其它页面一直存在一个(不应该有)。

操作:
随意点击页面切换,跳转,发现 不应该显示的页面显示了一个,切换到应该显示的第三个页面,看到了两个。

通过代码可知悬浮窗是单例的,我通过代码不断执行show()方法打开 实例也只会存在一个,所以出现了这种情况令我很头疼。

悬浮窗宽度移动问题。

在移动悬浮窗口时移动的宽度没有做限制,导致可以把悬浮窗口移动屏幕外这样子,滑动感觉很难受。看了一下你的源码。只是做了高度限制,没有做宽度限制,应该在宽度哪里增加判断如图
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.