在所有Activity之上添加一个视图

23

我正在开发一个安卓应用程序。我想通过代码添加一个视图,该视图会绘制在应用程序所有活动的顶部。

我尝试将其添加到窗口管理器:

LayoutInflater inflater = activity.getLayoutInflater();
layout = inflater.inflate(R.layout.toast_layout, null);

WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.gravity = Gravity.BOTTOM;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.type = WindowManager.LayoutParams.TYPE_TOAST;
final WindowManager mWindowManager = (WindowManager);
activity.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
                mWindowManager.addView(layout, params);

然而,像这样添加,我面临两个问题:

1.当我退出我的应用程序时,布局仍然显示。

2.布局不响应点击事件。

是否有另一种方法来实现这一点?

谢谢。


你想在每个活动中都显示这个顶部视图吗? - Biraj Zalavadia
@BirajZalavadia 对于我应用程序中的所有活动。如果我显示一个新的活动,我希望仍然显示。 - Mateu
3个回答

8

LayoutParams类型从TYPE_TOAST更改为TYPE_APPLICATION,并删除我建议的先前标志,

为您应用程序中的所有活动创建一个BaseActivity,在该活动的onResume()中将此视图添加到WindowManager中,在onPause()中删除该视图,如下所示:

  windowManager.removeView(view);

这解决了问题(1),但没有解决问题(2)。添加的布局仍然无法响应点击事件。 - Mateu
使用TYPE_APPLICATION参数时,我遇到了以下android.view.WindowManager$BadTokenException异常:无法添加窗口--令牌null不是应用程序的令牌。 - Mateu
在创建顶部视图时,传递Activity引用。例如:new LinearLayout(Activity.this); - Gopal Gopi
我在问题中添加了如何定义布局的说明。我尝试将inflate方法的“null”更改为ViewGroup,但仍然出现相同的BadTokenException错误。 - Mateu
我也遇到了同样的错误。我尝试通过服务来显示覆盖窗口,但是如果我传递TYPE_APPLICATION_OVERLAY参数,它会在应用程序最小化后继续显示。我只想在应用程序运行时显示。 - Madhav

8

1)创建一个继承Activity的BaseActivity类。

2)现在你的所有活动都应该扩展BaseActivity而不是Activity。

3)重写setContentView()方法。

4)在此方法中创建一个空垂直LinearLayout。

5)将您的topView添加到此布局中

6)然后在这个LinearLayout中添加充气的视图

7)最后调用super.setContentView(passLinearLayoutHere)

如何实现?

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;

public class BaseActivity extends Activity {

    @Override
    public void setContentView(int resId) {

        LinearLayout screenRootView = new LinearLayout(this);
        screenRootView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.MATCH_PARENT));
        screenRootView.setOrientation(LinearLayout.VERTICAL);

        // Create your top view here
        View topView = new View(this); // Replace this topview with your view 

        LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View screenView = inflater.inflate(resId, null);
        topView.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                           //You will get onclick here of your topview in whatever screen it is clicked
            }
        });

        screenRootView.addView(topView);
        screenRootView.addView(screenView);

        super.setContentView(screenRootView);
    }

}

1
每次用户切换活动时,这将创建一个新的视图,而不会重用现有的顶部视图。 - user153275
不可能在活动之间使用相同的视图对象,因为这违反了面向对象编程的概念,即一个子元素不能有多个父元素。当视图附加到一个活动时,它是该活动的子元素,因此其他活动无法使用相同的视图。因此,这是实现此类功能的正确方式。 - Biraj Zalavadia
是的,我只是想指出这并没有回答问题,而是一个近乎达到目标的解决方法。 - user153275
惊人的解决方案。 :) - Ajeet

5
为了管理视图的显示和查看,我使用了Gopal提出的解决方案。我附加了onStop和onResume事件,以便在退出应用程序时隐藏视图。
对于点击事件,我意识到toast类型不响应点击事件。因此,我已更改了类型。
params.type = WindowManager.LayoutParams.TYPE_TOAST;

to

params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;

我需要添加以下权限:

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

我认为TYPE_SYSTEM_ALERT需要用户权限。 - Gopal Gopi
@GopalRao 是的,我已经将它添加到解决方案中了。抱歉,但是TYPE_APPLICATION不能在WINDOW_SERVICE视图中使用。 - Mateu
@Mateu,点击仍然无法正常工作,我尝试了所有三个标志。以下是我的视图代码:LinearLayout linearLayout = new LinearLayout(MainActivity.this); linearLayout.setBackgroundColor(getResources().getColor(android.R.color.holo_red_light)); TextView valueTV = new TextView(this); valueTV.setText("你好你好"); valueTV.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); linearLayout.addView(valueTV); - T_C
在我的 Nexus 6P 上,Android 7.1.1 上不起作用,我只是不知道为什么。 - DysaniazzZ
@DysaniazzZ:你是否使用了Marshmallow中引入的权限理由向用户请求权限?可能是因为这个原因导致它无法正常工作。 - Roadblock
非常喜欢你的解决方案。但是如何做到视图下面的活动仍然可以捕捉用户的点击? - David Papirov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接