Giter Site home page Giter Site logo

princekin-f / easyfloat Goto Github PK

View Code? Open in Web Editor NEW
3.3K 37.0 424.0 27.76 MB

🔥 EasyFloat:浮窗从未如此简单(Android可拖拽悬浮窗口,支持页面过滤、自定义动画,可设置单页面浮窗、前台浮窗、全局浮窗,浮窗权限按需自动申请...)

License: Apache License 2.0

Java 14.13% Kotlin 85.87%
kotlin android floating floating-window floating-view kotlin-dsl kotlin-dsl-java

easyfloat's Issues

悬浮窗

您好 您发布的悬浮窗项目 今天用到了 很棒
但是 发现弹框布局中出现的输入框能获取到焦点 但是不能输入 请问这个问题从哪里入手解决。

已经解决谢谢!

虚拟大师(安卓真机里的 安卓模拟器)
EasyFloat.hideAppFloat()
EasyFloat.showAppFloat()
EasyFloat.dismissAppFloat()失效咋办··

系统级弹窗消失与新建问题

首先很感谢开源这个项目,在使用当中有些地方发现的问题提出一下,
设置了 .setSidePattern(SidePattern.TOP) 之后 配合 .setGravity(Gravity.TOP, 0, 20)这个偏移 拖动功能就失效了。我的设置总属性如下:
EasyFloat.with(this).setLayout(R.layout.item_float_top_view)
.setMatchParent(true, false)
// .setSidePattern(SidePattern.TOP)
.setTag("only" + i)
.setDragEnable(true)
.setShowPattern(ShowPattern.FOREGROUND)
.setGravity(Gravity.TOP, 0, 20)

            .setAppFloatAnimator(null)
            .invokeView(this)
            .show();

因业务需要 弹窗会被下一个弹窗顶掉 也就是弹窗内容改变 可是 .invokeView(this) 的话貌似只能在新弹窗才能更新xml内容
然后在创新新弹窗和销毁上一个弹窗的时候 出现了一个问题 首先代码如下

private int i = 0;
@Override
public void invoke(View floatingView) {
    ((TextView) floatingView.findViewById(R.id.tv_tip_show)).setText("电");
    ((TextView) floatingView.findViewById(R.id.tv_tip_content)).setText("电气工程" + i);
}
@OnClick(R.id.btn)
public void onViewClicked() {
    if (EasyFloat.appFloatIsShow("only"+i)) {
        EasyFloat.dismissAppFloat(this, "only"+i);
    }
    i++;
    showFloat();
}

先判断是否显示 然后dismiss掉它 再show一个不同的tag 此时发现一个问题 0-1 Floatservice 正常启动 然后在 1-2的过程中 dismiss 1 之后 此时 2还未被启动 也就未添加到 floatTag 中 然后在1完结动画后 就stopService了 就这样 2 成了孤儿。。而后续 又因为 2被添加进了 floatTag 并且不会被清除,所以后续的 3 ,4等tag /**
* 关闭浮窗后,检测是否需要关闭Service
*/
fun checkStop(context: Context, floatTag: String?) {
// 先清除当条浮窗信息
if (floatMap.isNotEmpty()) floatMap.remove(floatTag)
// 如有没有其他浮窗存在,关闭Service
if (floatMap.isEmpty()) context.stopService(Intent(context, FloatService::class.java))
}
并不会stopService 就独独 2 会很尴尬

我的解决方法是
private int i = 0;
private int oldI = 0;
@OnClick(R.id.btn)
public void onViewClicked() {
oldI = i;
i++;
showFloat();
if (EasyFloat.appFloatIsShow("only" + oldI)) {
EasyFloat.dismissAppFloat(this, "only" + oldI);
}
}
先show 后 dismiss 目前看 是不会stopService 了所以每一个dismiss 都会执行。
当然 还是 希望能优化 这部分。。。

请问如何获取拖动后图片的xy轴坐标呢?

我是通过xml布局加载出来的,想要获取该图片在middle_constraintlayout这个ConstraintLayout布局内的xy轴坐标,而不是整个手机屏幕的坐标

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<androidx.appcompat.widget.Toolbar
    android:id="@+id/toolbar_yiyilingqi"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#3300ff00"
    app:layout_constraintTop_toTopOf="parent">

</androidx.appcompat.widget.Toolbar>

<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/middle_constraintlayout"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    app:layout_constraintBottom_toTopOf="@id/tl_bottom"
    android:background="#330000ff"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toBottomOf="@id/toolbar_yiyilingqi">

    <com.lzf.easyfloat.widget.activityfloat.FloatingView
        android:id="@+id/floatingView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src="@mipmap/ic_launcher_round" />

    </com.lzf.easyfloat.widget.activityfloat.FloatingView>

</androidx.constraintlayout.widget.ConstraintLayout>

<androidx.appcompat.widget.Toolbar
    android:id="@+id/tl_bottom"
    app:layout_constraintBottom_toBottomOf="parent"
    android:layout_width="match_parent"
    android:background="#ffffff"
    android:layout_height="wrap_content">

</androidx.appcompat.widget.Toolbar>

</androidx.constraintlayout.widget.ConstraintLayout>

过滤Activity时失灵

我在自己项目集成,在一个被设置成过滤的Activity里面触发悬浮窗的显示;
说明:activity1:主界面(显示和隐藏的逻辑都在这里)
activity2:触发界面,被设置成过滤不显示
activity3:其他界面
bug1: 从1到2,在2里面点击触发,发送EvenBus,1收到后显示;这个时候2并没有被过滤掉。
bug2:退出2回到1,正常显示,重新进入2,发现被过滤了,返回2回到1,1也不显示了,直到进入3,又恢复正常显示。

我在demo上操作上面流程没问题,但是由于我的项目比较复杂,应该是有某些冲突,我该从什么地方入手找原因解决他。谢谢。

能否添加透过系统悬浮窗点击浮窗下面的按钮API

希望能提供动态修改WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
这样的API。
因为有的浮窗只是展示用,不需要按钮点击。希望能透过浮窗直接点击或滚动浮窗下面的按钮或界面,浮窗不占用浮窗区域的焦点。

魅族手机,

fragment.startActivityForResult启动设置页面,会立马在OnActivityResult中响应。

类似QQ/wx 通知消息屏幕最上方悬浮

大佬你好 ,我想实现一个推送消息来了,在屏幕上方出现一个消息框,前台的,用户点击或触摸就可以自动划上去,控制用户只能往上滑动。这个怎么实现呢

无法同时创建多个系统悬浮窗

连续两次创建悬浮窗代码如下

    override fun openFloatWindow() {
        EasyFloat.with(AppManager.getAppManager().currentActivity())
            // 设置浮窗xml布局文件
            .setLayout(R.layout.float_window_select_question)
            // 设置浮窗显示类型,默认只在当前Activity显示,可选一直显示、仅前台显示
            .setShowPattern(ShowPattern.ALL_TIME)
            // 设置浮窗的标签,用于区分多个浮窗
            .setTag("selectQuestion")
            // 设置浮窗固定坐标,ps:设置固定坐标,Gravity属性和offset属性将无效
            .setLocation(ConvertUtils.dp2px(64f), ConvertUtils.dp2px(128f))
            // 设置我们传入xml布局的详细信息
            .invokeView(OnInvokeView {
                val rootView = it.findViewById<ConstraintLayout>(R.id.cl_root_view)
                val params = rootView.layoutParams as ViewGroup.LayoutParams
                it.findViewById<ScaleImage>(R.id.img_scale).onScaledListener =
                    object : ScaleImage.OnScaledListener {
                        override fun onScaled(x: Float, y: Float, event: MotionEvent) {
                            params.width += x.toInt()
                            params.height += y.toInt()
                            rootView.layoutParams = params
                        }
                    }
            })
            .show()

        EasyFloat.with(AppManager.getAppManager().currentActivity())
            // 设置浮窗xml布局文件
            .setLayout(R.layout.float_window_get_answer)
            // 设置浮窗显示类型,默认只在当前Activity显示,可选一直显示、仅前台显示
            .setShowPattern(ShowPattern.ALL_TIME)
            // 设置浮窗的标签,用于区分多个浮窗
            .setTag("getAnswer")
            // 设置浮窗固定坐标,ps:设置固定坐标,Gravity属性和offset属性将无效
            .setLocation(ConvertUtils.dp2px(30f), ConvertUtils.dp2px(500f))
            // 设置我们传入xml布局的详细信息
            .invokeView(OnInvokeView {

            })
            // 创建浮窗(不要忘记哦😂)
            .show()
    }

排查了下,发现原因是因为FloatService中的config属性导致

companion object {
        private const val FLOAT_ACTION = "floatAction"
        private const val FLOAT_VISIBLE = "floatVisible"
        private const val FLOAT_DISMISS = "floatDismiss"
        private const val FLOAT_TAG = "floatTag"
        const val DEFAULT_TAG = "default"
        val floatMap = mutableMapOf<String, AppFloatManager>()
        private var config = FloatConfig()

        /**
         * 开启创建浮窗的Service
         */
        fun startService(context: Context, floatConfig: FloatConfig) {
            config = floatConfig
            context.startService(Intent(context, FloatService::class.java))
        }
}

由于config是静态变量,因此当连续两次调用startService的时候,第二次的config中的tag会把第一次config中的tag给覆盖掉,导致第二次的checkTag()方法返回false

另外这是个很棒的库,感谢大佬,最近项目正好需要用到

创建2个系统悬浮窗失败

EasyFloat.with(activity)
.setShowPattern(ShowPattern.ALL_TIME)
.setSidePattern(SidePattern.RESULT_SIDE)
.setDragEnable(true)
.setTag(TAG_START)
.setGravity(Gravity.END | Gravity.CENTER_VERTICAL, 0, 200)
.setFilter(MainActivity.class)
.setLayout(R.layout.float_item)
.show();

EasyFloat.with(activity)
.setShowPattern(ShowPattern.ALL_TIME)
.setSidePattern(SidePattern.RESULT_SIDE)
.setDragEnable(true)
.setTag(TAG_END)
.setGravity(Gravity.END | Gravity.CENTER_VERTICAL, 0, 200)
.setFilter(MainActivity.class)
.setLayout(R.layout.float_item)
.show();

以上是创建系统悬浮窗的代码,执行时,只能显示最后创建的系统悬浮窗,我也尝试过在两次创建时间增加等待时间,还是不行,大家可以帮看下吗?

AndroidX 怎么办?

项目使用的AndroidX.
集成之后:implementation 'com.github.princekin-f:EasyFloat:1.1.0'
提示:Error: Program type already present: androidx.asynclayoutinflater.view.AsyncLayoutInflater$1
大佬可否提供androidX版本的支持?

希望能开放出 申请权限的方法

/**
* 申请悬浮窗权限
*/
internal fun requestPermission(activity: Activity, onPermissionResult: OnPermissionResult) {
PermissionFragment.requestPermission(activity, onPermissionResult)
}
就是这个方法啦 因为想在开始 就引导用户开启 而不是在触发的时候 使用 有时候 权限回调 并没有回来 。。。

悬浮窗输入文本后,点击返回键没有反应的处理办法

可以在根布局视图类添加

@Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
    boolean result = super.dispatchKeyEventPreIme(event);
    if (event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
        InputMethodUtils.closedInputMethod(FLOAT_TAG);
    }
    return result;
}

Failed to set EGL_SWAP_BEHAVIOR on surface

E/EGL_emulation: tid 1728: eglSurfaceAttrib(1210): error 0x3009 (EGL_BAD_MATCH) W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xc917edc0, error=EGL_BAD_MATCH
android 8.0上直接崩溃了、其他版本都是可以的。 @princekin-f

设置系统浮窗的不需要显示的页面 bug

// 设置系统浮窗的不需要显示的页面
.setFilter(MainActivity::class.java, SecondActivity::class.java)
不起作用在demo上和我自己的项目上试了不起作用,还是显示

设置动画无效

class EasyMain : OnFloatAnimator {

override fun enterAnim(view: View, parentView: ViewGroup, sidePattern: SidePattern): Animator? {
    val ofFloat = ObjectAnimator.ofFloat(
        view,
        "translationX",
        view.translationX,
        0f
    )
    ofFloat.duration = 2000
    return ofFloat
}

override fun exitAnim(view: View, parentView: ViewGroup, sidePattern: SidePattern): Animator? {
    val ofFloat = ObjectAnimator.ofFloat(
        view,
        "translationX",
        view.translationX,
        PixelChange.dp2px(view.context, 100f).toFloat()
    )
    ofFloat.duration = 2000
    return ofFloat
}

}

奇怪requestPermission报错了

/**
* 申请悬浮窗权限
*/
fun requestPermission(activity: Activity, onPermissionResult: OnPermissionResult) {
PermissionFragment.requestPermission(activity, onPermissionResult)
}

方法报错了,无法从静态上下文中引用非静态
我自己加上了@JvmStatic就可以了,不知道为什么Demo里的不会报错

/**
* 主动申请浮窗权限
*/
private fun requestPermission() {
PermissionUtils.requestPermission(this, object : OnPermissionResult {
override fun permissionResult(isOpen: Boolean) {
logger.i(isOpen)
}
})
}

希望能增加个允许重新setGrivity的方法

如果setGrivity为Grivity.End,然后布局的宽度改变了,悬浮窗就没法自动贴在屏幕右侧,仍是原来的位置。看了一下源码,希望能把AppFloatManager.setGrivaity由EasyFloat暴露出来,这样就可以手动调用

.registerCallbacks { show {} } 中, show{}函数不会被回调

部分代码

fun showWindow() {
        var btnBack: ImageView? = null

        EasyFloat.with(activity)
            .setShowPattern(ShowPattern.ALL_TIME)
            .setSidePattern(SidePattern.TOP)
            .setDragEnable(false)
            .setAnimator(null)
            .setMatchParent(widthMatch = true, heightMatch = true)
            .setGravity(Gravity.CENTER, 0, 51)
            .startForeground(true, myNotification(activity))
            .setLayout(R.layout.window_doorlock_video_call, OnInvokeView { root ->
                root?.let {
                    btnBack = root.findViewById(R.id.iv_calling_back)
                    
                }
                btnBack?.setOnClickListener {
                    
                }
            })
            .registerCallbacks {
                //                createResult { isCreated, msg, view -> }
//                hide {  }
//                touchEvent { view, motionEvent ->
//                    IdleMode.instance.resetCountdown()
//                }
//                drag { view, motionEvent ->  }
//                dragEnd {  }
                show {
                    Log.i(TAG, "showWindow show")  //此处不会有打印
                }
                dismiss {
                    Log.i(TAG, "showWindow dismiss")
                   
                }
            }
            .show()

申请悬浮窗权限会导致app奔溃

我进入app悬浮窗权限设置的页面选择允许后,APP会报
E/InputDispatcher: channel '718ffe2 com.loma.im/com.xxxx.activity.MainActivity (server)' ~ Channel is unrecoverably broken and will be disposed!

然后app重启,是什么原因呢?

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.