¿Puede un Android Toast ser más largo que Toast.LENGTH_LONG?

263

Al usar setDuration () para un Toast, ¿es posible establecer una longitud personalizada o al menos algo más largo que Toast.LENGTH_LONG?

Hussein El Feky
fuente
44
@Nicolae ¿alguna razón por la que eliminó la toastetiqueta? Parece relevante para la pregunta ..
Shadow Wizard is Ear For You
2
@ShadowWizard Las etiquetas, me parece, deberían reflejar los temas de la pregunta que es de gran interés. Como por ejemplo, está etiquetado como Android, por lo que un gurú de Android encontrará esta pregunta. Toast no ayuda en absoluto a esta pregunta y parece más una etiqueta inútil. Si una tostada es buena, porque la pregunta es acerca de la etiqueta en Android, entonces también la longitud fue una buena etiqueta. Hack, cada palabra en la pregunta debería ser una etiqueta ... No faltar al respeto, solo estoy haciendo mi punto :)
Nicu Surdu
11
Yo uso la toastetiqueta para. Pensé que las etiquetas estaban allí para ayudar a buscar y ordenar, y toastdefinitivamente es una búsqueda común. androidy toastparece perfecto
ChrisWilson4

Respuestas:

142

Los valores de LENGTH_SHORTy LENGTH_LONGson 0 y 1. Esto significa que se tratan como indicadores en lugar de duraciones reales, por lo que no creo que sea posible establecer la duración en nada más que estos valores.

Si desea mostrar un mensaje al usuario por más tiempo, considere una Notificación de barra de estado . Las notificaciones de la barra de estado se pueden cancelar mediante programación cuando ya no son relevantes.

Dave Webb
fuente
1
Gracias por la sugerencia sobre la barra de estado, pero voy con una actividad de diálogo personalizada.
337

Si profundiza en el código de Android, puede encontrar las líneas que indican claramente que no podemos cambiar la duración del mensaje Toast.

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

y los valores predeterminados para la duración son

private static final int LONG_DELAY = 3500; // 3.5 seconds
private static final int SHORT_DELAY = 2000; // 2 seconds
Sentirse bien
fuente
44
Gracias ... esto fue EXACTAMENTE lo que necesitaba.
mcherm
3
¡Gracias por publicar los valores predeterminados! Tenía miedo de no poder encontrarlos.
Amplify91
1
Estaba buscando los valores de tostado predeterminados también, este fue el primer éxito. Definitivamente votado. ¡Gracias!
Dave
120

Es posible que desee probar:

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

duplicar el tiempo Si especifica 3 en lugar de 2, triplicará el tiempo ... etc.

Arturo
fuente
17
el mensaje parpadea :(
Deniz
61
Esta solución es mala porque, por ejemplo, si abandonas la actividad antes del momento del brindis, parpadeará una y otra vez ...
dwbrito
@dwbrito: totalmente de acuerdo y por lo tanto -1
Fahim Parkar
[+1] para la respuesta ... La cancelación de la tostada se puede manejar usando Toast.cancel()en lugares apropiados
Devrath
1
Sí, se puede implementar, pero el brindis parpadeará tanto como especifique el recuento
HendraWD
31

Si desea Toastque persista, descubrí que puede sortearlo haciendo una Timerllamada toast.show()repetidamente (cada segundo más o menos debería hacerlo). Las llamadas show()no interrumpen nada si Toastya se muestra, pero actualiza la cantidad de tiempo que permanece en la pantalla.

iandisme
fuente
3
El problema con esto es que si el usuario toca la pantalla, Android brindará el brindis, pero luego el temporizador lo volverá a crear.
Violet Giraffe
2
@VioletGiraffe es bastante trivial de manejar con algo como una bandera booleana en su ViewGroup OnTouchevento. Para optimizar esto, probablemente debería hacer que su temporizador se repita tan cerca del tiempo real que Toastse muestra en la pantalla (3.5 segundos por mucho tiempo, 2 segundos por poco tiempo)
syklon
18

He desarrollado una clase de Toast personalizada con la que puede mostrar Toast durante un tiempo deseado (en Milli segundos)

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);
        }
    }
}
Gopal Gopi
fuente
android.view.WindowManager $ BadTokenException: no se puede agregar la ventana; el token nulo no es válido; ¿se está ejecutando tu actividad?
Ahamadullah Saikat
13

Codifiqué una clase auxiliar para hacer esto. Puede ver el código en github: https://github.com/quiqueqs/Toast-Expander/blob/master/src/com/thirtymatches/toasted/ToastedActivity.java

Así es como mostrarías una tostada durante 5 segundos (o 5000 milisegundos):

Toast aToast = Toast.makeText(this, "Hello World", Toast.LENGTH_SHORT);
ToastExpander.showFor(aToast, 5000);
Henrique
fuente
Thx and Nice, pero ¿cómo podemos detener el hilo en Destroy, por ejemplo? He intentado hacer eso, pero no estoy seguro: public static void cancel (Toast mytoast) {if (null! = T) t.stop (); mytoast.cancel (); }
hornetbzz
10

Sé que llego un poco tarde, pero tomé la respuesta de Regis_AG y la envolví en una clase auxiliar y funciona muy bien.

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

En el código de su aplicación, simplemente haga algo como esto:

    Toaster.makeLongToast("Toasty!", 8000);
Chris Aitchison
fuente
¡Esto realmente funciona! pero, ¿cómo puedes hacerlo personalizable y táctil?
Desarrollador de Android el
Perdón por esta pregunta de novato, pero cuando creo la clase Toaster anterior, dice que no puede resolver el símbolo 'Aplicación' en la línea. Toast final t = Toast.makeText (App.context (), text, Toast.LENGTH_SHORT); Gracias y disculpas.
Brian Fleming el
¡Oh, perdon por eso! App.context () es básicamente un fragmento de código personalizado que había escrito para acceder al ApplicationContext convenientemente desde cualquier lugar sin pasarlo. No es un patrón que usarías para muchas cosas, pero descubrí que tenía sentido para ApplicationContext. Es posible que desee editar este fragmento para pasar ApplicationContext al método como argumento.
Chris Aitchison
9

Sé que la respuesta es bastante tardía ... Tuve el mismo problema y decidí implementar mi propia versión de Toast, después de buscar el código fuente de Android para Toast.

Básicamente, debe crear un nuevo administrador de ventanas, y mostrar y ocultar la ventana durante el tiempo de duración deseado utilizando un controlador

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

Después de inicializar el diseño, puede usar sus propios métodos de ocultar y mostrar

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

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

Ahora todo lo que necesita es agregar dos subprocesos ejecutables que llamen a handleShow () y handleHide () que podría publicar en el controlador.

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

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

y la parte final

public void show() {

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

}

Esta fue una implementación rápida y sucia. No he tenido en cuenta ningún rendimiento.

Chris
fuente
1
Traté de ejecutarlo (incluida la llamada a "show ()") pero no aparece nada (probado en Android 7.1). Creo que extrañas algo. Además, ¿dónde está la parte aquí que evita que se elimine la vista, ya que un brindis desaparece después de un corto tiempo?
Desarrollador de Android el
8

Pantalla de tostadas LONG_DELAY durante 3.5 segundos y pantalla de tostadas SHORT_DELAY durante 2 segundos .

Toast usa INotificationManager internamente y llama a su método enqueueToast cada vez que se llama a Toast.show ().

Llamar al show () con SHORT_DELAY dos veces pondrá en cola la misma tostada de nuevo. se mostrará durante 4 segundos (2 segundos + 2 segundos).

Del mismo modo, llame al show () con LONG_DELAY dos veces y volverá a poner en cola el mismo brindis. se mostrará durante 7 segundos (3.5 segundos + 3.5 segundos)

Lava Sangeetham
fuente
6

Aquí hay una clase personalizada de Toast que hice usando el código anterior:

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();  
    }
}
Philipp F
fuente
5

Si necesita una tostada larga, hay una alternativa práctica, pero requiere que su usuario haga clic en un botón Aceptar para que desaparezca. Puede usar un AlertDialog como este:

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

Si tiene un mensaje largo, lo más probable es que no sepa cuánto tiempo le tomará a su usuario leer el mensaje, por lo que a veces es una buena idea pedirle a su usuario que haga clic en un botón Aceptar para continuar. En mi caso, uso esta técnica cuando un usuario hace clic en un icono de ayuda.

Steven
fuente
1
Esto es inteligente, pero no se puede implementar en algo como a Service, donde no hay interfaz de usuario.
mike47
@mikejeep En realidad, recientemente he visto un ejemplo de Google que muestra un diálogo sin actividad: developer.android.com/samples/AppShortcuts/index.html
desarrollador de Android el
5

Según lo mencionado por otros, Android Toast puede ser LENGTH_LONG o LENGTH_SHORT. No hay forma de evitar esto, ni debes seguir ninguno de los 'hacks' publicados.

El propósito de Toast es mostrar información "no esencial" y, debido a su efecto persistente, los mensajes pueden quedar fuera de contexto si su duración supera un cierto umbral. Si las tostadas de stock se modificaran para que puedan mostrarse más de LENGTH_LONG, el mensaje permanecería en la pantalla hasta que finalice el proceso de la aplicación, ya que las vistas de tostadas se agregan al WindowManager y no un ViewGroup en su aplicación. Supongo que es por eso que está codificado.

Si necesita mostrar un mensaje de estilo tostado durante más de tres segundos y medio, le recomiendo que cree una vista que se adjunte al contenido de la Actividad, de esa forma desaparecerá cuando el usuario salga de la aplicación. Mi biblioteca de SuperToasts trata este problema y muchos otros, ¡no dudes en usarlo! Lo más probable es que te interese usar SuperActivityToasts

John P.
fuente
4

Simplemente use SuperToast para hacer un brindis elegante en cualquier situación. Haz que tus tostadas sean coloridas . Edite el color de su fuente y también su tamaño . Espero que sea todo en uno para ti.

Muhammad Jobayer
fuente
3

Aquí hay un método muy simple que funcionó para mí:

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

La duración de LENGTH_SHORT es de 2 segundos y LENGTH_LONG es de 3.5 segundos. Aquí el mensaje de tostada se mostrará durante 6 segundos ya que está encerrado en un bucle for. Pero un inconveniente de este método es que después de cada 2 segundos puede surgir un pequeño efecto de desvanecimiento. Pero no se nota mucho. Espero que sea útil

Liya
fuente
2

El usuario no puede personalizar la duración del Toast. porque la función scheduleTimeoutLocked () de NotificationManagerService no usa la duración del campo. El código fuente es el siguiente.

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);
    }
cronaldoyang
fuente
2

Use Crouton, es una biblioteca Toast muy flexible.

Cuscurro

Puedes usarlo como tostadas:

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

¡o incluso puede ir un poco más profundo y personalizarlo más, como configurar el tiempo en infinito! Por ejemplo, aquí quiero mostrar un mensaje tostado hasta que el usuario lo reconozca haciendo clic en él.

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

Diseño personalizado que se inflará para el brindis.

<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>
Muhammad Alfaifi
fuente
2

La duración de la tostada se puede hackear usando un hilo que ejecuta la tostada exclusivamente. Esto funciona (ejecuta la tostada durante 10 segundos, modifica el sueño y el control a tu gusto):

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();
ExeCode
fuente
1

Un brindis con fondo y vista personalizados me sirvió. Lo probé en la tableta nexus 7 y no noté ninguna animación de desvanecimiento gradual durante el bucle. Aquí está la implementación:

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

}

Aquí está la vista de texto personalizada utilizada en el código anterior:

<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 está haciendo que mi tostada tenga una esquina redondeada como en la versión kitkat. También puede agregar otras vistas en el archivo. Se recomienda cualquier modificación para mejorar y comentar ya que planeo implementar esto en mi aplicación en vivo.

Argumento ilegal
fuente
1

Programe una cuenta regresiva hasta un momento en el futuro, con notificaciones regulares en intervalos en el camino. Ejemplo de mostrar una cuenta regresiva de 30 segundos en un campo de texto:

     nuevo CountDownTimer (30000, 1000) {

     public void onTick (long millisUntilFinished) {
         mTextField.setText ("segundos restantes:" + millisUntilFinished / 1000);
     }

     public void onFinish () {
         mTextField.setText ("hecho!");
     }
  }.comienzo();


Houssin Boulla
fuente
1

Este texto desaparecerá en 5 segundos.

    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

Editar: como dijo Itai Spector en el comentario, se mostrará aproximadamente 3.5 segundos, así que use este código:

    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();
Alireza Noorali
fuente
Creo que este texto desaparecerá después de 3.5 segundos
Itai Spector
@ItaiSpector: Verifique mi nuevo Código, por favor.
Alireza Noorali
1

No, y la mayoría / todos los hacks enumerados aquí ya no funcionan en Android 9. Pero hay una solución mucho mejor: si necesita un mensaje, use un cuadro de diálogo.

(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();
Al Ro
fuente
Aunque esta no es la respuesta que Hussein estaba buscando, ¡es una mejor opción que todos esos 'hacks'!
Danny EK van der Kolk
0

Un enfoque muy simple para crear un mensaje un poco más largo es el siguiente:

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

Tenga en cuenta que el ejemplo anterior elimina la opción LENGTH_SHORT para mantener el ejemplo simple.

Por lo general, no querrá usar un mensaje Toast para mostrar mensajes durante intervalos muy largos, ya que ese no es el propósito previsto de la clase Toast. Pero hay ocasiones en que la cantidad de texto que necesita mostrar puede llevar al usuario más de 3.5 segundos para leer, y en ese caso una pequeña extensión de tiempo (por ejemplo, a 6.5 segundos, como se muestra arriba) puede, en mi opinión, ser útil y consistente con el uso previsto.

Carl
fuente
0

Establece un brindis por un período específico en milisegundos:

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);
        }
    }
}
LEMUEL ADANE
fuente
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();
      }
Pa Palca
fuente
0

Después de fallar con todas las soluciones disponibles, finalmente tuve una solución alternativa usando recursión.

Código:

//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);
}
umair151
fuente
2
La mayoría de las soluciones a esta pregunta relacionadas con la llamada repetida a "show" para mantener las tostadas mostradas lo hacen con la misma instancia de tostadas, mientras que la suya en realidad está creando una nueva instancia de tostadas cada segundo y especificando que cada una debe mostrarse a lo LARGO duración (normalmente 3,5 segundos). Esto no solo es ineficiente porque sigue creando instancias de objetos adicionales, sino que también Android pone mensajes tostados en una cola para que se muestren uno tras otro durante la duración especificada. Entonces, si llamó a esto con una duración de 5, el mensaje en realidad se mostraría durante 17.5 segundos.
Niall
-1
Toast.makeText(this, "Text", Toast.LENGTH_LONG).show(); 
Toast.makeText(this, "Text", Toast.LENGTH_LONG).show();

Una solución muy simple a la pregunta. Dos o tres veces hará que Toast dure más. Es la única forma de evitarlo.

GoLfWRC
fuente
Aunque suena pirateo, ¡pero aprecio el pensamiento!
Sony Kadavan
por qué rechazó una solución similar mencionada por @Arturo usa el mismo truco con el bucle for
mal estado
Este enfoque funcionó para mí. Sería bueno saber de quienes votaron en contra por qué lo hicieron.
Christopher Mills
-8

Puede establecer el tiempo deseado en milisegundos en el Toast.makeText();método de esta manera:

//40 seconds
long mToastLength = 40*1000 
//this toast will be displayed for 40 seconds.
Toast.makeText(this, "Hello!!!!!", mToastLength).show(); 
aplicación Android
fuente
1
¡La respuesta es CORRECTA! La API se extendió en algún momento para permitir el uso de un valor diferente a LENGTH_LONG o LENGTH_SHORT. I
rts