创建系统覆盖窗口(总在最前) [英] Creating a system overlay window (always on top)

查看:130
本文介绍了创建系统覆盖窗口(总在最前)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创造一个永远运顶部的按钮/点击图像 它停留在所有窗口的顶部所有的时间。

的证明 概念

我 下面从Android源$ C ​​$ C此示例code

  • <一个href="https://github.com/android/platform_frameworks_base/blob/master/packages/SystemUI/src/com/android/systemui/LoadAverageService.java">LoadAverageService.java

我是成功的,现在有一个正在运行的服务。服务 在屏幕上显示的左上角,而所有的时间一些文本 用户可以自由地在正常的方式休息的应用程序进行交互。

我是什么 做的是子类的ViewGroup ,并把它添加到根窗口管理器 标志 TYPE_SYSTEM_OVERLAY 。现在,我想添加一个按钮/可点击图像 到位本文能对自己接收触摸事件。一世 试图重写的onTouchEvent整个的ViewGroup ,但它确实 没有收到任何事件。

我怎么能接受事件仅在某些部位 我总在顶视图组?请建议。

 公共类HUD延伸服务{
    HUDView MView的;

    @覆盖
    公众的IBinder onBind(意向意图){
        返回null;
    }

    @覆盖
    公共无效的onCreate(){
        super.onCreate();
        Toast.makeText(getBaseContext(),的onCreate,Toast.LENGTH_LONG).show();
        MVIEW =新HUDView(本);
        WindowManager.LayoutParams PARAMS =新WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                0,
// WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
// | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.RIGHT | Gravity.TOP;
        params.setTitle(平均负载);
        窗口管理WM =(窗口管理器)getSystemService(WINDOW_SERVICE);
        wm.addView(MVIEW,则params);
    }

    @覆盖
    公共无效的onDestroy(){
        super.onDestroy();
        Toast.makeText(getBaseContext(),的onDestroy,Toast.LENGTH_LONG).show();
        如果(MVIEW!= NULL)
        {
            ((窗口管理器)getSystemService(WINDOW_SERVICE))removeView(MVIEW)。
            MVIEW = NULL;
        }
    }
}

类HUDView扩展的ViewGroup {
    私人油漆mLoadPaint;

    公共HUDView(上下文的背景下){
        超(上下文);
        Toast.makeText(的getContext(),HUDView,Toast.LENGTH_LONG).show();

        mLoadPaint =新的油漆();
        mLoadPaint.setAntiAlias​​(真正的);
        mLoadPaint.setTextSize(10);
        mLoadPaint.setARGB(255,255,0,0);
    }

    @覆盖
    保护无效的OnDraw(帆布油画){
        super.onDraw(画布);
        canvas.drawText(的Hello World,5,15,mLoadPaint);
    }

    @覆盖
    保护无效onLayout(布尔为arg0,诠释ARG1,诠释ARG2,诠释ARG3,诠释ARG4){
    }

    @覆盖
    公共布尔的onTouchEvent(MotionEvent事件){
        //返回super.onTouchEvent(事件);
        Toast.makeText(的getContext(),的onTouchEvent,Toast.LENGTH_LONG).show();
        返回true;
    }
}
 

解决方案

这可能是一个愚蠢的解决方案。但是,它的工作原理。如果你能改善它,请让我知道。

在OnCreate您服务的:我已经使用 WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH 标志。这是服务的唯一变化。

  @覆盖
    公共无效的onCreate(){
        super.onCreate();
        Toast.makeText(getBaseContext(),的onCreate,Toast.LENGTH_LONG).show();
        MVIEW =新HUDView(本);
        WindowManager.LayoutParams PARAMS =新WindowManager.LayoutParams(
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.RIGHT | Gravity.TOP;
        params.setTitle(平均负载);
        窗口管理WM =(窗口管理器)getSystemService(WINDOW_SERVICE);
        wm.addView(MVIEW,则params);
    }
 

现在,你会开始得到每一个click事件。所以,你需要在你的事件处理程序来纠正。

在你的ViewGroup触摸事件

  @覆盖
公共布尔的onTouchEvent(MotionEvent事件){

    //注意:GET事件的X,Y从参数
    //再检查,如果这是在你需要的区域


    Toast.makeText(的getContext(),的onTouchEvent,Toast.LENGTH_LONG).show();
    返回true;
}
 

另外,你可能需要这个权限添加到你的清单:

 &LT;使用-权限的Andr​​oid:名称=android.permission.SYSTEM_ALERT_WINDOW/&GT;
 

I'm trying to create an always-op-top button/clickable-image which stays on top of all the windows all the time.

The proof of concept is

I was following this sample code from the Android source code

I have been successful and have a running service now. The service displays some text on top left corner of screen all the time while user can freely interact with rest of apps in normal manner.

What I'm doing is subclass ViewGroup and add it to root window manager with flag TYPE_SYSTEM_OVERLAY. Now I want to add a button/clickable-image in place of this text which can receive touch events on itself. I tried overriding "onTouchEvent" for the whole ViewGroup but it does not receive any event.

How can I receive events only on certain parts of my always-on-top view group? Kindly suggest.

public class HUD extends Service {
    HUDView mView;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();
        mView = new HUDView(this);
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                0,
//              WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
//                      | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.RIGHT | Gravity.TOP;
        params.setTitle("Load Average");
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm.addView(mView, params);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(getBaseContext(),"onDestroy", Toast.LENGTH_LONG).show();
        if(mView != null)
        {
            ((WindowManager) getSystemService(WINDOW_SERVICE)).removeView(mView);
            mView = null;
        }
    }
}

class HUDView extends ViewGroup {
    private Paint mLoadPaint;

    public HUDView(Context context) {
        super(context);
        Toast.makeText(getContext(),"HUDView", Toast.LENGTH_LONG).show();

        mLoadPaint = new Paint();
        mLoadPaint.setAntiAlias(true);
        mLoadPaint.setTextSize(10);
        mLoadPaint.setARGB(255, 255, 0, 0);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawText("Hello World", 5, 15, mLoadPaint);
    }

    @Override
    protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //return super.onTouchEvent(event);
        Toast.makeText(getContext(),"onTouchEvent", Toast.LENGTH_LONG).show();
        return true;
    }
}

解决方案

This might be a stupid solution. But it works. If you can improve it, please let me know.

OnCreate of your Service: I have used WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH flag. This is the only change in service.

@Override
    public void onCreate() {
        super.onCreate();
        Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();
        mView = new HUDView(this);
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.RIGHT | Gravity.TOP;
        params.setTitle("Load Average");
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm.addView(mView, params);
    }

Now, you will start getting each and every click event. So, you need to rectify in your event handler.

In your ViewGroup touch event

@Override
public boolean onTouchEvent(MotionEvent event) {

    // ATTENTION: GET THE X,Y OF EVENT FROM THE PARAMETER
    // THEN CHECK IF THAT IS INSIDE YOUR DESIRED AREA


    Toast.makeText(getContext(),"onTouchEvent", Toast.LENGTH_LONG).show();
    return true;
}

Also you may need to add this permission to your manifest:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

这篇关于创建系统覆盖窗口(总在最前)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆