【问题标题】:Button in custom Android Toast?自定义Android Toast中的按钮?
【发布时间】:2011-03-19 13:09:40
【问题描述】:

Toast 中是否可以有一个按钮?

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

【问题讨论】:

    标签: android button android-button toast


    【解决方案1】:

    无法点击 Toast。无法在 toast 消息中捕获点击。 您将需要为此构建一个对话框。更多信息请查看Creating Dialogs

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

    【讨论】:

    • 我也是这么想的。好的,谢谢您的解释。我知道对话框,我只是在做一些测试。
    • 完美的解释并在我检查此问题的第一个 SO 页面上帮助了我。为什么不是每个答案都是您点击的第一件事! :)
    【解决方案2】:

    吐司不能包含按钮。除了 gmail 应用程序和 jelly beans 中的画廊应用程序有一个包含按钮的半吐司之外,谷歌是这样做的

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

    我想这回答了你的问题。

    【讨论】:

    • 您的链接无效
    • 这个新链接正在工作,而不是投票你可以用谷歌搜索类名 (UndoBarController.java),repos 被移动了,这不是我的错。
    • 正确的链接在答案中不受欢迎。当然,我会照顾新的时间。删除了反对票。
    • 感谢您的考虑
    【解决方案3】:

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

    • 具有与原始Toast 类类似的界面
    • 可用作Dialog(具有Gmail 应用等可点击按钮)
    • 可以在millis 中设置length
    • 可以设置显示和取消动画
    • 只存在于初始化的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);
                }
            }
        };
    }
    

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

    【讨论】:

    • 谢谢,但刚刚发现的材料 :) 小吃店是一样的
    • 它是在几周前添加到新的支持库中的。
    【解决方案4】:

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

    UndoBar
    MessageBar
    Nurik's UndoBar

    当然,也欢迎您使用我整理的SuperToasts 库,但是对于一种用法可能有点过分。我的做法在SuperActivityToast 类中进行了概述。

    【讨论】:

      【解决方案5】:

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

      1. Extras 中的SDK Manager 下载Android Support Library(修订版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;

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

          如果您想添加按钮,请使用警报框:-)。这里有些例子 Dialog boxes in Android

          【讨论】:

            【解决方案8】:

            Creating a system overlay window (always on top)

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-08-08
              • 2014-01-27
              • 1970-01-01
              • 2015-11-26
              • 1970-01-01
              • 2023-03-14
              • 2018-03-12
              • 1970-01-01
              相关资源
              最近更新 更多