• Android -- 使用WindowManager实现悬浮框效果


    1,原文在这里http://blog.csdn.net/qq_17250009/article/details/52908791,我只是把里面的关键步骤给注释了一下,首先来看一下我们的效果,如图(电脑太卡,截图有问题,见谅):

    2,来看一下我们的实现步骤,首先创建一个service,用于将我们的布局悬浮到我们的Android系统上去,然后通过activity来启动这个service,所以代码如下:

    MainActivity.java

    package com.qianmo.suspendcircle;
    
    import android.content.Intent;
    import android.os.Bundle;
    import android.support.design.widget.FloatingActionButton;
    import android.support.design.widget.Snackbar;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.Toolbar;
    import android.view.View;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.widget.Button;
    
    import static android.icu.lang.UCharacter.GraphemeClusterBreak.V;
    import static android.os.Build.VERSION_CODES.M;
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
        private Button btn_start;
        private Button btn_end;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            btn_start = (Button) findViewById(R.id.btn_start);
            btn_end = (Button) findViewById(R.id.btn_end);
            btn_start.setOnClickListener(this);
            btn_end.setOnClickListener(this);
            setSupportActionBar(toolbar);
    
            FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
            fab.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                            .setAction("Action", null).show();
                }
            });
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.menu_main, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
    
            //noinspection SimplifiableIfStatement
            if (id == R.id.action_settings) {
                return true;
            }
    
            return super.onOptionsItemSelected(item);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                //启动服务
                case R.id.btn_start:
                    Intent intent = new Intent(MainActivity.this, WindowService.class);
                    startService(intent);
                    break;
                //停止服务
                case R.id.btn_end:
                    Intent intent1 = new Intent(MainActivity.this, WindowService.class);
                    stopService(intent1);
                    break;
            }
        }
    }
    

    MainActivity这个没什么好说的,就是启动service和关闭service而已,主要是那个Service,代码如下:

    WindowService.java

    package com.qianmo.suspendcircle;
    
    import android.app.ActivityManager;
    import android.app.Service;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.graphics.PixelFormat;
    import android.os.IBinder;
    import android.support.annotation.Nullable;
    import android.util.Log;
    import android.view.Gravity;
    import android.view.LayoutInflater;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.WindowManager;
    import android.widget.TextView;
    
    import java.util.List;
    
    
    
    
    /**
     * Created by Administrator on 2017/2/9 0009.
     * E-Mail:543441727@qq.com
     */
    
    public class WindowService extends Service {
        private final String TAG = this.getClass().getSimpleName();
    
        private WindowManager.LayoutParams wmParams;
        private WindowManager mWindowManager;
        private View mWindowView;
        private TextView mPercenrTv;
    
        private int mStartX;
        private int mStartY;
        private int mEndX;
        private int mEndY;
    
        @Override
        public void onCreate() {
            super.onCreate();
            Log.i(TAG, "Create");
            initWindowParams();
            initView();
            addWindowViewZWindow();
            initClick();
        }
    
        /**
         * 点击事件和拖拽事件
         */
        private void initClick() {
            mPercenrTv.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch (event.getAction()) {
                        //按下鼠标的时候记录下屏幕的位置
                        case MotionEvent.ACTION_DOWN:
                            mStartX = (int) event.getRawX();
                            mStartY = (int) event.getRawY();
    
                            break;
                        case MotionEvent.ACTION_MOVE:
                            mEndX = (int) event.getRawX();
                            mEndY = (int) event.getRawY();
                            if (needIntercept()) {
                                //getRawX是触摸位置相对于整个屏幕的位置,getX是控触摸点相对于控件最左边的位置
                                wmParams.x = (int) event.getRawX() - mWindowView.getMeasuredWidth() / 2;
                                wmParams.y = (int) event.getRawY() - mWindowView.getMeasuredHeight() / 2;
                                mWindowManager.updateViewLayout(mWindowView, wmParams);
                                return true;
                            }
                            break;
                        case MotionEvent.ACTION_UP:
                            if (needIntercept()) {
                                return true;
                            }
                            break;
                    }
    
                    return false;
                }
            });
    
            mPercenrTv.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.i(TAG, "点击了");
                    if (isAppAtBackground(WindowService.this)) {
                        Intent intent = new Intent(WindowService.this, MainActivity.class);
                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startActivity(intent);
                    }
                }
            });
    
    
        }
    
        /**
         * 判断当前应用是前台还是后台
         */
        private boolean isAppAtBackground(final Context context) {
            ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
            List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
            if (!tasks.isEmpty()) {
                ComponentName topActivity = tasks.get(0).topActivity;
                if (!topActivity.getPackageName().equals(context.getPackageName())) {
                    return true;
                }
            }
            return false;
        }
    
        /**
         * 判断是否拦截,根据滑动的距离
         *
         * @return
         */
        private boolean needIntercept() {
            if (Math.abs(mStartX - mEndX) > 30 || Math.abs(mStartY - mEndY) > 30) {
                return true;
            }
            return false;
        }
    
        /**
         * 添加View到桌面Window界面上
         */
        private void addWindowViewZWindow() {
            mWindowManager.addView(mWindowView, wmParams);
        }
    
        /**
         * 初始化加速球控件
         */
        private void initView() {
            mWindowView = LayoutInflater.from(getApplication()).inflate(R.layout.layout_window, null);
            mPercenrTv = (TextView) mWindowView.findViewById(R.id.percentTv);
        }
    
        /**
         * 初始化Window对象的参数
         */
        private void initWindowParams() {
            //1,获取系统级别的WindowManager
            mWindowManager = (WindowManager) getApplication().getSystemService(getApplication().WINDOW_SERVICE);
            wmParams = new WindowManager.LayoutParams();
    
            //2,添加系统参数,确保悬浮框能显示到手机上
    
            //电话窗口。它用于电话交互(特别是呼入)。它置于所有应用程序之上,状态栏之下。
            wmParams.type = WindowManager.LayoutParams.TYPE_PHONE;
            //期望的位图格式。默认为不透明
            wmParams.format = PixelFormat.TRANSLUCENT;
            //不许获得焦点
            wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
            //窗口停靠位置
            wmParams.gravity = Gravity.LEFT | Gravity.TOP;
            wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
            wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
    
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            if (mWindowView != null) {
                //移除悬浮窗口
                Log.i(TAG, "removeView");
                mWindowManager.removeView(mWindowView);
            }
            Log.i(TAG, "onDestroy");
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    }
    

     由于注释很详细了,就不给大家说代码了

     最后附上源码地址: https://github.com/543441727/SuspendWindow.git

  • 相关阅读:
    List<Object> 查询解析优化
    hibernate 中 query.list()的优化
    移动端屏幕宽度自适应原理及实现
    js获取用户当前地理位置(省、市、经纬度)
    mescroll.js简单的上拉加载、下拉刷新插件,带完整注释
    Web前端性能优化总结——如何提高网页加载速度
    浏览器渲染页面的原理及流程
    优酷1080p的kux格式文件怎么转换为MP4格式?
    js处理文章详情页点击量统计
    plupload上传视频插件jQuery+php
  • 原文地址:https://www.cnblogs.com/wjtaigwh/p/6383208.html
Copyright © 2020-2023  润新知