自定义 Android Toast 中的按钮?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3308975/
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-20 09:38:35  来源:igfitidea点击:

Button in custom Android Toast?

androidbuttonandroid-buttontoast

提问by Sephy

Is it possible to have a button in a Toast?

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?

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

回答by Janusz

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 Dialogsfor more info.

无法单击 Toast。无法在 Toast 消息中捕获点击。您将需要为此构建一个对话框。查看创建对话框了解更多信息。

The API on the Toastclass 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.

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

回答by Hazem Farahat

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

Toast 不能包含按钮。除了 gmail 应用程序和 jelly beans 中的 Gallery 应用程序有一个包含按钮的半吐司,以下是 Google 的做法

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

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

I guess this answers your question.

我想这回答了你的问题。

回答by Yakiv Mospan

Snippet shows implementation of custom Toast that:

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

Header

标题

  • Have similar interface as original Toastclass
  • Can be used as Dialog(have clickable buttons like Gmail app)
  • Have possibility to set lengthin millis
  • Have possibility to set show and cancel animation
  • Lives only with initialized Activity
  • 具有与原始Toast类相似的接口
  • 可以用作Dialog(具有可点击的按钮,如 Gmail 应用程序)
  • 有可能设置lengthmillis
  • 可以设置显示和取消动画
  • 仅在初始化时存在 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

我在 github Post上的原始帖子
显示了本文中自定义布局的实现

回答by John P.

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.

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

UndoBar
MessageBar
Nurik's UndoBar

UndoBar
MessageBar
Nurik 的 UndoBar

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

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

回答by Dylan Vander Berg

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 Dialogor custom Viewand has the ability to have a button unlike a Toast.

你应该使用一个Snackbar. 它在最新的 android 支持库中(在回答时)并且与旧的 api 级别兼容。它比 aDialog或 custom更容易实现View,并且能够拥有一个不同于Toast.

  1. Download Android Support Libraryfrom Extrasin the SDK Manager(revision 22.2.1 or later).
  2. In the build.gradleadd 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;

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

    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.

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

回答by Muhammad Jobayer

You can try SuperToastin 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

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

回答by Martijn de Langh

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

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

回答by Martin

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

如果要添加按钮,请使用警报框:-)。以下是Android中的一些示例 对话框