【问题标题】:Is it possible to create a clickable Toast-like notification?是否可以创建一个可点击的类似 Toast 的通知?
【发布时间】:2014-07-09 12:02:06
【问题描述】:

我需要显示一个侵入性最低的非阻塞通知,它与它显示的活动相关(如Toast这是可点击的。有人知道这是否可能吗?不幸的是,Toast 通知(自定义或其他)似乎不可点击(即在其视图上设置 OnClickListener 无效)。而且,如果我错了,请纠正我,所有替代方案(AlertDialgPopupWindowCrouton)都会显示与它所显示的活动相关的通知(即当活动时它们不会继续显示完成)。有什么建议吗?

【问题讨论】:

标签: android android-toast


【解决方案1】:

您可以使用PopupWindow,添加onClickListener 并添加handler 以在n 次后自动取消它(就像toast 的行为一样)。像这样的:

public static void showToast(Activity a, String title, String message) {

    // inflate your xml layout
    LayoutInflater inflater = a.getLayoutInflater();
    View layout = inflater.inflate(R.layout.custom_toast,
            (ViewGroup) a.findViewById(R.id.toast_layout_root));

    // set the custom display
    ((TextView) layout.findViewById(R.id.title)).setText(title);
    ((TextView) layout.findViewById(R.id.message)).setText(message);

    // initialize your popupWindow and use your custom layout as the view
    final PopupWindow pw = new PopupWindow(layout,
            LinearLayout.LayoutParams.WRAP_CONTENT,
            LinearLayout.LayoutParams.WRAP_CONTENT, true);

    // set windowType to TYPE_TOAST (requires API 23 above)
    // this will make popupWindow still appear even the activity was closed
    pw.setWindowLayoutType(WindowManager.LayoutParams.TYPE_TOAST);
    pw.showAtLocation(layout, Gravity.CENTER | Gravity.TOP, 0, 500);

    // handle popupWindow click event
    layout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // do anything when popupWindow was clicked
            pw.dismiss(); // dismiss the window
        }
    });

    // dismiss the popup window after 3sec
    new Handler().postDelayed(new Runnable() {
        public void run() {
            pw.dismiss();
        }
    }, 3000);
}

xml 布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/toast_layout_root"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:background="#000"
              android:orientation="vertical"
              android:elevation="10dp"
              android:padding="20dp">

    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textColor="#FFF"
        android:textStyle="bold"/>

    <TextView
        android:id="@+id/message"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textColor="#FFF"/>

</LinearLayout>

【讨论】:

  • 删除“pw.setWindowLayoutType(WindowManager.LayoutParams.TYPE_TOAST);”并且可以在 API 23 下使用。在 21 上效果很好。谢谢!
  • new Handler() 应该用 Looper.getMainLooper() 初始化以避免未准备好的 looper
【解决方案2】:

您说得对,Toast 对象无法与之交互,但是有许多库可以为您提供与 toast 相同的外观和感觉,但具有一些交互性。我用的是https://github.com/JohnPersano/SuperToasts

【讨论】:

  • SuperToast 是否可点击独立于它所显示的活动?即SuperToast 会在它显示的活动完成后继续出现吗?
  • 如果您希望消息可点击,这是不可能的。此时活动上下文已被销毁,您设置的任何侦听器也将被销毁。
【解决方案3】:

我认为您实际上需要的是一个PopupWindow,可以在这里看到“http://developer.android.com/reference/android/widget/PopupWindow.html”。

Toast 有一个非常具体的任务,就是通知用户,而不需要用户的任何输入。因此,与其尝试扩展 Toast 的用途,不如使用用户可以与之交互的 PopupWindow。

【讨论】:

  • PopupWindow 是否独立于它所显示的活动?即PopupWindow 会在它显示的活动完成后继续出现吗?
  • 好的。那不是我所追求的。
【解决方案4】:

“对话”类型的活动可能是您最好的选择。


在清单中:

<activity android:name=".ToastLikeActivity"
             android:theme="@android:style/Theme.Dialog"
             android:label="@string/label"
             ></activity>


并让 onCreate() 中的活动超时:

class ToastLikeActivity extends Activity  {

     @Override
     public void onCreate(Bundle state)
           // auto-kill activity after X seconds <-------------------------
           Handler handler = new Handler();
           handler.postDelayed(new Runnable() {
                   @Override
                   public void run() {
                        ToastLikeActivity.this.finish(); // kill after X seconds
                   }
           }
    }, VisibleTimeSecs*1000);

}


要显示对话框,请像使用任何其他活动一样启动它:

Intent i = new Intent(this, ToastLikeActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);


它会在 X 秒后显示并自动消失。


这样的弹出窗口不会与调用者活动相关联。事实上 - 它甚至不需要调用者活动。你 甚至可以通过服务激活它(坏主意,但可能)。

您基本上可以实现您想要的任何类型的敏感(即接受用户的点击)界面 ToastLikeActivity。尤其是:您可以使其外观透明,使其具有对话式外观。

【讨论】:

  • ToastLikeActivity 将阻止它开始的活动。那不是我想要的。
猜你喜欢
  • 2011-06-28
  • 2014-01-15
  • 2021-10-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多