Java 如何在一切之上绘制视图?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16264650/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 06:04:10  来源:igfitidea点击:

How to draw a view on top of everything?

javaandroidviewnotifications

提问by Allahjane

I want to make an app that can create notification on the screen on top of anything that is currently being displayed. Something like the Go SMS message popup or something like the ChatHead in the following picture:

我想制作一个应用程序,它可以在当前显示的任何内容的顶部在屏幕上创建通知。类似于 Go SMS 消息弹出窗口或下图中的 ChatHead:

enter image description here

在此处输入图片说明

It would be even better if it is possible to draw it dynamically including touch events.What is the conventional or standard way to do this?

如果可以动态地绘制它,包括触摸事件,那就更好了。这样做的常规或标准方法是什么?

Example:

例子:

Like an Icon that can be clicked or dragged no matter whether you are on home screen or app drawer or other apps.Pay attention to the circular icons near the edges of the screen in the picture posted. You can drag them anywhere in any app.

就像一个无论你是在主屏幕还是应用程序抽屉或其他应用程序上都可以点击或拖动的图标。注意贴出的图片中靠近屏幕边缘的圆形图标。您可以将它们拖动到任何应用程序中的任何位置。

回答by Stochastically

You don't need a new activity to do this. All you need to do is to add another view into your existing activity and bring it to the front, and draw/write the things that you want into that view.

你不需要一个新的活动来做到这一点。您需要做的就是将另一个视图添加到您现有的活动中并将其放在最前面,然后在该视图中绘制/写入您想要的内容。

If you want to do special things with this extra view, you could create your own view class

如果你想用这个额外的视图做一些特殊的事情,你可以创建自己的视图类

class DrawOnTop extends View { 
    public DrawOnTop(Context activity) { 
        super(activity);
    }

    @Override 
    protected void onDraw(Canvas canvas) {
        // put your drawing commands here
    }

}

and then you do something like

然后你做类似的事情

DrawOnTop mDraw = new DrawOnTop(this);
addContentView(mDraw, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
mDraw.bringToFront();

Then to force it to draw, you need to use mDraw.invalidate();

然后强制它绘制,你需要使用 mDraw.invalidate();

回答by Knossos

You could have the parent of your whole layout as RelativeLayout. The first child being the "root" of your main layout. Anything after that can be considered an overlay which is placeable to your whims.

您可以将整个布局的父级作为 RelativeLayout。第一个孩子是主布局的“根”。之后的任何内容都可以被视为可以随心所欲放置的叠加层。

Example:

例子:

<RelativeLayout>
  <LinearLayout>
    ... Main Layout here ...
  </LinearLayout>

  <TextView left="20dip" top="20dip" text="Overlay" alpha="0.7" />
</RelativeLayout>

回答by rhoadster91

What you are looking for is System Alert Window.

您正在寻找的是系统警报窗口。

There's a library called StandOut! which will assist you in creating such apps.

有一个名为StandOut的库!这将帮助您创建此类应用程序。

回答by Joel Teply

Here is how things like Toast and dialog windows work:

以下是 Toast 和对话框窗口之类的工作方式:

In the case where just adding or bringing to front does not work, say when you are having a service add its own view to another client activity or application (FaceUnlock does this), or you cannot depend on hierarchies, you need to use the window manager and a window token to do the trick. You can then create layouts and take advantage of animations and hardware acceleration as before.

如果仅添加或置于前端不起作用,例如当您让服务将自己的视图添加到另一个客户端活动或应用程序时(FaceUnlock 会这样做),或者您不能依赖层次结构,则需要使用窗口manager 和一个窗口令牌来做这个伎俩。然后,您可以像以前一样创建布局并利用动画和硬件加速。

    WindowManager windowManager = (WindowManager) getBaseContext().getSystemService(Context.WINDOW_SERVICE);

    WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.FIRST_SUB_WINDOW);
    layoutParams.width = 300;
    layoutParams.height = 300;

    layoutParams.format = PixelFormat.RGBA_8888;
    layoutParams.flags =
            WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                    | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
    layoutParams.token = getWindow().getDecorView().getRootView().getWindowToken();

    //Feel free to inflate here
    mTestView = new View(this);
    mTestView.setBackgroundColor(Color.RED);

    //Must wire up back button, otherwise it's not sent to our activity
    mTestView.setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                onBackPressed();
            }
            return true;
        }
    });
    windowManager.addView(mTestView, layoutParams);

Then be sure to remove the view onDestroy (or onPause) or you will crash

然后一定要删除onDestroy(或onPause)视图,否则你会崩溃

   if (mTestView != null) {
       WindowManager windowManager = (WindowManager) getBaseContext().getSystemService(Context.WINDOW_SERVICE);
       if (mTestView.isShown()) {
            windowManager.removeViewImmediate(mTestView);
       }
   }

回答by Sujith Royal

The best way is to start a service with your application. Create an ImageView. Set the LayoutParams of the Image View. Add the view along with the params to the window manager when the service is created.

最好的方法是使用您的应用程序启动服务。创建一个图像视图。设置图像视图的 LayoutParams。创建服务时,将视图与参数一起添加到窗口管理器。

ALL SET Your Image sticks to your window (At any screen over all apps), till you application is closed.

ALL SET 您的图像粘在您的窗口上(在所有应用程序的任何屏幕上),直到您的应用程序关闭。

You can even add onclicklisteners and ontouchlisteners to the imageview. Eg. OnClick listeners to perform some actions and Ontouchlisteners move the image along the screen.

您甚至可以将 onclicklisteners 和 ontouchlisteners 添加到图像视图中。例如。OnClick 侦听器执行一些操作,Ontouchlistener 沿屏幕移动图像。