Czy Android Toast może być dłuższy niż Toast.LENGTH_LONG?


263

Czy podczas korzystania z metody setDuration () dla Toast można ustawić niestandardową długość lub przynajmniej coś dłuższego niż Toast.LENGTH_LONG?


4
@Nicolae z jakiegoś powodu usunąłeś toasttag? Wygląda na to, że odnosi się do pytania.
Shadow Wizard is Ear For You

2
@ShadowWizard Wydaje mi się, że tagi powinny odzwierciedlać tematy pytania, które jest bardzo interesujące. Jak na przykład, jest oznaczony androidem, więc guru Androida znajdzie to pytanie. Toast wcale nie pomaga na to pytanie i wydaje się bardziej bezużytecznym tagiem. Jeśli toast jest dobry, ponieważ pytanie dotyczy tagu w Androidzie, to również długość była dobrym tagiem. Hack, każde słowo w pytaniu powinno być tagiem ... Bez szacunku, tylko o co mi chodzi :)
Nicu Surdu,

11
Używam toasttagu do. Myślałem, że tagi były tam, aby pomóc w wyszukiwaniu i sortowaniu, i toastjest to zdecydowanie częste wyszukiwanie. androidi toastwydaje się idealny.
ChrisWilson4

Odpowiedzi:


142

Wartości LENGTH_SHORTi LENGTH_LONGwynoszą 0 i 1. Oznacza to, że są one traktowane jako flagi, a nie rzeczywiste czasy trwania, więc nie sądzę, aby można było ustawić czas trwania na cokolwiek innego niż te wartości.

Jeśli chcesz wyświetlać użytkownikowi wiadomość dłużej, rozważ Powiadomienie na pasku stanu . Powiadomienia na pasku stanu można programowo anulować, gdy nie są już istotne.


1
Dzięki za sugestię dotyczącą paska stanu, ale wybieram niestandardowe działanie w oknie dialogowym.

337

Jeśli zagłębisz się głębiej w kod Androida, możesz znaleźć wiersze, które wyraźnie wskazują, że nie możemy zmienić czasu trwania wiadomości Toast.

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

a domyślne wartości czasu trwania to

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

4
Dzięki ... to było dokładnie to, czego potrzebowałem.
mcherm

3
Dziękujemy za opublikowanie wartości domyślnych! Bałem się, że nie będę w stanie ich znaleźć.
Amplify91

1
Szukałem również domyślnych wartości tostów, to był pierwszy hit. Zdecydowanie pozytywnie oceniany. Dzięki!
Dave

120

Możesz spróbować:

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

podwoić czas. Jeśli podasz 3 zamiast 2, potroi to czas ... itd.


17
wiadomość miga :(
Deniz

61
To rozwiązanie jest złe, ponieważ np. Jeśli zrezygnujesz z aktywności przed czasem toastu, będzie migać w kółko ...
dwbrito

@dwbrito: całkowicie się zgadzam, a więc -1
Fahim Parkar

[+1] za odpowiedź .... Anulowanie toastu można wykonać, używając Toast.cancel()w odpowiednich miejscach
Devrath

1
Tak, można to wdrożyć, ale toast będzie mrugał tak długo, jak podasz liczbę
HendraWD

31

Jeśli chcesz się Toastupierać, odkryłem, że możesz zhakować sobie drogę, powtarzając Timerpołączenie toast.show()(co sekunda powinno to zrobić). Wywołanie show()niczego nie psuje, jeśli Toastjest już wyświetlane, ale odświeża ilość czasu, jaki pozostaje na ekranie.


3
Problem polega na tym, że jeśli użytkownik dotknie ekranu, toast zostanie ukryty przez Androida, a następnie odtworzony przez timer.
Violet Giraffe

2
@ VioletGiraffe jest dość trywialny w obsłudze z czymś takim, jak flaga logiczna w twoim ViewGroup OnTouchwydarzeniu. Aby to zoptymalizować, powinieneś prawdopodobnie powtórzyć swój czas tak blisko rzeczywistego czasu, jaki Toastjest pokazywany na ekranie (3,5 sekundy dla długiego, 2 sekundy dla krótkiego)
syklon 30.01.2013

18

Opracowałem niestandardową klasę toastów, dzięki której możesz pokazywać tosty przez określony czas (w milisekundach)

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: Nie można dodać okna - token null jest nieprawidłowy; czy twoja aktywność działa?
Ahamadullah Saikat

13

Stworzyłem klasę pomocników, aby to zrobić. Możesz zobaczyć kod na github: https://github.com/quiqueqs/Toast-Expander/blob/master/src/com/thirtymatches/toasted/ToastedActivity.java

Oto sposób wyświetlania toastu przez 5 sekund (lub 5000 milisekund):

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

Dzięki i Nicei, ale jak możemy na przykład zatrzymać wątek na Destroy? Próbowałem to zrobić, ale nie jestem pewien: public static void cancel (Toast mytoast) {if (null! = T) t.stop (); mytoast.cancel (); }
hornetbzz

10

Wiem, że jestem trochę spóźniony, ale wziąłem odpowiedź Regis_AG i umieściłem ją w klasie pomocniczej i działa świetnie.

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

W kodzie aplikacji po prostu zrób coś takiego:

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

To faktycznie działa! ale jak sprawić, by można go było dostosowywać i dotykać?
programista Androida

Przepraszam za to pytanie dla początkujących, ale kiedy tworzę powyższą klasę tostera, mówi ona, że ​​nie może rozwiązać symbolu „App” w linii. final Toast t = Toast.makeText (App.context (), tekst, Toast.LENGTH_SHORT); Dzięki i przepraszam.
Brian Fleming

Oh przepraszam za to! App.context () jest w zasadzie kawałkiem niestandardowego kodu, który napisałem, aby uzyskać wygodny dostęp do ApplicationContext z dowolnego miejsca bez przekazywania go. Nie jest to wzorzec, którego można by użyć do wielu rzeczy, ale okazało się, że ma sens dla ApplicationContext. Możesz edytować ten fragment kodu, aby przekazać ApplicationContext do metody jako argument.
Chris Aitchison

9

Wiem, że odpowiedź jest dość późna. Miałem ten sam problem i postanowiłem wdrożyć własną wersję gołej kości Toast, po zapoznaniu się z kodem źródłowym Androida na toast.

Zasadniczo musisz utworzyć nowy menedżer okien oraz pokazać i ukryć okno przez żądany czas trwania za pomocą modułu obsługi

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

Po zainicjowaniu układu możesz użyć własnych metod ukrywania i pokazywania

    public void handleShow() {
    mWindowManager.addView(mLayout, mParams);
    }

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

Teraz wystarczy dodać dwa działające wątki, które wywołują uchwytShow () i uchwytHide (), które można opublikować w module obsługi.

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

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

i ostatnia część

public void show() {

    mHandler.post(toastShowRunnable);
    //The duration that you want
    mHandler.postDelayed(toastHideRunnable, mDuration);

}

To była szybka i brudna implementacja. Nie wziąłem pod uwagę wydajności.


1
Próbowałem go uruchomić (w tym wywołanie „show ()”), ale nic się nie pojawiło (testowane na Androidzie 7.1). Myślę, że czegoś brakuje. A także, gdzie jest ta część, która uniemożliwia usunięcie widoku, ponieważ toast znika po krótkim czasie?
programista Androida

8

Wyświetlanie tostów LONG_DELAY przez 3,5 sekundy i wyświetlanie toastów SHORT_DELAY przez 2 sekundy .

Toast wewnętrznie używa INotificationManager i wywołuje metodę enqueueToast za każdym razem, gdy wywoływana jest Toast.show ().

Dwukrotne wywołanie show () za pomocą SHORT_DELAY spowoduje ponowne umieszczenie tego samego toastu. będzie wyświetlany przez 4 sekundy (2 sekundy + 2 sekundy).

podobnie, wywołanie show () za pomocą LONG_DELAY dwukrotnie spowoduje kolejkowanie tego samego toastu. będzie wyświetlany przez 7 sekund (3,5 sekundy + 3,5 sekundy)


6

Oto niestandardowa klasa Toast utworzona przy użyciu powyższego kodu:

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

Jeśli potrzebujesz długiego Toastu, istnieje praktyczna alternatywa, ale wymaga kliknięcia przycisku OK, aby go usunąć. Możesz użyć AlertDialog w następujący sposób:

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

Jeśli masz długą wiadomość, prawdopodobnie nie wiesz, ile czasu zajmie jej przeczytanie przez użytkownika, więc czasami dobrym pomysłem jest wymaganie od użytkownika kliknięcia przycisku OK, aby kontynuować. W moim przypadku używam tej techniki, gdy użytkownik kliknie ikonę pomocy.


1
Jest to inteligentne, ale nie można go zaimplementować w czymś takim Service, jak interfejs użytkownika.
mike47

@ mikejeep Właściwie ostatnio widziałem przykład Google pokazujący okno dialogowe bez aktywności: developer.android.com/samples/AppShortcuts/index.html
programista Androida

5

Jak wspomnieli inni, Android Toast może mieć wartość LENGTH_LONG lub LENGTH_SHORT. Nie można tego obejść, ani nie należy śledzić żadnego z opublikowanych „hacków”.

Celem Toastów jest wyświetlanie „nieistotnych” informacji, a ze względu na ich trwały efekt wiadomości mogą być odsunięte od kontekstu, jeśli ich czas trwania przekroczy określony próg. Jeśli zapasowe Tosty zostały zmodyfikowane, aby mogły wyświetlać się dłużej niż LENGTH_LONG, wiadomość pozostawałaby na ekranie, dopóki proces aplikacji nie zostanie zakończony, ponieważ widoki Toast są dodawane do WindowManager, a nie ViewGroup w Twojej aplikacji. Zakładam, że właśnie dlatego jest mocno zakodowany.

Jeśli absolutnie musisz pokazać wiadomość w stylu toast dłuższą niż trzy i pół sekundy, zalecam zbudowanie widoku, który zostanie dołączony do treści działania, w ten sposób zniknie, gdy użytkownik wyjdzie z aplikacji. Moja biblioteka SuperToastów zajmuje się tym problemem i wielu innych, zachęcamy do korzystania z niego! Najprawdopodobniej byłbyś zainteresowany korzystaniem z SuperActivityToasts


4

Wystarczy użyć SuperToast, aby zrobić elegancki toast w każdej sytuacji. Spraw, aby toast był kolorowy . Edytuj kolor czcionki, a także jej rozmiar . Mam nadzieję, że będzie to dla ciebie wszystko w jednym.



3

Oto bardzo prosta metoda, która zadziałała dla mnie:

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

Czas trwania LENGTH_SHORT wynosi 2 sekundy, a LENGTH_LONG wynosi 3,5 sekundy, tutaj komunikat toast będzie wyświetlany przez 6 sekund, ponieważ jest zamknięty w pętli for. Jednak wadą tej metody jest to, że po każdych 2 sekundach może pojawić się niewielki efekt zanikania. ale nie jest to zbytnio zauważalne. Mam nadzieję, że to jest pomocne


2

Użytkownik nie może zdefiniować czasu trwania Toastu. ponieważ funkcja scheduleTimeoutLocked () NotificationManagerService nie używa czasu trwania pola. kod źródłowy jest następujący.

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

Użyj Crouton, jest to bardzo elastyczna biblioteka Toast.

Grzanka

Możesz go używać tak jak tosty:

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

lub możesz pójść trochę głębiej i dostosować go bardziej, na przykład ustawić czas na nieskończoność! na przykład tutaj chcę wyświetlać wiadomość toast, dopóki użytkownik nie potwierdzi jej, klikając ją.

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

Układ klienta, który zostanie napompowany do tostów.

<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

Czas trwania toastu można zhakować za pomocą wątku, który uruchamia toast wyłącznie. Działa to (uruchamia toast na 10 sekund, modyfikuje tryb uśpienia i ctr do własnych upodobań):

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

Toast za niestandardowe tło i widok załatwił sprawę. Testowałem to na tablecie Nexus 7 i nie zauważyłem żadnej animacji zanikania / zanikania podczas zapętlania. Oto wdrożenie:

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

}

Oto niestandardowy widok tekstu użyty w powyższym kodzie:

<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 sprawia, że ​​mój toast ma zaokrąglony róg, jak w wersji KitKat. Możesz także dodać inne widoki w pliku. Zachęca się do wprowadzania jakichkolwiek zmian w celu ulepszenia i komentarzy, ponieważ planuję wdrożyć to w mojej aplikacji na żywo.


1

Zaplanuj odliczanie do czasu w przyszłości, z regularnymi powiadomieniami o interwałach po drodze. Przykład pokazujący 30-sekundowe odliczanie w polu tekstowym:

     nowy CountDownTimer (30000, 1000) {

     public void onTick (long millisUntilFinished) {
         mTextField.setText („pozostało sekund:” + millisUntilFinished / 1000);
     }

     public void onFinish () {
         mTextField.setText („gotowe!”);
     }
  }.początek();



1

Ten tekst zniknie za 5 sekund.

    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

Edycja: Jak powiedział Itai Spector w komentarzu, będzie wyświetlany około 3,5 sekundy, więc użyj tego kodu:

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

Myślę, że ten tekst zniknie po 3,5 sekundach
Itai Spector

@ItaiSpector: Proszę sprawdzić mój nowy kod.
Alireza Noorali,

1

Nie, a większość wymienionych tu włamań nie działa już w Androidzie 9. Jest jednak o wiele lepsze rozwiązanie: jeśli wiadomość musi się zawiesić, użyj okna dialogowego.

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

Chociaż nie jest to odpowiedź, której szukał Hussein, jest to lepsza opcja niż wszystkie te „hacki”!
Danny EK van der Kolk

0

Bardzo proste podejście do tworzenia nieco dłuższej wiadomości jest następujące:

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

Zauważ, że powyższy przykład eliminuje opcję LENGTH_SHORT, aby zachować prostotę przykładu.

Zasadniczo nie będziesz chciał używać komunikatu Toast do wyświetlania komunikatów przez bardzo długie okresy, ponieważ nie jest to zamierzonym celem klasy Toast. Ale są chwile, kiedy ilość tekstu, który musisz wyświetlić, może zająć użytkownikowi więcej niż 3,5 sekundy, aby przeczytać, i w takim przypadku niewielkie wydłużenie czasu (np. Do 6,5 sekundy, jak pokazano powyżej) może być przydatne, IMO, i zgodne z przeznaczeniem.


0

Ustawia toast na określony okres w milisekundach:

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

Po niepowodzeniu z każdym dostępnym rozwiązaniem w końcu miałem obejście za pomocą rekurencji.

Kod:

//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
Większość rozwiązań tego pytania dotyczących wielokrotnego wywoływania „pokaż”, aby wyświetlać toast, robi to z tą samą instancją toastową, podczas gdy twoja faktycznie tworzy nową instancję toastową co sekundę i określa, że ​​każda z nich powinna być wyświetlana przez DŁUGI czas trwania (zwykle 3,5 sekundy). Jest to nie tylko nieefektywne, ponieważ ciągle tworzysz dodatkowe instancje obiektów, ale także system Android umieszcza wiadomości toast w kolejce, aby były wyświetlane jeden po drugim przez określony czas. Więc jeśli zadzwonisz na czas 5, komunikat będzie pokazywany przez 17,5 sekundy.
Niall

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

Bardzo proste rozwiązanie tego pytania. Dwa lub trzy z nich sprawią, że Toast będzie trwać dłużej. To jedyna droga.


Choć brzmi hack, ale doceń myślenie!
Sony Kadavan

dlaczego przegłosowano podobne rozwiązanie wspomniane przez @Arturo, używa tej samej sztuczki z pętlą for
shabby

To podejście zadziałało dla mnie. Dobrze byłoby usłyszeć od tych, którzy głosowali, dlaczego to zrobili.
Christopher Mills,

-8

Możesz ustawić żądany czas w milisekundach w następujący Toast.makeText();sposób:

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

1
Odpowiedź jest prawidłowa! Interfejs API został w pewnym momencie rozszerzony, aby umożliwić użycie wartości innej niż LENGTH_LONG lub LENGTH_SHORT. I
rts

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.