トーストに setDuration() を使用する場合、カスタムの長さまたは少なくともそれより長いものを設定することは可能Toast.LENGTH_LONG
ですか?
27 に答える
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
との値は 0LENGTH_SHORT
とLENGTH_LONG
1 です。これは、実際の期間ではなくフラグとして扱われることを意味するため、期間をこれらの値以外に設定することはできないと思います。
ユーザーへのメッセージをより長く表示したい場合は、Status Bar Notificationを検討してください。ステータス バーの通知は、関連性がなくなったときにプログラムでキャンセルできます。
あなたは試してみたいかもしれません:
for (int i=0; i < 2; i++)
{
Toast.makeText(this, "blah", Toast.LENGTH_LONG).show();
}
時間を2倍にします。2の代わりに3を指定すると、時間が3倍になります。
を持続させたい場合は、呼び出しを繰り返し (1 秒ごとに行う必要があります)Toast
ことで回避できることがわかりました。が既に表示されている場合、呼び出しによって何も壊れることはありませんが、画面に留まる時間が更新されます。Timer
toast.show()
show()
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);
}
}
}
これを行うためのヘルパー クラスをコーディングしました。コードは 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);
3.5 秒のLONG_DELAYトースト表示と2 秒のSHORT_DELAYトースト表示。
Toast は内部で INotificationManager を使用し、Toast.show() が呼び出されるたびに enqueueToast メソッドを呼び出します。
SHORT_DELAY を指定して show() を 2 回呼び出すと、同じトーストが再びキューに入れられます。4 秒間表示されます(2 秒 + 2 秒)。
同様に、LONG_DELAY を指定して show() を 2 回呼び出すと、同じトーストが再びキューに入れられます。7 秒間表示されます(3.5 秒 + 3.5 秒)
私は少し遅れていることを知っていますが、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);
私は答えがかなり遅いことを知っています..私はまったく同じ問題を抱えていて、 toast のAndroidのソースコードを調べた後、ベアボーン Toast の独自のバージョンを実装することにしました。
基本的に、新しい Window manager を作成し、ハンドラーを使用して目的の期間ウィンドウを表示および非表示にする必要があります
//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;
レイアウトの初期化後、独自の hide メソッドと show メソッドを使用できます
public void handleShow() {
mWindowManager.addView(mLayout, mParams);
}
public void handleHide() {
if (mLayout != null) {
if (mLayout.getParent() != null) {
mWindowManager.removeView(mLayout);
}
mLayout = null;
}
これで、handleShow() と handleHide() を呼び出す 2 つの実行可能なスレッドを追加するだけで、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);
}
これは手早く汚い実装でした.. パフォーマンスは考慮されていません。
上記のコードを使用して作成したカスタム 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();
}
}
長いトーストが必要な場合は、実用的な代替手段がありますが、ユーザーが [OK] ボタンをクリックしてトーストを消す必要があります。次のように 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();
メッセージが長い場合、ユーザーがメッセージを読むのにどれくらいかかるかわからない可能性があるため、ユーザーに [OK] ボタンをクリックして続行するよう要求することをお勧めします。私の場合、ユーザーがヘルプ アイコンをクリックしたときにこの手法を使用します。
他の人が述べたように、Android Toasts は LENGTH_LONG または LENGTH_SHORT のいずれかです。これを回避する方法はなく、投稿された「ハック」に従うべきではありません。
トーストの目的は、「重要ではない」情報を表示することであり、メッセージの持続時間が特定のしきい値を超えると、メッセージが長引くため、文脈からかけ離れたものになる可能性があります。ストック トーストが変更されて LENGTH_LONG よりも長く表示できるようになった場合、トースト ビューはアプリの ViewGroup ではなく WindowManager に追加されるため、アプリケーションのプロセスが終了するまでメッセージが画面に残ります。これがハードコードされている理由だと思います。
トースト スタイルのメッセージを 3 秒半より長く表示する必要がある場合は、Activity のコンテンツに関連付けられるビューを作成することをお勧めします。これにより、ユーザーがアプリケーションを終了するとメッセージが消えます。私のSuperToastsライブラリは、この問題と他の多くの問題を扱っています。自由に使用してください! SuperActivityToastsの使用に関心がある可能性が最も高いでしょう。
SuperToastを使用するだけで、どんな状況でもエレガントなトーストを作ることができます。トーストをカラフルに。フォントの色とサイズを編集します。それがあなたにとって一つになることを願っています。
いいえ、ここにリストされているハックのほとんど/すべては、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();
非常に柔軟な Toast ライブラリである Crouton を使用します。
トーストのように使用できます。
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;
}
トースト用に膨らませるCustome Layout。
<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>
カスタムの背景とビューを使用したトーストは、私にとってはうまくいきました。nexus 7 タブレットでテストしたところ、ループ中にフェードイン フェードアウト アニメーションがないことに気付きました。実装は次のとおりです。
public static void customToast(Context context, String message, int duration) {
for (int i = 0; i < duration; i++) {
Toast toast = new Toast(context);
toast.setDuration(Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.toast_layout, null);
TextView textViewToast = (TextView) view
.findViewById(R.id.textViewToast);
textViewToast.setText(message);
toast.setView(view);
toast.show();
}
}
上記のコードで使用されているカスタム テキストビューは次のとおりです。
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/textViewToast"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/fragment_background"
android:padding="8dp"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@color/blue" />
@drawable/fragment_background は、kitkat バージョンのようにトーストの角を丸くしています。ファイルに他のビューも追加できます。ライブアプリにこれを実装することを計画しているため、改善のための変更とコメントをお寄せください。
将来のある時点までカウントダウンをスケジュールし、途中で間隔を置いて定期的に通知します。テキスト フィールドに 30 秒のカウントダウンを表示する例:
新しい CountDownTimer(30000, 1000) { public void onTick(long millisUntilFinished) { mTextField.setText("残り秒数: " + millisUntilFinished / 1000); } public void onFinish() { mTextField.setText("完了!"); } }。始める();
このテキストは 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();
少し長いメッセージを作成するための非常に簡単な方法は次のとおりです。
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 が役立つ可能性があります。意図された使用法と一致しています。
トーストをミリ秒単位の特定の期間に設定します。
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);
}
}
}
Toast.makeText(this, "Text", Toast.LENGTH_LONG).show();
Toast.makeText(this, "Text", Toast.LENGTH_LONG).show();
質問に対する非常に簡単な解決策。2 倍または 3 倍にすると、Toast が長持ちします。それが唯一の方法です。