Может ли Android-тост быть длиннее, чем Toast.LENGTH_LONG?


263

При использовании setDuration () для Toast, возможно ли установить пользовательскую длину или хотя бы что-то длиннее Toast.LENGTH_LONG?


4
@Nicolae, по какой причине вы удалили этот toastтег? Это похоже на вопрос ..
Shadow Wizard - это Ear For You

2
@ShadowWizard Теги, как мне кажется, должны отражать темы вопроса, который представляет широкий интерес. Как, например, он помечен Android, и гуру Android найдет этот вопрос. Тост вообще не помогает в этом вопросе и больше похож на бесполезный тэг. Если тост хорош, потому что вопрос касается тегов в Android, то длина тоже была хорошим тегом. Хак, каждое слово в вопросе должно быть тегом ... Нет неуважения, просто высказываю свою точку зрения :)
Нику Сурду

11
Я использую toastтег для. Я думал, что теги были там, чтобы помочь в поиске и сортировке, и toastэто определенно обычный поиск. androidи toastказаться идеальным.
ChrisWilson4

Ответы:


142

Значения LENGTH_SHORTи LENGTH_LONGравны 0 и 1. Это означает, что они обрабатываются как флаги, а не как фактические длительности, поэтому я не думаю, что будет возможно установить длительность в любое значение, кроме этих значений.

Если вы хотите, чтобы сообщение показывалось пользователю дольше, рассмотрите уведомление в строке состояния . Уведомления в строке состояния могут быть программно отменены, когда они больше не актуальны.


1
Спасибо за предложение по поводу строки состояния, но я собираюсь с пользовательским диалогом.

337

Если вы покопаетесь глубже в коде 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

4
Спасибо ... это было именно то, что мне было нужно.
mcherm

3
Спасибо за публикацию значений по умолчанию! Я боялся, что не смогу их найти.
Amplify91

1
Я также искал значения тостов по умолчанию, это был первый хит. Определенно проголосовал. Спасибо!
Дейв

120

Вы можете попробовать:

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

удвоить время Если вы укажете 3 вместо 2, это утроит время .. и т. Д.


17
сообщение мигает :(
Дениз

61
Это решение плохое, потому что, например, если вы выйдете из активности до времени тоста, оно будет мигать снова и снова ...
dwbrito

@dwbrito: полностью согласен и, следовательно, -1
Фахим Паркар

[+1] за ответ .... Отмену тоста можно выполнить, используя Toast.cancel()соответствующие места
Devrath

1
Да, это может быть реализовано, но тост будет мигать столько раз, сколько вы укажете
HendraWD

31

Если вы хотите, чтобы a Toastсохранялся, я обнаружил, что вы можете обойти его путем повторного Timerвызова toast.show()(каждую секунду или около того следует делать). Вызов show()ничего не прерывает, если Toastон уже отображается, но он обновляет количество времени, которое остается на экране.


3
Проблема в том, что если пользователь коснется экрана, тост будет скрыт Android, но затем воссоздан по таймеру.
Фиолетовый Жираф

2
@VioletGiraffe - это довольно тривиально, чтобы справиться с чем-то вроде логического флага в вашем ViewGroup OnTouchмероприятии. Чтобы оптимизировать это, вы, вероятно, должны сделать так, чтобы ваш таймер повторялся как можно ближе к фактическому времени, Toastкоторое отображается на экране (3,5 секунды для длинных, 2 секунды для коротких)
syklon

18

Я разработал класс Custom 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: невозможно добавить окно - нулевой токен недействителен; ваша деятельность работает?
Ахамадулла Сайкат

13

Я написал вспомогательный класс для этого. Вы можете увидеть код на 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);

Спасибо и Ницца, но как мы можем остановить поток на Дестрой, например? Я пытался сделать это, но не уверен: public static void cancel (Toast mytoast) {if (null! = T) t.stop (); mytoast.cancel (); }
hornetbzz

10

Я знаю, что немного опоздал, но я взял ответ 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);

Это на самом деле работает! но как сделать его настраиваемым и осязаемым?
Android разработчик

Извините за этот вопрос новичка, но когда я создаю вышеупомянутый класс Toaster, он говорит, что не может разрешить символ 'App' в строке. окончательный Toast t = Toast.makeText (App.context (), текст, Toast.LENGTH_SHORT); Спасибо и извинения.
Брайан Флеминг

о, извините за это! App.context () - это, по сути, фрагмент пользовательского кода, который я написал для удобного доступа к ApplicationContext из любого места, не передавая его. Не шаблон, который вы бы использовали для многих вещей, но я обнаружил, что он имеет смысл для ApplicationContext. Вы можете отредактировать этот фрагмент, чтобы передать ApplicationContext в метод в качестве аргумента.
Крис

9

Я знаю, что ответ довольно поздно. У меня возникла та же проблема, и я решил реализовать свою собственную версию Toast, после изучения исходного кода Android для 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 (), которые вы можете публиковать в Handler.

    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);

}

Это была быстрая и грязная реализация. Не принимал во внимание какую-либо производительность.


1
Я пытался запустить его (включая вызов "show ()"), но ничего не появляется (проверено на Android 7.1). Я думаю, что вы что-то упускаете. Кроме того, где находится часть, которая препятствует удалению вида, так как тост исчезает через короткое время?
Android-разработчик

8

Показ тостов LONG_DELAY в течение 3,5 секунд и показ тостов SHORT_DELAY в течение 2 секунд .

Toast внутренне использует INotificationManager и вызывает его метод enqueueToast при каждом вызове Toast.show ().

Вызовите show () с SHORT_DELAY дважды, чтобы снова поставить в очередь один и тот же тост. он будет отображаться в течение 4 секунд (2 секунды + 2 секунды).

аналогично, вызов show () дважды с LONG_DELAY снова поставит в очередь один и тот же тост. будет отображаться для 7 с (3,5 с + 3,5 с)


6

Вот пользовательский класс 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();  
    }
}

5

Если вам нужен длинный тост, есть практическая альтернатива, но он требует, чтобы ваш пользователь нажал кнопку ОК, чтобы он исчез. Вы можете использовать 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();

Если у вас длинное сообщение, скорее всего, вы не знаете, сколько времени понадобится вашему пользователю, чтобы прочитать сообщение, поэтому иногда полезно попросить пользователя нажать кнопку ОК, чтобы продолжить. В моем случае я использую эту технику, когда пользователь нажимает на значок справки.


1
Это умно, но не может быть реализовано в чем-то вроде Service, где нет пользовательского интерфейса.
mike47

@mikejeep На самом деле, я недавно видел пример от Google, показывающий диалоговое окно без активности: developer.android.com/samples/AppShortcuts/index.html
разработчик Android

5

Как уже упоминалось, Android-тосты могут быть LENGTH_LONG или LENGTH_SHORT. Обойти это невозможно, и вы не должны следовать ни одному из опубликованных «хаков».

Цель тостов состоит в том, чтобы отображать «несущественную» информацию, и из-за их длительного эффекта сообщения могут быть выведены из контекста, если их продолжительность превышает определенный порог. Если бы обычные тосты были изменены так, чтобы они могли отображаться дольше, чем LENGTH_LONG, сообщение будет задерживаться на экране до тех пор, пока процесс приложения не будет завершен, поскольку тостовые представления добавляются в WindowManager, а не в ViewGroup в вашем приложении. Я предположил бы, что это - то, почему это жестко закодировано.

Если вам абсолютно необходимо, чтобы сообщение в стиле тоста длилось более трех с половиной секунд, я рекомендую создать представление, которое присоединяется к содержимому действия, таким образом оно исчезнет, ​​когда пользователь выйдет из приложения. Моя библиотека SuperToasts занимается этой проблемой и многими другими, не стесняйтесь использовать ее! Скорее всего, вам будет интересно использовать SuperActivityToasts


4

Просто используйте SuperToast, чтобы сделать элегантный тост в любой ситуации. Сделайте свой тост красочным . Отредактируйте свой цвет шрифта, а также его размер . Надеюсь, это будет все в одном для вас.



3

Вот очень простой метод, который работал для меня:

for (int i=0; i < 3; i++) { Toast.makeText(this, "MESSAGE", Toast.LENGTH_SHORT).show(); }

Продолжительность LENGTH_SHORT составляет 2 секунды, а LENGTH_LONG составляет 3,5 секунды. Здесь сообщение о тосте будет отображаться в течение 6 секунд, поскольку оно заключено в цикл for. Но недостатком этого метода является то, что через каждые 2 секунды может возникнуть небольшой эффект замирания. но это не сильно заметно. Надеюсь, это полезно


2

Пользователь не может по собственному усмотрению определить продолжительность тоста. потому что функция scheduleTimeoutLocked () NotificationManagerService не использует длительность поля. Исходный код следующий.

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);
    }

2

Используйте Crouton, это очень гибкая библиотека Toast.

гренок для супа

Вы можете использовать его как тосты:

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

или вы можете даже пойти немного глубже и настроить его больше, например, установить время бесконечно! например, здесь я хочу показать тостовое сообщение, пока пользователь не подтвердит его, нажав на него.

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>

2

Длительность тоста может быть взломана с помощью потока, который запускает тост исключительно. Это работает (запускает тост в течение 10 секунд, изменяет сон и 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();

1

Тост с пользовательским фоном и видом сделал свое дело для меня. Я протестировал его на планшете 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 / frag_background заставляет мой тост иметь закругленный угол, как в версии Kitkat. Вы также можете добавить другие виды в файл. Любые изменения для улучшения и комментарии приветствуются, так как я планирую реализовать это в моем живом приложении.


1

Запланируйте обратный отсчет до определенного времени в будущем с регулярными уведомлениями об интервалах по пути. Пример отображения 30-секундного обратного отсчета в текстовом поле:

     новый CountDownTimer (30000, 1000) {

     public void onTick (long millisUntilFinished) {
         mTextField.setText («осталось секунд:» + millisUntilFinished / 1000);
     }

     public void onFinish () {
         mTextField.setText ( "сделано!");
     }
  }.Начало();



1

Этот текст исчезнет через 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 секунды
Itai Spector

@ItaiSpector: Проверьте мой новый код, пожалуйста.
Алиреза Нурали,

1

Нет, и большинство / все хаки, перечисленные здесь, больше не работают в 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();

Хотя это не тот ответ, который искал Хуссейн, это лучший вариант, чем все эти «хаки»!
Дэнни Е.К. ван дер Колк

0

Очень простой подход к созданию более длинного сообщения заключается в следующем:

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, быть полезным и в соответствии с предполагаемым использованием.


0

Устанавливает тост за определенный период в миллисекундах:

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);
        }
    }
}

0
  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();
      }

0

После сбоя в каждом доступном решении я наконец-то нашел обходной путь с использованием рекурсии.

Код:

//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);
}

2
Большинство решений по этому вопросу, связанных с повторным вызовом «show» для отображения отображаемого тоста, делается с одним и тем же экземпляром тоста, тогда как на самом деле вы создаете новый экземпляр тоста каждую секунду и указываете, что каждый из них должен отображаться для LONG. продолжительность (обычно 3,5 секунды). Это не только неэффективно, потому что вы продолжаете создавать дополнительные экземпляры объектов, но и Android помещает всплывающие сообщения в очередь, которая будет отображаться одна за другой в течение указанной продолжительности. Так что если вы вызываете это с продолжительностью 5, сообщение будет отображаться в течение 17,5 секунд.
Найл

-1
Toast.makeText(this, "Text", Toast.LENGTH_LONG).show(); 
Toast.makeText(this, "Text", Toast.LENGTH_LONG).show();

Очень простое решение вопроса. Два или три раза из них заставит тост длиться дольше. Это единственный путь.


Хотя звучит взломать, но ценим мышление!
Sony Kadavan

почему downvoted подобное решение, упомянутое @Arturo, использует тот же трюк с циклом for
потрепанный

Этот подход работал для меня. Было бы хорошо услышать от тех, кто проголосовал за то, почему они это сделали.
Кристофер Миллс

-8

Вы можете установить желаемое время в миллисекундах следующим Toast.makeText();способом:

//40 seconds
long mToastLength = 40*1000 
//this toast will be displayed for 40 seconds.
Toast.makeText(this, "Hello!!!!!", mToastLength).show(); 

1
Ответ правильный! API был расширен в некоторый момент времени, чтобы позволить использовать значение, отличное от LENGTH_LONG или LENGTH_SHORT. Я
RTs

Я так не думаю. Посмотрите на android.googlesource.com/platform/frameworks/base/+/…
AntiCZ
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.