我有几个SeekBar
and onSeekBarProgressStop()
,我想显示一条Toast
消息。
但是,如果SeekBar
我快速执行操作,那么 UI 线程会以某种方式阻塞并且Toast
消息会等待直到 UI 线程空闲。
Toast
现在我担心的是如果Toast
消息已经显示,则避免出现新消息。或者它们是我们检查 UI 线程当前是否空闲的任何条件,然后我将显示该Toast
消息。
我通过使用runOnUIThread()
和创建新的Handler
.
我有几个SeekBar
and onSeekBarProgressStop()
,我想显示一条Toast
消息。
但是,如果SeekBar
我快速执行操作,那么 UI 线程会以某种方式阻塞并且Toast
消息会等待直到 UI 线程空闲。
Toast
现在我担心的是如果Toast
消息已经显示,则避免出现新消息。或者它们是我们检查 UI 线程当前是否空闲的任何条件,然后我将显示该Toast
消息。
我通过使用runOnUIThread()
和创建新的Handler
.
我已经尝试了很多方法来做到这一点。起初我尝试使用cancel()
,这对我没有影响(另见这个答案)。
我setDuration(n)
也不会去任何地方。记录getDuration()
结果表明它的值为 0(如果makeText()
's 参数是Toast.LENGTH_SHORT
)或 1(如果makeText()
's 参数是Toast.LENGTH_LONG
)。
最后,我尝试检查 toast 的 view 是否isShown()
。当然,如果没有显示 toast 则不是,但更重要的是,在这种情况下,它会返回一个致命错误。所以我需要尝试捕捉错误。现在,isShown()
如果显示吐司,则返回 true。利用isShown()
我想出的方法:
/**
* <strong>public void showAToast (String st)</strong></br>
* this little method displays a toast on the screen.</br>
* it checks if a toast is currently visible</br>
* if so </br>
* ... it "sets" the new text</br>
* else</br>
* ... it "makes" the new text</br>
* and "shows" either or
* @param st the string to be toasted
*/
public void showAToast (String st){ //"Toast toast" is declared in the class
try{ toast.getView().isShown(); // true if visible
toast.setText(st);
} catch (Exception e) { // invisible if exception
toast = Toast.makeText(theContext, st, toastDuration);
}
toast.show(); //finally display it
}
以下是最受欢迎的答案的替代解决方案,没有 try/catch。
public void showAToast (String message){
if (mToast != null) {
mToast.cancel();
}
mToast = Toast.makeText(this, message, Toast.LENGTH_SHORT);
mToast.show();
}
开箱即用的干净解决方案。在您的活动中定义:
private Toast toast;
/**
* Use this to prevent multiple Toasts from spamming the UI for a long time.
*/
public void showToast(CharSequence text, int duration)
{
if (toast == null)
toast = Toast.makeText(this, text, duration);
else
toast.setText(text);
toast.show();
}
public void showToast(int resId, int duration)
{
showToast(getResources().getText(resId), duration);
}
跟踪您上次展示 toast 的时间,如果它在某个时间间隔内,则重新展示它。
public class RepeatSafeToast {
private static final int DURATION = 4000;
private static final Map<Object, Long> lastShown = new HashMap<Object, Long>();
private static boolean isRecent(Object obj) {
Long last = lastShown.get(obj);
if (last == null) {
return false;
}
long now = System.currentTimeMillis();
if (last + DURATION < now) {
return false;
}
return true;
}
public static synchronized void show(Context context, int resId) {
if (isRecent(resId)) {
return;
}
Toast.makeText(context, resId, Toast.LENGTH_LONG).show();
lastShown.put(resId, System.currentTimeMillis());
}
public static synchronized void show(Context context, String msg) {
if (isRecent(msg)) {
return;
}
Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
lastShown.put(msg, System.currentTimeMillis());
}
}
进而,
RepeatSafeToast.show(this, "Hello, toast.");
RepeatSafeToast.show(this, "Hello, toast."); // won't be shown
RepeatSafeToast.show(this, "Hello, toast."); // won't be shown
RepeatSafeToast.show(this, "Hello, toast."); // won't be shown
这并不完美,因为 和 的长度LENGTH_SHORT
未定义LENGTH_LONG
,但在实践中效果很好。与其他解决方案相比,它的优势在于您不需要保留 Toast 对象,并且调用语法保持简洁。
来自上述线程的增强功能,仅在同一短信不可见时才会显示吐司:
public void showSingleToast(){
try{
if(!toast.getView().isShown()) {
toast.show();
}
} catch (Exception exception) {
exception.printStackTrace();
Log.d(TAG,"Toast Exception is "+exception.getLocalizedMessage());
toast = Toast.makeText(this.getActivity(), getContext().getString(R.string.no_search_result_fou`enter code here`nd), Toast.LENGTH_SHORT);
toast.show();
}
}
对于我的情况,如果显示当前的 toast,我需要取消它并显示另一个。
这是为了解决当用户在服务仍在加载或不可用时请求服务的情况,我需要展示一个 toast(如果请求的服务不同,我可能会有所不同)。否则,toast 将继续按顺序显示,并且需要很长时间才能自动隐藏它们。
所以基本上我保存了正在创建的 toast 的实例,下面的代码是如何安全地取消它
synchronized public void cancel() {
if(toast == null) {
Log.d(TAG, "cancel: toast is null (occurs first time only)" );
return;
}
final View view = toast.getView();
if(view == null){
Log.d(TAG, "cancel: view is null");
return;
}
if (view.isShown()) {
toast.cancel();
}else{
Log.d(TAG, "cancel: view is already dismissed");
}
}
为了使用它,我现在不用担心取消,如下所示:
if (toastSingleton != null ) {
toastSingleton.cancel();
toastSingleton.showToast(messageText);
}else{
Log.e(TAG, "setMessageText: toastSingleton is null");
}
showToast取决于您如何实现它,因为我需要为我的 toast 自定义外观。
我的解决方案是:
public class Utils {
public static Toast showToast(Context context, Toast toast, String str) {
if (toast != null)
toast.cancel();
Toast t = Toast.makeText(context, str, Toast.LENGTH_SHORT);
t.show();
return t;
}
}
并且调用者应该为此方法的参数有一个 Toast 成员,或者
class EasyToast {
Toast toast;
Context context;
public EasyToast(Context context) {
this.context = context;
}
public Toast show(String str) {
if (toast != null)
toast.cancel();
Toast t = Toast.makeText(context, str, Toast.LENGTH_SHORT);
t.show();
return t;
}
}
有一个这样的助手类。
适合停止堆叠,例如点击驱动吐司。基于@Addi 的回答。
public Toast toast = null;
//....
public void favsDisplay(MenuItem item)
{
if(toast == null) // first time around
{
Context context = getApplicationContext();
CharSequence text = "Some text...";
int duration = Toast.LENGTH_SHORT;
toast = Toast.makeText(context, text, duration);
}
try
{
if(toast.getView().isShown() == false) // if false not showing anymore, then show it
toast.show();
}
catch (Exception e)
{}
}
检查是否在屏幕上显示 toast 消息,无论它是否显示。用于显示 toast 消息创建一个单独的类。并使用此类在检查 toast 消息的可见性后显示 toast 消息的方法。使用这段代码:
public class AppToast {
private static Toast toast;
public static void showToast(Context context, String message) {
try {
if (!toast.getView().isShown()) {
toast=Toast.makeText(context, message, Toast.LENGTH_SHORT);
toast.show();
}
} catch (Exception ex) {
toast=Toast.makeText(context,message,Toast.LENGTH_SHORT);
toast.show();
}
}
}
我希望这个解决方案能帮助你。
谢谢
添加了计时器以在 2 秒后取出吐司。
private Toast toast;
public void showToast(String text){
try {
toast.getView().isShown();
toast.setText(text);
}catch (Exception e){
toast = Toast.makeText(mContext, text, Toast.LENGTH_SHORT);
}
if(toast.getView().isShown()){
new Timer().schedule(new TimerTask() {
@Override
public void run() {
toast.cancel();
}
}, 2000);
}else{
toast.show();
}
}
showToast("Please wait");