自定义 Android Toast 中的按钮?

发布于 2024-09-11 14:51:20 字数 100 浏览 6 评论 0原文

Toast 中可以有一个按钮吗?

理论上是的,因为您可以从 XML 布局构建自定义 Toast,但我尝试在其中放置一个按钮,但无法让它注册单击。 有人设法做这样的事情吗?

Is it possible to have a button in a Toast?

In theory, yes because you can build a custom Toast from a layout in XML, but I tried to put a button in it and couldn't get it to register the click.
Did anyone manage to do something like that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

我不吻晚风 2024-09-18 14:51:20

无法点击 toast。无法捕获 toast 消息内的点击。
您需要为此构建一个对话框。有关详细信息,请参阅创建对话框

Toast 类上的 API 声明 toast 永远不会获得焦点并且因为 Toast 不是视图,所以没有 onClick 消息。我认为因此 Toast 的子级也不能被单击。

A toast can not be clicked. It is not possible to capture a click inside a toast message.
You will need to build a dialog for that. Look at Creating Dialogs for more info.

The API on the Toast class state that a toast will never receive the focus and because a toast is not a view there is no onClick message. I would assume that therefore childs of a Toast can not be clicked as well.

挖个坑埋了你 2024-09-18 14:51:20

Toast 不能包含按钮。除了 gmail 应用程序和果冻豆中的图库应用程序有一个包含按钮的半吐司之外,谷歌是这样做的

https://gist.github.com/benvd/4090998

我想这回答了你的问题。

A toast cant contain a button. Except that the gmail app and the gallery app in jelly beans have a semi toast that contains a button, here is how Google did it

https://gist.github.com/benvd/4090998

I guess this answers your question.

流绪微梦 2024-09-18 14:51:20

片段显示了自定义 Toast 的实现:

Header

  • 与原始 Toast 类具有类似的接口,
  • 可以使用作为Dialog(具有像Gmail应用程序一样可点击的按钮)
  • 可以在millis中设置长度
  • 可以设置显示和取消动画
  • 仅在初始化时才存在Activity

当前限制:

  • 不支持屏幕方向更改

用法:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //...

    View toastView = new View(getBaseContext());
    //init your toast view

    ActivityToast toast = new ActivityToast(this, toastView);

    //set toast Gravity ( Gravity.BOTTOM | Gravity.FILL_HORIZONTAL by default)
    toast.setGravity(Gravity.CENTER);

    toast.setLength(10000); //set toast show duration to 10 seconds (2 seconds by default)

    Animation showAnim; // init animation
    Animation.AnimationListener showAnimListener; //init anim listener
    toast.setShowAnimation(showAnim);
    toast.setShowAnimationListener(showAnimListener);

    Animation cancelAnim; // init animation
    Animation.AnimationListener cancelAnimListener; //init anim listener
    toast.setCancelAnimation(showAnim);
    toast.setCancelAnimationListener(showAnimListener);

    toast.show(); //show toast view
    toast.isShowing(); // check if toast is showing now
    toast.cancel(); //cancel toast view

    toast.getView(); //get toast view to update it or to do something ..
}

来源

import android.app.Activity;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.FrameLayout;

public class ActivityToast {

    public static final long LENGTH_SHORT = 2000;
    public static final long LENGTH_LONG = 3000;
    public static final int DEFAULT_ANIMATION_DURATION = 400;

    private final Activity mActivity;
    private FrameLayout.LayoutParams mLayoutParams;

    private Handler mHandler = new Handler();

    private ViewGroup mParent;
    private FrameLayout mToastHolder;
    private View mToastView;

    private Animation mShowAnimation;
    private Animation mCancelAnimation;

    private long mLength = LENGTH_SHORT;

    private Animation.AnimationListener mShowAnimationListener;
    private Animation.AnimationListener mCancelAnimationListener;

    private boolean mIsAnimationRunning;
    private boolean mIsShown;

    /**
     * @param activity Toast will be shown at top of the widow of this Activity
     */
    public ActivityToast(@NonNull Activity activity, View toastView) {
        mActivity = activity;

        mParent = (ViewGroup) activity.getWindow().getDecorView();
        mToastHolder = new FrameLayout(activity.getBaseContext());
        mLayoutParams = new FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT,
                Gravity.BOTTOM | Gravity.FILL_HORIZONTAL
        );
        mToastHolder.setLayoutParams(mLayoutParams);

        mShowAnimation = new AlphaAnimation(0.0f, 1.0f);
        mShowAnimation.setDuration(DEFAULT_ANIMATION_DURATION);
        mShowAnimation.setAnimationListener(mHiddenShowListener);

        mCancelAnimation = new AlphaAnimation(1.0f, 0.0f);
        mCancelAnimation.setDuration(DEFAULT_ANIMATION_DURATION);
        mCancelAnimation.setAnimationListener(mHiddenCancelListener);

        mToastView = toastView;
        mToastHolder.addView(mToastView);

        mToastHolder.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                    cancel();
                }
                return false;
            }
        });
    }

    public void show() {
        if (!isShowing()) {
            mParent.addView(mToastHolder);
            mIsShown = true;

            if (mShowAnimation != null) {
                mToastHolder.startAnimation(mShowAnimation);
            } else {
                mHandler.postDelayed(mCancelTask, mLength);
            }
        }
    }

    public void cancel() {
        if (isShowing() && !mIsAnimationRunning) {
            if (mCancelAnimation != null) {
                mToastHolder.startAnimation(mCancelAnimation);
            } else {
                mParent.removeView(mToastHolder);
                mHandler.removeCallbacks(mCancelTask);
                mIsShown = false;
            }
        }
    }

    public boolean isShowing() {
        return mIsShown;
    }

    /**
     * Pay attention that Action bars is the part of Activity window
     *
     * @param gravity Position of view in Activity window
     */

    public void setGravity(int gravity) {
        mLayoutParams.gravity = gravity;

        if (isShowing()) {
            mToastHolder.requestLayout();
        }
    }

    public void setShowAnimation(Animation showAnimation) {
        mShowAnimation = showAnimation;
    }

    public void setCancelAnimation(Animation cancelAnimation) {
        mCancelAnimation = cancelAnimation;
    }

    /**
     * @param cancelAnimationListener cancel toast animation. Note: you should use this instead of
     *                                Animation.setOnAnimationListener();
     */
    public void setCancelAnimationListener(Animation.AnimationListener cancelAnimationListener) {
        mCancelAnimationListener = cancelAnimationListener;
    }

    /**
     * @param showAnimationListener show toast animation. Note: you should use this instead of
     *                              Animation.setOnAnimationListener();
     */
    public void setShowAnimationListener(Animation.AnimationListener showAnimationListener) {
        mShowAnimationListener = showAnimationListener;
    }

    public void setLength(long length) {
        mLength = length;
    }

    public View getView() {
        return mToastView;
    }

    private Runnable mCancelTask = new Runnable() {
        @Override
        public void run() {
            cancel();
        }
    };

    private Animation.AnimationListener mHiddenShowListener = new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
            if (mShowAnimationListener != null) {
                mShowAnimationListener.onAnimationStart(animation);
            }

            mIsAnimationRunning = true;
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            mHandler.postDelayed(mCancelTask, mLength);

            if (mShowAnimationListener != null) {
                mShowAnimationListener.onAnimationEnd(animation);
            }

            mIsAnimationRunning = false;
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            if (mShowAnimationListener != null) {
                mShowAnimationListener.onAnimationRepeat(animation);
            }
        }
    };

    private Animation.AnimationListener mHiddenCancelListener = new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
            if (mCancelAnimationListener != null) {
                mCancelAnimationListener.onAnimationStart(animation);
            }

            mIsAnimationRunning = true;
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            mParent.removeView(mToastHolder);
            mHandler.removeCallbacks(mCancelTask);

            if (mCancelAnimationListener != null) {
                mCancelAnimationListener.onAnimationEnd(animation);
            }

            mIsAnimationRunning = false;
            mIsShown = false;
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            if (mCancelAnimationListener != null) {
                mCancelAnimationListener.onAnimationRepeat(animation);
            }
        }
    };
}

我在 github 上的原始帖子
显示自定义布局实现的帖子在这篇文章中

Snippet shows implementation of custom Toast that:

Header

  • Have similar interface as original Toast class
  • Can be used as Dialog (have clickable buttons like Gmail app)
  • Have possibility to set length in millis
  • Have possibility to set show and cancel animation
  • Lives only with initialized Activity

Current Limitations:

  • No screen orientation change are supported

Usage:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //...

    View toastView = new View(getBaseContext());
    //init your toast view

    ActivityToast toast = new ActivityToast(this, toastView);

    //set toast Gravity ( Gravity.BOTTOM | Gravity.FILL_HORIZONTAL by default)
    toast.setGravity(Gravity.CENTER);

    toast.setLength(10000); //set toast show duration to 10 seconds (2 seconds by default)

    Animation showAnim; // init animation
    Animation.AnimationListener showAnimListener; //init anim listener
    toast.setShowAnimation(showAnim);
    toast.setShowAnimationListener(showAnimListener);

    Animation cancelAnim; // init animation
    Animation.AnimationListener cancelAnimListener; //init anim listener
    toast.setCancelAnimation(showAnim);
    toast.setCancelAnimationListener(showAnimListener);

    toast.show(); //show toast view
    toast.isShowing(); // check if toast is showing now
    toast.cancel(); //cancel toast view

    toast.getView(); //get toast view to update it or to do something ..
}

Sources

import android.app.Activity;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.FrameLayout;

public class ActivityToast {

    public static final long LENGTH_SHORT = 2000;
    public static final long LENGTH_LONG = 3000;
    public static final int DEFAULT_ANIMATION_DURATION = 400;

    private final Activity mActivity;
    private FrameLayout.LayoutParams mLayoutParams;

    private Handler mHandler = new Handler();

    private ViewGroup mParent;
    private FrameLayout mToastHolder;
    private View mToastView;

    private Animation mShowAnimation;
    private Animation mCancelAnimation;

    private long mLength = LENGTH_SHORT;

    private Animation.AnimationListener mShowAnimationListener;
    private Animation.AnimationListener mCancelAnimationListener;

    private boolean mIsAnimationRunning;
    private boolean mIsShown;

    /**
     * @param activity Toast will be shown at top of the widow of this Activity
     */
    public ActivityToast(@NonNull Activity activity, View toastView) {
        mActivity = activity;

        mParent = (ViewGroup) activity.getWindow().getDecorView();
        mToastHolder = new FrameLayout(activity.getBaseContext());
        mLayoutParams = new FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT,
                Gravity.BOTTOM | Gravity.FILL_HORIZONTAL
        );
        mToastHolder.setLayoutParams(mLayoutParams);

        mShowAnimation = new AlphaAnimation(0.0f, 1.0f);
        mShowAnimation.setDuration(DEFAULT_ANIMATION_DURATION);
        mShowAnimation.setAnimationListener(mHiddenShowListener);

        mCancelAnimation = new AlphaAnimation(1.0f, 0.0f);
        mCancelAnimation.setDuration(DEFAULT_ANIMATION_DURATION);
        mCancelAnimation.setAnimationListener(mHiddenCancelListener);

        mToastView = toastView;
        mToastHolder.addView(mToastView);

        mToastHolder.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                    cancel();
                }
                return false;
            }
        });
    }

    public void show() {
        if (!isShowing()) {
            mParent.addView(mToastHolder);
            mIsShown = true;

            if (mShowAnimation != null) {
                mToastHolder.startAnimation(mShowAnimation);
            } else {
                mHandler.postDelayed(mCancelTask, mLength);
            }
        }
    }

    public void cancel() {
        if (isShowing() && !mIsAnimationRunning) {
            if (mCancelAnimation != null) {
                mToastHolder.startAnimation(mCancelAnimation);
            } else {
                mParent.removeView(mToastHolder);
                mHandler.removeCallbacks(mCancelTask);
                mIsShown = false;
            }
        }
    }

    public boolean isShowing() {
        return mIsShown;
    }

    /**
     * Pay attention that Action bars is the part of Activity window
     *
     * @param gravity Position of view in Activity window
     */

    public void setGravity(int gravity) {
        mLayoutParams.gravity = gravity;

        if (isShowing()) {
            mToastHolder.requestLayout();
        }
    }

    public void setShowAnimation(Animation showAnimation) {
        mShowAnimation = showAnimation;
    }

    public void setCancelAnimation(Animation cancelAnimation) {
        mCancelAnimation = cancelAnimation;
    }

    /**
     * @param cancelAnimationListener cancel toast animation. Note: you should use this instead of
     *                                Animation.setOnAnimationListener();
     */
    public void setCancelAnimationListener(Animation.AnimationListener cancelAnimationListener) {
        mCancelAnimationListener = cancelAnimationListener;
    }

    /**
     * @param showAnimationListener show toast animation. Note: you should use this instead of
     *                              Animation.setOnAnimationListener();
     */
    public void setShowAnimationListener(Animation.AnimationListener showAnimationListener) {
        mShowAnimationListener = showAnimationListener;
    }

    public void setLength(long length) {
        mLength = length;
    }

    public View getView() {
        return mToastView;
    }

    private Runnable mCancelTask = new Runnable() {
        @Override
        public void run() {
            cancel();
        }
    };

    private Animation.AnimationListener mHiddenShowListener = new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
            if (mShowAnimationListener != null) {
                mShowAnimationListener.onAnimationStart(animation);
            }

            mIsAnimationRunning = true;
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            mHandler.postDelayed(mCancelTask, mLength);

            if (mShowAnimationListener != null) {
                mShowAnimationListener.onAnimationEnd(animation);
            }

            mIsAnimationRunning = false;
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            if (mShowAnimationListener != null) {
                mShowAnimationListener.onAnimationRepeat(animation);
            }
        }
    };

    private Animation.AnimationListener mHiddenCancelListener = new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
            if (mCancelAnimationListener != null) {
                mCancelAnimationListener.onAnimationStart(animation);
            }

            mIsAnimationRunning = true;
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            mParent.removeView(mToastHolder);
            mHandler.removeCallbacks(mCancelTask);

            if (mCancelAnimationListener != null) {
                mCancelAnimationListener.onAnimationEnd(animation);
            }

            mIsAnimationRunning = false;
            mIsShown = false;
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            if (mCancelAnimationListener != null) {
                mCancelAnimationListener.onAnimationRepeat(animation);
            }
        }
    };
}

My original post on github
Post that shows implementation of custom layout in this post

掌心的温暖 2024-09-18 14:51:20

传递给 toast 的自定义视图可以包含任何内容;但是,Toast 无法接收任何触摸事件,因此使用触摸事件的任何组件都无法在 Stock Toast 中工作(按钮、单选按钮等)。您唯一的选择是创建一个包含按钮的自定义视图并将其添加到您的布局中。有很多关于如何执行此操作的示例,并且您可以查看一些库以了解其他人是如何执行此操作的。

撤消栏
消息栏
Nurik 的 UndoBar

当然也欢迎您使用我放在一起的 SuperToasts 库,但对于一种用法来说可能有点矫枉过正。我的做法在 SuperActivityToast 类。

A custom view passed to a toast can contain anything; however, toasts cannot receive any touch events so no components that use touch events will work in a stock toast (buttons, radiobuttons, etc.). The only choice you have is to create a custom view with a button in it and add it to your layout. There are many examples of how to do this and a few libraries you can check out to see how other people are doing it.

UndoBar
MessageBar
Nurik's UndoBar

Of course you are also welcome to use the SuperToasts library I put together however it might be a little overkill for one usage. The way that I do it is outlined in the SuperActivityToast class.

身边 2024-09-18 14:51:20

您应该使用 Snackbar。它位于最新的 android 支持库中(在回答时),并且与旧的 api 级别兼容。它比 Dialog 或自定义 View 更容易实现,并且能够拥有与 Toast 不同的按钮。

  1. SDK Manager 中的 Extras 下载 Android 支持库(修订版 22.2.1 或更高版本)。
  2. build.gradle 中将其添加到类依赖项中:com.android.support:design:22.2.0
  3. 实施:

    Snackbar.make(this.findViewById(android.R.id.content), "Toast 消息", Snackbar.LENGTH_LONG)
    .setAction("单击此处激活操作", onClickListener)
    .setActionTextColor(颜色.RED)
    .show;

就是这样。没有 github 项目,实现与 Toast 非常相似。我在我的一个项目中使用了它,效果非常好。

You should use a Snackbar. It is in the latest android support library(at time of answer) and is compatible with older api levels. It is much easier to implement than a Dialog or custom View and has the ability to have a button unlike a Toast.

  1. Download Android Support Library from Extras in the SDK Manager(revision 22.2.1 or later).
  2. In the build.gradle add this to the class dependencies: com.android.support:design:22.2.0.
  3. Implement:

    Snackbar.make(this.findViewById(android.R.id.content), "Toast Message", Snackbar.LENGTH_LONG)
    .setAction("Click here to activate action", onClickListener)
    .setActionTextColor(Color.RED)
    .show;

And that is it. No github projects and implementation is very similiar to Toast. I used it in one of my projects and it works great.

如若梦似彩虹 2024-09-18 14:51:20

在这种情况下,您可以尝试 SuperToast 。它可以用按钮创建吐司。它具有自定义持续时间功能、彩色背景、彩色字体、自定义字体、动画效果。希望你会喜欢它

You can try SuperToast in this case. It can create toast with button. It has custom duration feature, colourful background, colourful fonts, custom fonts, animated effect. Hope u will enjoy it

泅人 2024-09-18 14:51:20

如果您想添加按钮,请使用警报框:-)。这是一些例子
Android 中的对话框

Use an alertbox, if you want to add a button :-). Here are some examples
Dialog boxes in Android

2024-09-18 14:51:20

创建系统覆盖窗口(始终位于顶部)

这是建议可以完成,我还需要吐司中的按钮,所以我仍然需要自己实现。如果我找到更多,我会将其添加到我的帖子中

Creating a system overlay window (always on top)

This is suggesting that it can be done, I also need buttons in a toast so I still have to make my own implementation. If I find more I will add it to my post

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文