admin管理员组

文章数量:1635371

效果演示:
悬浮小球在移动时会换成一张图片,当松开时,会自动停靠在一侧,并且恢复原来的形式。
点击悬浮小球,会从屏幕底部滑入一个菜单栏。
双击加速球,会有水不断注入的动画效果,并且水面逐渐平静下来。
单击加速球,水面会震荡,最后恢复平静。

这个的实现是观看了慕课网视频后,在其基础上做了一些适当的修改,如:在android23以上,如何申请动态权限。因为这个实现需要用到一个危险权限,弹出窗口。有兴趣的可以前往:http://www.imooc/learn/693。

整体思路:
可以看下项目结构。在MainActivity开启了一个服务MyFloatService,这个服务获得了FloatViewManager管理类的实例,view包下有悬浮球的view以及加速球的view。而这个管理类则可控制这些view的显示,隐藏,位置。开启服务后,显示了悬浮球,通过对悬浮球进行Touch事件的监听,实现了拖动改变图片,自动停靠在一侧,单击出现菜单栏。在菜单栏的FloatMenuView类中,实现了对自身的Touch监听,双击出现水不断注入效果,单击水面震荡。单击加速球其他的地方则隐藏菜单栏。

源码已经开放在github上:https://github/My-Zzw/FloatView360Demo

在这篇文章中,简单提一下使用到的技巧,以及一些主要的思路,一些思想,一些需要注意的地方。

1.权限问题
当点击主界面的开启悬浮窗按钮时,开启MyFloatService服务。当服务创建时,进行判断,如果运行在大于等于6.0系统上,则跳转到应用信任界面,允许该应用所有权限。在这个项目中,需要用到 SYSTEM_ALERT_WINDOW 权限,记得要在manifest中注册。

@Override
    public void onCreate() {
        FloatViewManager manager = FloatViewManager.getInstance(this);
        manager.showFloatCircleView();//弹出一个窗口,需要权限。>=23,需要动态申请。
        super.onCreate();
    }

2.在FloatViewManager中,是如何控制悬浮球以及菜单栏显示和隐藏的。
首先已经实例化了悬浮球View和菜单栏的View

 //实例化悬浮球View
 floatCircleView = new FloatCircleView(context);
 //实例化菜单View
 floatMenuView = new FloatMenuView(context);

已经实例化了View。那么View要显示在界面,就需要一些布局参数,比如view的宽和高,位置在哪里?所以需要一个 WindowManager.LayoutParams 对象。这样,要显示的view已经拿到,如何显示也拿到,那么就可以添加到界面显示了。显示到界面上让用户看到,需要实例化一个 WindowManager 的对象,通过其addView方法添加到窗口。例如显示悬浮窗。

//显示菜单栏
    private void showFloatMenuView() {
        WindowManager.LayoutParams params2 = new WindowManager.LayoutParams();
        params2.width = getScreenWidth();
        params2.height = getScreenHeight() - getStatusHeigt();//高度为全屏。
        params2.gravity = Gravity.BOTTOM | Gravity.LEFT;
        params2.x = 0;
        params2.y = 0;
        params2.type = WindowManager.LayoutParams.TYPE_PHONE;//布局参数的类型为手机类型。意味着 在所有页面的上面。
        params2.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;//不和其他应用抢焦点
        params2.format = PixelFormat.RGBA_8888;//设置透明度

        windowManager.addView(floatMenuView, params2);//通过manager添加视图到窗口。第一个参数为要添加的view,第二个为view的布局参数
    }

3.实现悬浮窗在点击移动时变成一张火箭的图片,松开时自动附着在其中一侧。
首先对悬浮窗注册一个事件监听器。类型为触摸事件。

//注册触摸事件监听器
floatCircleView.setOnTouchListener(circleViewOnTouchListener);

接着实现这个事件监听器的触发事件。当用户按下,移动,抬起时。
需要说明的是,当监听到用户在移动这个悬浮球时,调用了悬浮球对象的setDrawState方法通知到这个悬浮球在移动中,那么悬浮球对象就会调用invalidate进行重绘。在onDraw方法去drawBitmap。
当用户松开时,判断最后松开的悬浮窗x坐标如果大于或者小于屏幕的一半,修改悬浮窗的params.x布局参数的x坐标。最后调用updateViewLayout方法,更新悬浮窗。

 //监听的内部类
    private View.OnTouchListener circleViewOnTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {

            switch (motionEvent.getAction()) {
                case MotionEvent.ACTI

本文标签: 效果