Toast的基本原理其实就是将一个View添加到WindowManager中,让WindowManager来把View显示出来。(WindowManager可以将View显示在任何地方,任何Activity之上)
Toast的默认属性
// 对其方式为:水平居中,并在底部 mGravity = Gravtiy.CENTER_HORIZONTAL | Gravtiy.BOTTOM; mX = 0; mY =context.getResources().getDimensionPixelSize(com.android.internal.R.dimen.toast_y_offset); mHorizontalMargin = 0; mVerticalMargin = 0; 所以用Toast.makeText(getApplicationContext(), R.string.text, Toast.LENGTH_SHORT).show();生成的Toast总是处在底部水平居中的位置
在指定x, y处显示Toast
// 在(50, 100)处显示Toast Toast toast = Toast.makeText(getApplicationContext(), "toast use", Toast.LENGTH_SHORT); toast.setGravity(Gravity.TOP | Gravity.LEFT, 50, 100); toast.show(); // 如果使用Gravity.NO_GRAVITY,后面的x, y就是相对于屏幕的中心点的(估计android是默认这么处理的) Toast toast = Toast.makeText(getApplicationContext(), "toast use", Toast.LENGTH_SHORT); toast.setGravity(Gravity.NO_GRAVITY, 50, 100); toast.show(); // 用margin来控制toast的位置 Toast toast = Toast.makeText(getApplicationContext(), "toast use", Toast.LENGTH_SHORT); toast.setGravity(Gravity.LEFT | Gravity.TOP, 0, 0); // leftMargin, topMargin分别是容器width, height的%多少(这里是10%和20%) toast.setMargin(0.1F, 0.2F); toast.show();
指定View的Toast
// 布局xml:R.layout.toast < Button xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/message" android:layout_width="fill_parent" android:layout_height="wrap_content" /> Toast toast = new Toast(getApplicationContext()); toast.setView(LayoutInflater.from(getApplicationContext()).inflate(R.layout.toast, null)); toast.setText("toast use"); // Button是否fill_parent是由gravity控制的, xml中的不起任何作用 toast.setGravity(toast.getGravity() | Gravity.FILL_HORIZONTAL, toast.getXOffset(), toast.getYOffset()); toast.setDuration(Toast.LENGTH_SHORT); toast.show();
Toast部分源码
// Toast的构造器只设置了mY这个属性。mNextView, mDuration都没有设置(用makeText的话,这两个属性会设置) public Toast(Context context) { mContext = context; mTN = new TN(); mY = context.getResources().getDimensionPixelSize(com.android.internal.R.dimen.toast_y_offset); } // setText方法,需要将显示text的view的id设为@android:id/message,否则会抛RuntimeException public void setText(CharSequence s) { if (mNextView == null) { throw new RuntimeException("This Toast was not created with Toast.makeText()"); } TextView tv = (TextView) mNextView.findViewById(com.android.internal.R.id.message); if (tv == null) { throw new RuntimeException("This Toast was not created with Toast.makeText()"); } tv.setText(s); }
一直显示的Toast
实现原理是:在Toast隐藏之前,再show一个相同的Toast,来实现长显示的假象
private class ToastWrapper { private Toast mToast; private Handler mHandler; private Runnable mShowToast = new Runnable() { @Override public void run() { continueShow(); } }; private boolean mCancelled = true; public ToastWrapper(Context ctxt) { this(ctxt, new Handler()); } public ToastWrapper(Context ctxt, Handler handler) { mToast = Toast.makeText(ctxt, null, Toast.LENGTH_SHORT); mHandler = handler; } public Toast getToast() { return mToast; } public void showUntilCancel() { if (mCancelled) { mCancelled = false; mToast.setDuration(Toast.LENGTH_LONG); continueShow(); } } public void cancel() { mCancelled = true; mToast.cancel(); } private void continueShow() { if (mCancelled) { return; } mToast.show(); mHandler.postDelayed(mShowToast, 3000); } }
使用ToastWrapper
// 一直显示的toast toastWrapper = new ToastWrapper(getApplicationContext()); Toast toast = toastWrapper.getToast(); toast.setText("toast wrapper"); // ... Button button = new Button(getApplicationContext()); button.setText("一直显示toast"); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { toastWrapper.showUntilCancel(); } }); Button button = new Button(getApplicationContext()); button.setText("隐藏toast"); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { toastWrapper.cancel(); } }); // 一搬的toast Button button = new Button(getApplicationContext()); button.setText("一般的toast"); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast toast = toastWrapper.getToast(); toast.setDuration(Toast.LENGTH_SHORT); toast.show(); } });
glMatrixMode - 指定哪一个矩阵是当前矩阵 编辑本段参数 mode 指定哪一个矩阵堆栈是下一个矩阵操作的目标,可选值: GL_MODELVIEW、GL_PROJECTION、GL_TEXTURE. 说明 glMatrixMode设置当前矩阵模式: GL_MODELVIEW,对模型视景矩阵堆栈应用随后的矩阵操作. GL_PROJECTION,对投影矩阵应用随后的矩阵操作. GL_TEXTURE,对纹理矩阵堆栈应用随后的矩阵操作. 与glLoadIdentity()一同使用 glLoadIdentity():该函数的功能是重置当前指定的矩阵为单位矩阵。 在glLoadIdentity()之后我们为场景设置了透视图。glMatrixMode(GL_MODELVIEW)设置当前矩阵为模型视图矩阵,模型视图矩阵储存了有关物体的信息。 编辑本段glMatrixMode与gluPerspective函数的使用 GL_MODELVIEW 是模型矩阵 GL_PROJECTION 是投影矩阵。 gluPerspective的是创建一个投影矩阵并且与当前矩阵相乘,得到的矩阵设定为当前变换,但要先通过glMatrixMode设定成投影矩阵才会得到想要的投影矩阵变换。 例如: gluPerspective(45.0f,(GLfloat)cx/(GLfloat)cy,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); 可以出来结果,反之,换位置后; glMatrixMode(GL_MODELVIEW); gluPerspective(45.0f,(GLfloat)cx/(GLfloat)cy,0.1f,100.0f);
则,投影矩阵位置不正确.
android:windowSoftInputMode="stateHidden" 键盘隐藏