【问题标题】:Can an Android Toast be longer than Toast.LENGTH_LONG?Android Toast 可以比 Toast.LENGTH_LONG 长吗?
【发布时间】:2011-01-14 07:14:24
【问题描述】:

当对 Toast 使用 setDuration() 时,是否可以设置自定义长度或至少比 Toast.LENGTH_LONG 更长的长度?

【问题讨论】:

  • @Nicolae 你删除toast标签有什么原因吗?它看起来与问题相关..
  • @ShadowWizard 在我看来,标签应该反映广泛感兴趣的问题的主题。例如,它被标记为 android,因此 android 大师会发现这个问题。 Toast 根本没有帮助这个问题,而且看起来更像是一个无用的标签。如果 toast 很好,因为问题是关于 Android 中的标签,那么长度也是一个很好的标签。哈克,问题中的每个单词都应该是一个标签......没有不尊重,只是表达我的观点:)
  • 我使用toast标签。我认为这些标签可以帮助搜索和排序,toast 绝对是一个常见的搜索。 android 和 toast 看起来很完美。

标签: android android-toast


【解决方案1】:

如果您深入研究 android 代码,您会发现明确指出我们无法更改 Toast 消息的持续时间的行。

 NotificationManagerService.scheduleTimeoutLocked() {
    ...
    long delay = immediate ? 0 : (r.duration == Toast.LENGTH_LONG ? LONG_DELAY : SHORT_DELAY);
    }

持续时间的默认值为

private static final int LONG_DELAY = 3500; // 3.5 seconds
private static final int SHORT_DELAY = 2000; // 2 seconds

【讨论】:

  • 谢谢...这正是我所需要的。
  • 感谢您发布默认值!我怕找不到他们。
  • 我也在寻找默认的 toast 值,这是第一次命中。绝对赞成。谢谢!
  • 这是真的。解决方案是寻找除 toast 以外的其他内容,例如对话框
【解决方案2】:

LENGTH_SHORT 和 LENGTH_LONG 的值是 0 和 1。这意味着它们被视为标志而不是实际持续时间,所以我认为除了这些值之外,不能将持续时间设置为任何值。

如果您想向用户显示更长时间的消息,请考虑使用Status Bar Notification。当状态栏通知不再相关时,可以通过编程方式取消它们。

【讨论】:

  • 感谢关于状态栏的建议,但我正在使用自定义对话框活动。
  • 这是一个有趣的想法,但与祝酒词不同。对话框是更好的选择(就像我在下面给出的示例)。
【解决方案3】:

你不妨试试:

for (int i=0; i < 2; i++)
{
      Toast.makeText(this, "blah", Toast.LENGTH_LONG).show();
}

时间加倍。如果您指定 3 而不是 2 它将增加三倍时间..等等。

【讨论】:

  • 这个解决方案很糟糕,因为,例如,如果你在祝酒时间之前退出活动,它会一遍又一遍地闪烁......
  • @dwbrito :完全同意,因此-1
  • [+1] 答案....取消祝酒可以通过在适当的地方使用Toast.cancel()来处理
  • 是的,它可以实现,但是吐司会随着你指定的计数闪烁
  • 这是有史以来最好的 DIY 答案啊 - 没做过。
【解决方案4】:

如果您希望 Toast 持续存在,我发现您可以通过重复使用 Timer 调用 toast.show()(每秒左右应该这样做)来破解它。如果Toast 已经显示,则调用show() 不会破坏任何内容,但它会刷新它在屏幕上停留的时间。

【讨论】:

  • 这样的问题是,如果用户触摸屏幕,toast 将被 Android 隐藏,然后由计时器重新创建。
  • @VioletGiraffe 在 ViewGroup OnTouch 事件中处理布尔标志之类的东西非常简单。为了优化这一点,您可能应该让您的计时器重复接近屏幕上显示Toast 的实际时间(长 3.5 秒,短 2 秒)
【解决方案5】:

我开发了一个自定义 Toast 类,您可以使用它显示 Toast 所需的持续时间(以毫秒为单位)

import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;

public final class ToastHelper {

    private static final String TAG = ToastHelper.class.getName();

    public static interface OnShowListener {
        public void onShow(ToastHelper toast);
    }

    public static interface OnDismissListener {
        public void onDismiss(ToastHelper toast);
    }

    private static final int WIDTH_PADDING_IN_DIP = 25;
    private static final int HEIGHT_PADDING_IN_DIP = 15;
    private static final long DEFAULT_DURATION_MILLIS = 2000L;

    private final Context context;
    private final WindowManager windowManager;
    private View toastView;

    private int gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
    private int mX;
    private int mY;
    private long duration = DEFAULT_DURATION_MILLIS;
    private CharSequence text = "";
    private int horizontalMargin;
    private int verticalMargin;
    private WindowManager.LayoutParams params;
    private Handler handler;
    private boolean isShowing;
    private boolean leadingInfinite;

    private OnShowListener onShowListener;
    private OnDismissListener onDismissListener;

    private final Runnable timer = new Runnable() {

        @Override
        public void run() {
            cancel();
        }
    };

    public ToastHelper(Context context) {
        Context mContext = context.getApplicationContext();
        if (mContext == null) {
            mContext = context;
        }
        this.context = mContext;
        windowManager = (WindowManager) mContext
                .getSystemService(Context.WINDOW_SERVICE);
        init();
    }

    private void init() {
        mY = context.getResources().getDisplayMetrics().widthPixels / 5;
        params = new WindowManager.LayoutParams();
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
        params.format = android.graphics.PixelFormat.TRANSLUCENT;
        params.type = WindowManager.LayoutParams.TYPE_TOAST;
        params.setTitle("ToastHelper");
        params.alpha = 1.0f;
        // params.buttonBrightness = 1.0f;
        params.packageName = context.getPackageName();
        params.windowAnimations = android.R.style.Animation_Toast;
    }

    @SuppressWarnings("deprecation")
    @android.annotation.TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    private View getDefaultToastView() {
        TextView textView = new TextView(context);
        textView.setText(text);
        textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
        textView.setClickable(false);
        textView.setFocusable(false);
        textView.setFocusableInTouchMode(false);
        textView.setTextColor(android.graphics.Color.WHITE);
        // textView.setBackgroundColor(Color.BLACK);
        android.graphics.drawable.Drawable drawable = context.getResources()
                .getDrawable(android.R.drawable.toast_frame);
        if (Build.VERSION.SDK_INT < 16) {
            textView.setBackgroundDrawable(drawable);
        } else {
            textView.setBackground(drawable);
        }
        int wP = getPixFromDip(context, WIDTH_PADDING_IN_DIP);
        int hP = getPixFromDip(context, HEIGHT_PADDING_IN_DIP);
        textView.setPadding(wP, hP, wP, hP);
        return textView;
    }

    private static int getPixFromDip(Context context, int dip) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dip, context.getResources().getDisplayMetrics());
    }

    public void cancel() {
        removeView(true);
    }

    private void removeView(boolean invokeListener) {
        if (toastView != null && toastView.getParent() != null) {
            try {
                Log.i(TAG, "Cancelling Toast...");
                windowManager.removeView(toastView);
                handler.removeCallbacks(timer);
            } finally {
                isShowing = false;
                if (onDismissListener != null && invokeListener) {
                    onDismissListener.onDismiss(this);
                }
            }
        }
    }

    public void show() {
        if (leadingInfinite) {
            throw new InfiniteLoopException(
                    "Calling show() in OnShowListener leads to infinite loop.");
        }
        cancel();
        if (onShowListener != null) {
            leadingInfinite = true;
            onShowListener.onShow(this);
            leadingInfinite = false;
        }
        if (toastView == null) {
            toastView = getDefaultToastView();
        }
        params.gravity = android.support.v4.view.GravityCompat
                .getAbsoluteGravity(gravity, android.support.v4.view.ViewCompat
                        .getLayoutDirection(toastView));
        if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
            params.horizontalWeight = 1.0f;
        }
        if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) {
            params.verticalWeight = 1.0f;
        }
        params.x = mX;
        params.y = mY;
        params.verticalMargin = verticalMargin;
        params.horizontalMargin = horizontalMargin;

        removeView(false);
        windowManager.addView(toastView, params);
        isShowing = true;
        if (handler == null) {
            handler = new Handler();
        }
        handler.postDelayed(timer, duration);
    }

    public boolean isShowing() {
        return isShowing;
    }

    public void setDuration(long durationMillis) {
        this.duration = durationMillis;
    }

    public void setView(View view) {
        removeView(false);
        toastView = view;
    }

    public void setText(CharSequence text) {
        this.text = text;
    }

    public void setText(int resId) {
        text = context.getString(resId);
    }

    public void setGravity(int gravity, int xOffset, int yOffset) {
        this.gravity = gravity;
        mX = xOffset;
        mY = yOffset;
    }

    public void setMargin(int horizontalMargin, int verticalMargin) {
        this.horizontalMargin = horizontalMargin;
        this.verticalMargin = verticalMargin;
    }

    public long getDuration() {
        return duration;
    }

    public int getGravity() {
        return gravity;
    }

    public int getHorizontalMargin() {
        return horizontalMargin;
    }

    public int getVerticalMargin() {
        return verticalMargin;
    }

    public int getXOffset() {
        return mX;
    }

    public int getYOffset() {
        return mY;
    }

    public View getView() {
        return toastView;
    }

    public void setOnShowListener(OnShowListener onShowListener) {
        this.onShowListener = onShowListener;
    }

    public void setOnDismissListener(OnDismissListener onDismissListener) {
        this.onDismissListener = onDismissListener;
    }

    public static ToastHelper makeText(Context context, CharSequence text,
            long durationMillis) {
        ToastHelper helper = new ToastHelper(context);
        helper.setText(text);
        helper.setDuration(durationMillis);
        return helper;
    }

    public static ToastHelper makeText(Context context, int resId,
            long durationMillis) {
        String string = context.getString(resId);
        return makeText(context, string, durationMillis);
    }

    public static ToastHelper makeText(Context context, CharSequence text) {
        return makeText(context, text, DEFAULT_DURATION_MILLIS);
    }

    public static ToastHelper makeText(Context context, int resId) {
        return makeText(context, resId, DEFAULT_DURATION_MILLIS);
    }

    public static void showToast(Context context, CharSequence text) {
        makeText(context, text, DEFAULT_DURATION_MILLIS).show();
    }

    public static void showToast(Context context, int resId) {
        makeText(context, resId, DEFAULT_DURATION_MILLIS).show();
    }

    private static class InfiniteLoopException extends RuntimeException {
        private static final long serialVersionUID = 6176352792639864360L;

        private InfiniteLoopException(String msg) {
            super(msg);
        }
    }
}

【讨论】:

  • android.view.WindowManager$BadTokenException: 无法添加窗口 -- 令牌 null 无效;您的活动正在进行吗?
【解决方案6】:

为此,我编写了一个辅助类。可以在github看到代码:https://github.com/quiqueqs/Toast-Expander/blob/master/src/com/thirtymatches/toasted/ToastedActivity.java

这就是你如何在 5 秒(或 5000 毫秒)内显示吐司:

Toast aToast = Toast.makeText(this, "Hello World", Toast.LENGTH_SHORT);
ToastExpander.showFor(aToast, 5000);

【讨论】:

  • Thx 和 Nice 但是我们如何停止线程 onDestroy 例如?我试过这样做,但不确定: public static void cancel(Toast mytoast) { if (null != t) t.stop(); mytoast.cancel(); }
【解决方案7】:

LONG_DELAY toast 显示 3.5 秒 和 SHORT_DELAY toast 显示 2 秒。

Toast 内部使用 INotificationManager 并在每次调用 Toast.show() 时调用它的 enqueueToast 方法。

使用 SHORT_DELAY 调用 show() 两次将再次将相同的 toast 排入队列。它将显示 4 秒(2 秒 + 2 秒)。

类似地,使用 LONG_DELAY 调用 show() 两次将再次将相同的 toast 排入队列。它将显示 7 秒(3.5 秒 + 3.5 秒)

【讨论】:

    【解决方案8】:

    我知道我有点晚了,但我接受了 Regis_AG 的回答并将其包装在一个帮助类中,效果很好。

    public class Toaster {
      private static final int SHORT_TOAST_DURATION = 2000;
    
      private Toaster() {}
    
      public static void makeLongToast(String text, long durationInMillis) {
        final Toast t = Toast.makeText(App.context(), text, Toast.LENGTH_SHORT);
        t.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0);
    
        new CountDownTimer(Math.max(durationInMillis - SHORT_TOAST_DURATION, 1000), 1000) {
          @Override
          public void onFinish() {
            t.show();
          }
    
          @Override
          public void onTick(long millisUntilFinished) {
            t.show();
          }
        }.start();
      }
    }
    

    在您的应用程序代码中,只需执行以下操作:

        Toaster.makeLongToast("Toasty!", 8000);
    

    【讨论】:

    • 这确实有效!但是如何让它可定制和可触摸呢?
    • 抱歉这个新手问题,但是当我创建上面的 Toaster 类时,它说它无法解析行中的符号 'App'。最后的 Toast t = Toast.makeText(App.context(), text, Toast.LENGTH_SHORT);谢谢,并道歉。
    • 哦,对不起! App.context() 基本上是我编写的一段自定义代码,可以方便地从任何地方访问 ApplicationContext 而无需传递它。不是你会在很多事情上使用的模式,但我发现它对 ApplicationContext 有意义。您可能需要编辑此 sn-p 以将 ApplicationContext 作为参数传递给方法。
    【解决方案9】:

    我知道答案已经很晚了.. 在查看 android 的 toast 源代码后,我遇到了同样的问题并决定实现我自己的裸骨 Toast 版本。

    基本上,您需要创建一个新的窗口管理器,并使用处理程序在所需的持续时间内显示和隐藏窗口

     //Create your handler
     Handler mHandler = new Handler();
    
    //Custom Toast Layout
    mLayout = layoutInflater.inflate(R.layout.customtoast, null);
    
    //Initialisation 
    
    mWindowManager = (WindowManager) context.getApplicationContext()
                .getSystemService(Context.WINDOW_SERVICE);
    WindowManager.LayoutParams params = new WindowManager.LayoutParams();
    
    params.gravity = Gravity.BOTTOM
    params.height = WindowManager.LayoutParams.WRAP_CONTENT;
    params.width = WindowManager.LayoutParams.WRAP_CONTENT;
    params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
    params.format = PixelFormat.TRANSLUCENT;
    params.windowAnimations = android.R.style.Animation_Toast;
    params.type = WindowManager.LayoutParams.TYPE_TOAST;
    

    布局初始化后,您可以使用自己的隐藏和显示方法

        public void handleShow() {
        mWindowManager.addView(mLayout, mParams);
        }
    
        public void handleHide() {
            if (mLayout != null) {
                if (mLayout.getParent() != null) {
                    mWindowManager.removeView(mLayout);
                }
                             mLayout = null;
            }
    

    现在你只需要添加两个可运行的线程,它们调用你可以发布到处理程序的 handleShow() 和 handleHide()。

        Runnable toastShowRunnable = new Runnable() {
            public void run() {
                handleShow();
            }
        };
    
     Runnable toastHideRunnable = new Runnable() {
            public void run() {
                handleHide();
            }
        }; 
    

    以及最后的部分

    public void show() {
    
        mHandler.post(toastShowRunnable);
        //The duration that you want
        mHandler.postDelayed(toastHideRunnable, mDuration);
    
    }
    

    这是一个快速而肮脏的实现.. 没有考虑任何性能。

    【讨论】:

    • 我尝试运行它(包括对“show()”的调用),但没有出现(在 Android 7.1 上测试)。我想你错过了什么。另外,这里阻止视图被移除的部分在哪里,因为吐司会在短时间内消失?
    【解决方案10】:

    这是我使用上述代码制作的自定义 Toast 类:

    import android.content.Context;
    import android.os.CountDownTimer;
    import android.widget.Toast;
    
    public class CustomToast extends Toast {
        int mDuration;
        boolean mShowing = false;
        public CustomToast(Context context) {
            super(context);
            mDuration = 2;
        }
    
    
        /**
         * Set the time to show the toast for (in seconds) 
         * @param seconds Seconds to display the toast
         */
        @Override
        public void setDuration(int seconds) {
            super.setDuration(LENGTH_SHORT);
            if(seconds < 2) seconds = 2; //Minimum
            mDuration = seconds;
        }
    
        /**
         * Show the toast for the given time 
         */
        @Override
        public void show() {
            super.show();
    
            if(mShowing) return;
    
            mShowing = true;
            final Toast thisToast = this;
            new CountDownTimer((mDuration-2)*1000, 1000)
            {
                public void onTick(long millisUntilFinished) {thisToast.show();}
                public void onFinish() {thisToast.show(); mShowing = false;}
    
            }.start();  
        }
    }
    

    【讨论】:

      【解决方案11】:

      如果您需要较长的 Toast,有一个实用的替代方案,但它需要您的用户单击“确定”按钮才能使其消失。您可以像这样使用 AlertDialog:

      String message = "This is your message";
      new AlertDialog.Builder(YourActivityName.this)
          .setTitle("Optional Title (you can omit this)")
          .setMessage(message)
          .setPositiveButton("ok", null)
          .show();
      

      如果您的消息很长,很可能您不知道用户阅读该消息需要多长时间,因此有时要求您的用户单击“确定”按钮以继续是个好主意.在我的例子中,当用户点击帮助图标时,我会使用这种技术。

      【讨论】:

      【解决方案12】:

      正如其他人提到的那样,Android Toast 可以是 LENGTH_LONG 或 LENGTH_SHORT。没有办法解决这个问题,您也不应该遵循任何发布的“黑客”。

      Toast 的目的是显示“非必要”信息,并且由于它们的挥之不去的效果,如果消息的持续时间超过某个阈值,则消息可能会远离上下文。如果修改了库存 Toast 以使其显示时间超过 LENGTH_LONG,则消息将在屏幕上逗留,直到应用程序的进程终止,因为 Toast 视图被添加到 WindowManager 而不是应用程序中的 ViewGroup。我认为这就是为什么它是硬编码的。

      如果您绝对需要显示超过三秒半的 toast 样式消息,我建议构建一个附加到 Activity 内容的视图,这样当用户退出应用程序时它就会消失。我的SuperToasts 库处理了这个问题和许多其他问题,请随意使用它!你很可能有兴趣使用SuperActivityToasts

      【讨论】:

        【解决方案13】:

        只需使用SuperToast 即可在任何情况下优雅地祝酒。让您的吐司色彩缤纷。编辑您的字体颜色以及它的大小。希望一切都为您服务。

        【讨论】:

          【解决方案14】:

          当你可以拥有整个Snackbar时,为什么要吃Toast:https://developer.android.com/reference/android/support/design/widget/Snackbar.html

          Snackbar > 吐司、定制吐司、面包块

          【讨论】:

            【解决方案15】:

            不,这里列出的大多数/所有黑客都不再适用于 android 9。但是有一个更好的解决方案:如果您的消息需要闲逛,请使用对话框。

            (new AlertDialog.Builder(this)).setTitle("Sorry!")
            .setMessage("Please let me know by posting a beta comment on the play store .")
            .setPositiveButton("OK", null).create().show();
            

            【讨论】:

            • 虽然这不是侯赛因想要的答案,但它是比所有那些“黑客”更好的选择!
            【解决方案16】:

            用户无法自定义 Toast 的持续时间。因为 NotificationManagerService 的 scheduleTimeoutLocked() 函数不使用字段持续时间。源代码如下。

            private void scheduleTimeoutLocked(ToastRecord r, boolean immediate)
                {
                    Message m = Message.obtain(mHandler, MESSAGE_TIMEOUT, r);
                    long delay = immediate ? 0 : (r.duration == Toast.LENGTH_LONG ? LONG_DELAY : SHORT_DELAY);
                    mHandler.removeCallbacksAndMessages(r);
                    mHandler.sendMessageDelayed(m, delay);
                }
            

            【讨论】:

              【解决方案17】:

              使用Crouton,它是一个非常灵活的Toast库。

              Crouton

              你可以像吐司一样使用它:

              Crouton.makeText(context, "YOUR_MESSAGE", Style.INFO);
              

              或者您甚至可以更深入地自定义它,例如将时间设置为无限!例如,在这里我想显示一个 toast 消息,直到用户通过单击它来确认它。

              private static void showMessage(final Activity context, MessageType type, String header, String message) {
                  View v = context.getLayoutInflater().inflate(R.layout.toast_layout, null);
                  TextView headerTv = (TextView) v.findViewById(R.id.toastHeader);
                  headerTv.setText(header);
                  TextView messageTv = (TextView) v.findViewById(R.id.toastMessage);
                  messageTv.setText(message);
                  ImageView toastIcon = (ImageView) v.findViewById(R.id.toastIcon);
              
                  final Crouton crouton = getCrouton(context, v);
                  v.setOnClickListener(new View.OnClickListener() {
                      @Override
                      public void onClick(View v) {
                          Crouton.hide(crouton);
                      }
                  });
              
                  crouton.show();
              }
              
              private static Crouton getCrouton(final Activity context, View v) {
                  Crouton crouton = Crouton.make(context, v);
                  crouton.setConfiguration(new Configuration.Builder().setDuration(Configuration.DURATION_INFINITE).build());
                  return crouton;
              }
              

              将为吐司充气的自定义布局。

              <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  xmlns:tools="http://schemas.android.com/tools"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:animateLayoutChanges="true"
                  android:background="@drawable/shadow_container"
                  android:gravity="center_vertical"
                  android:orientation="horizontal"
                  android:padding="@dimen/default_margin"
                  tools:ignore="Overdraw">
              
                  <ImageView
                      android:id="@+id/toastIcon"
                      android:layout_width="wrap_content"
                      android:layout_height="wrap_content" />
              
                  <LinearLayout
                      android:layout_width="0dp"
                      android:layout_height="wrap_content"
                      android:layout_marginStart="@dimen/default_spacing_full"
                      android:layout_weight="1"
                      android:orientation="vertical">
              
                      <TextView
                          android:id="@+id/toastHeader"
                          style="@style/ItemText"
                          android:layout_width="wrap_content"
                          android:layout_height="wrap_content" />
              
                      <TextView
                          android:id="@+id/toastMessage"
                          style="@style/ItemSubText"
                          android:layout_width="wrap_content"
                          android:layout_height="wrap_content" />
              
                  </LinearLayout>
              
              </LinearLayout>
              

              【讨论】:

                【解决方案18】:

                可以使用专门运行 toast 的线程来破解 Toast 持续时间。这有效(运行 toast 10 秒,根据自己的喜好修改 sleep 和 ctr):

                final Toast toast = Toast.makeText(this, "Your Message", Toast.LENGTH_LONG);
                
                Thread t = new Thread(){
                    public void run(){
                          int ctr = 0;
                          try{
                               while( ctr<10 ){
                                    toast.show();
                                    sleep(1000);
                                    ctr++;
                               }
                          } catch (Exception e) {
                               Log.e("Error", "", e);
                          }
                     }
                 };
                 t.start();
                

                【讨论】:

                  【解决方案19】:

                  具有自定义背景和视图的 toast 对我有用。我在 nexus 7 平板电脑上对其进行了测试,我注意到循环期间没有淡入淡出动画。下面是实现:

                  public static void customToast(Context context, String message, int duration) {
                  
                      for (int i = 0; i < duration; i++) {
                          Toast toast = new Toast(context);
                          toast.setDuration(Toast.LENGTH_LONG);
                          toast.setGravity(Gravity.CENTER, 0, 0);
                          LayoutInflater inflater = (LayoutInflater) context
                                  .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                          View view = inflater.inflate(R.layout.toast_layout, null);
                          TextView textViewToast = (TextView) view
                                  .findViewById(R.id.textViewToast);
                          textViewToast.setText(message);
                          toast.setView(view);
                          toast.show();
                      }
                  
                  }
                  

                  这是上面代码中使用的自定义文本视图:

                  <TextView xmlns:android="http://schemas.android.com/apk/res/android"
                  android:id="@+id/textViewToast"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:background="@drawable/fragment_background"
                  android:padding="8dp"
                  android:text="Large Text"
                  android:textAppearance="?android:attr/textAppearanceLarge"
                  android:textColor="@color/blue" />
                  

                  @drawable/fragment_background 使我的吐司像 kitkat 版本一样有圆角。您也可以在文件中添加其他视图。鼓励对改进和 cmets 进行任何修改,因为我计划在我的实时应用中实现这一点。

                  【讨论】:

                    【解决方案20】:

                    将倒计时安排到未来的某个时间,并在此期间定期通知。在文本字段中显示 30 秒倒计时的示例:

                    新的倒计时(30000,1000){ 公共无效onTick(长millisUntilFinished){ mTextField.setText("剩余秒数:" + millisUntilFinished / 1000); } 公共无效 onFinish() { mTextField.setText("完成!"); } }。开始();

                    【讨论】:

                      【解决方案21】:

                      在所有可用的解决方案都失败后,我终于找到了使用递归的解决方法。

                      代码:

                      //Recursive function, pass duration in seconds
                      public void showToast(int duration) {
                          if (duration <= 0)
                              return;
                      
                          Toast.makeText(this, "Hello, it's a toast", Toast.LENGTH_LONG).show();
                          Handler handler = new Handler();
                          handler.postDelayed(new Runnable() {
                              @Override
                              public void run() {
                                  showToast(duration-1);
                              }
                          }, 1000);
                      }
                      

                      【讨论】:

                      • 关于这个问题的大多数解决方案与重复调用“show”以保持 toast 显示有关,都是使用相同的 toast 实例这样做的,而你的实际上是每秒创建一个新的 toast 实例并指定每一个都应该长时间显示(通常为 3.5 秒)。这不仅效率低下,因为您不断地创建额外的对象实例,而且 Android 将 toast 消息放入队列中,以便在指定的持续时间内一个接一个地显示。因此,如果您以 5 的持续时间调用它,则消息实际上会显示 17.5 秒。
                      【解决方案22】:

                      此文本将在 5 秒后消失。

                          final Toast toast = Toast.makeText(getApplicationContext(), "My Text", Toast.LENGTH_SHORT);
                          toast.show();
                      
                          Handler handler = new Handler();
                              handler.postDelayed(new Runnable() {
                                 @Override
                                 public void run() {
                                     toast.cancel(); 
                                 }
                          }, 5000); // Change to what you want
                      

                      编辑: 正如 Itai Spector 在评论中所说,它将显示大约 3.5 秒,所以使用此代码:

                          int toastDuration = 5000; // in MilliSeconds
                          Toast mToast = Toast.makeText(this, "My text", Toast.LENGTH_LONG);
                          CountDownTimer countDownTimer;
                          countDownTimer = new CountDownTimer(toastDuration, 1000) {
                              public void onTick(long millisUntilFinished) {
                                  mToast.show();
                              }
                      
                              public void onFinish() {
                                  mToast.cancel();
                              }
                          };
                      
                          mToast.show();
                          countDownTimer.start();
                      

                      【讨论】:

                      • 我认为这个文本会在 3.5 秒后消失
                      • @ItaiSpector:请检查我的新代码。
                      【解决方案23】:

                      创建稍长消息的一个非常简单的方法如下:

                      private Toast myToast;
                      
                      public MyView(Context context) {
                        myToast = Toast.makeText(getContext(), "", Toast.LENGTH_LONG);
                      }
                      
                      private Runnable extendStatusMessageLengthRunnable = new Runnable() {
                        @Override
                          public void run() {
                          //Show the toast for another interval.
                          myToast.show();
                         }
                      }; 
                      
                      public void displayMyToast(final String statusMessage, boolean extraLongDuration) {
                        removeCallbacks(extendStatusMessageLengthRunnable);
                      
                        myToast.setText(statusMessage);
                        myToast.show();
                      
                        if(extraLongDuration) {
                          postDelayed(extendStatusMessageLengthRunnable, 3000L);
                        }
                      }
                      

                      请注意,以上示例删除了 LENGTH_SHORT 选项以保持示例简单。

                      您通常不希望使用 Toast 消息以很长的间隔显示消息,因为这不是 Toast 类的预期用途。但是有时您需要显示的文本量可能需要用户超过 3.5 秒才能阅读,在这种情况下,稍微延长时间(例如,如上所示,延长至 6.5 秒)可能,IMO,很有用并符合预期用途。

                      【讨论】:

                        【解决方案24】:

                        将 toast 设置为以毫秒为单位的特定时间段:

                        public void toast(int millisec, String msg) {
                            Handler handler = null;
                            final Toast[] toasts = new Toast[1];
                            for(int i = 0; i < millisec; i+=2000) {
                                toasts[0] = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
                                toasts[0].show();
                                if(handler == null) {
                                    handler = new Handler();
                                    handler.postDelayed(new Runnable() {
                                        @Override
                                        public void run() {
                                            toasts[0].cancel();
                                        }
                                    }, millisec);
                                }
                            }
                        }
                        

                        【讨论】:

                          【解决方案25】:
                            private Toast mToastToShow;
                            public void showToast(View view) {
                           // Set the toast and duration
                           int toastDurationInMilliSeconds = 10000;
                           mToastToShow = Toast.makeText(this, "Hello world, I am a toast.",  Toast.LENGTH_LONG);
                          
                           // Set the countdown to display the toast
                           CountDownTimer toastCountDown;
                           toastCountDown = new CountDownTimer(toastDurationInMilliSeconds, 1000 /*Tick duration*/) {
                            public void onTick(long millisUntilFinished) {
                               mToastToShow.show();
                            }
                            public void onFinish() {
                               mToastToShow.cancel();
                               }
                              };
                          
                              // Show the toast and starts the countdown
                               mToastToShow.show();
                               toastCountDown.start();
                                }
                          

                          【讨论】:

                            【解决方案26】:
                            val toast = Toast.makeText(this, "", Toast.LENGTH_LONG)
                            
                            val countDownTimer = object : CountDownTimer(5000, 1000) {
                                override fun onTick(millisUntilFinished: Long) { }
                                override fun onFinish() { toast.cancel() }
                            }
                            
                            toast.show()
                            countDownTimer.start()
                            

                            【讨论】:

                              【解决方案27】:
                              Toast.makeText(this, "Text", Toast.LENGTH_LONG).show(); 
                              Toast.makeText(this, "Text", Toast.LENGTH_LONG).show();
                              

                              这个问题的一个非常简单的解决方案。他们的两倍或三倍将使吐司持续更长时间。这是唯一的出路。

                              【讨论】:

                              • 虽然听起来很老套,但很欣赏这种想法!
                              • 为什么不赞成@Arturo 提到的类似解决方案使用与 for 循环相同的技巧
                              • 这种方法对我有用。很高兴听到那些反对他们为什么这样做的人。
                              • 这在 android 9 及更高版本中不再起作用。
                              猜你喜欢
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2012-09-03
                              • 1970-01-01
                              • 2019-05-09
                              • 2014-04-18
                              • 1970-01-01
                              相关资源
                              最近更新 更多