项目中遇到一个需求,需要在 Service 中弹出 Dialog 以显示消费信息,但是 Dialog 需要依附于一个 Activity,但是当用户退出应用之后,该应用的 Activity 就已全部销毁,所以在 Service 中弹出的 Dialog 也就没有了可以依附的 Activity 了。

网上普遍是将这个应用的 Dialog 设置成一个系统级的 Dialog,即一个全局性质的提示框,这样,无论它现在处于何种界面之下,只要调用 show() 就可以弹出提示框了。

该方法由于配置起来相对麻烦,而且各大厂商的权限管理各不相同,于是我改用了一种更为简单粗暴的方法——直接从 Service 中弹出 ActivityActivity 为我们提供了多种主题,我们只需选择一个弹窗类型的主题即可。

首先创建一个新的 Activity,然后在「AndroidManifest.xml」中修改这个 Activity 的主题:

<activity
    android:name=".DialogActivity"
    android:theme="@style/Theme.AppCompat.Light.Dialog.Alert" />

其实 Dialog 主题也挺多的,有美有丑,得益于 IDE 的智能提醒,输入“Dialog”就列出了一大堆,我也懒得一个个试了,挑了两三个看下效果,发现最好看就是上面这个,所以就选它了。

然后开始写布局文件,虽然是 Dialog 样式,但只需按照平常写 Activity 布局的习惯来写即可。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp"
    tools:context=".DialogActivity">

    <TextView
        android:id="@+id/dialog_message"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="15dp" />

    <Button
        android:id="@+id/dialog_positive_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:background="@color/colorPrimary"
        android:text="确定"
        android:textColor="#FFFFFF" />

</LinearLayout>

布局十分简单,一个纵向线性布局,里面就一个文本显示框和一个按钮,宽度都填满父视图,高度则包裹该组件,这应该是多年 Windows 系统以及多种操作系统和应用达成的一种不成文的共识,使我们作为用户也形成了固有的印象。

最后就是逻辑代码实现了,同样极其简单,就像平常写 Activity 的逻辑一样。

public class DialogActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dialog);

        TextView dialogMessage = (TextView) findViewById(R.id.dialog_message);
        String details = getIntent().getStringExtra("dialogMessage");
        dialogMessage.setText(details);

        Button dialogPositiveButton = (Button) findViewById(R.id.dialog_positive_button);
        dialogPositiveButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });
    }
}

获取到 TextViewButton 的实例,TextView 通过 getIntent() 获取 Service 中传过来的内容并显示,而 Button 则负责关闭这个 Activity

实际效果如下:

Dialog 样式 Activity