今天在学习同事写的代码的时候,发现一个很有意思的东西,可以在Android 设备的任意位置(指的是空间上的任意位置)弹出来 Toast。
首先在layout 目录下新建一个布局文件 custom_toast.xml,里面按照下面写:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_ct"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="默认"/>
</LinearLayout>
然后就是工具类:
import android.content.Context;
import android.content.res.Resources;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class ToastUtils {
private static ToastUtils mInstance = null;
private long time;
public static ToastUtils getInstance() {
if (null == mInstance) {
synchronized (ToastUtils.class) {
if (null == mInstance) {
mInstance = new ToastUtils();
}
}
}
return mInstance;
}
public void showBottomToast(Context context, String content) {
if (System.currentTimeMillis() - time > 1000 * 3 ) {
Toast toast = Toast.makeText(context,content, Toast.LENGTH_LONG);
View view = LayoutInflater.from(context).inflate(R.layout.custom_toast, null);
TextView tv_ct = (TextView) view.findViewById(R.id.tv_ct);
tv_ct.setText(content);
toast.setView(view);
//toast.setGravity(Gravity.BOTTOM, 0, dp2px(50));
toast.setGravity(Gravity.CENTER, 0, dp2px(50));
toast.setDuration(Toast.LENGTH_SHORT);
toast.show();
time= System.currentTimeMillis();
}
}
static int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
Resources.getSystem().getDisplayMetrics());
}
}
然后在代码中这样使用:
ToastUtils.getInstance().showBottomToast(this, getResources().getString(R.string.app_name));
注意:
1.本文记录的是在Android 设备的任意位置(指的是屏幕空间上的任意位置)弹出来 Toast,不是在任意线程弹出Toast。
2.Toast 之所以在子线程弹Toast 的时候报错(基于Android 8.1.0):
java.lang.RuntimeException: Can't toast on a thread that has not called Looper.prepare()
是因为在调用 Toast.makeText()方法的时候,会创建一个 TN 对象,而在创建这个TN 对象的时候需要使用到当前线程的 Looper 实例!因此,必须在有 Looper 的线程里调用,如在 UI 线程(通过调用runOnUiThread 切换到UI线程)中调用,或者你造一个HandlerThread,然后绑定Handler 去 post。
另外,Toast 的 show()函数本身对 Context 是啥没有要求。
3.如果想在子线程中弹出 Toast的话,可以参考一下 这篇博客。