饿货!来块Toast尝尝吧!
~
***面包-吐司(Toast)***
</br>
上图只是假象中的Toast,而这篇文章我说需要讲解的Toast是这样的:
</br>
虽说这个Toast看起来并不诱人,但也值得我们咀嚼(研究)一番。
1.什么是Toast?
~
在第一次接触的时候我是这样认为的:Toast很简单嘛,就是在屏幕显示一段文字用来提示用户的。
直到后来老大叫我去修改下Toast样式,我才发现这货居然不是一个传统的View。
Toast虽说在android.widget包下但是他并不是一个传统的View,它并不是继承于View。实际上他是由Window直接承载的,真是一个高傲的家伙。在它的源码可以看出:
TN()
{ // XXX This should be changed to use a Dialog, with a Theme.Toast
// defined that sets up the layout params appropriately.
final WindowManager.LayoutParams params = mParams;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.format = PixelFormat.TRANSLUCENT;
params.windowAnimations = com.android.internal.R.style.Animation_Toast;
params.type = WindowManager.LayoutParams.TYPE_TOAST;
params.setTitle("Toast");
params.flags =
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON|
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
}
这里的flags告诉了我们几个重要的信息:
- Toast是一直显示在屏幕上的
- Toast是没有焦点的
- Toast是不能点击的
再结合源码中对Toast的定义
A toast is a view containing a quick little message for the user
我们就可以准确知道Toast是什么了:
Toast是为用户提供了轻量级信息的一个“View”,它没有焦点,也无法被点击
2.Toast的基本使用
~
既然知道了Toast是什么,现在我们就来看看它怎么用。
Toast.makeText(getApplicationContext(),"我是个不可以吃的Toast",Toast.LENGTH_SHORT).show();
- 第一个参数:上下文Context.
- 第二个参数:一段显示的文字,建议写在values下的strings.xml中,我这里是不标准的,这里是为了给大家一个错误示范(只是为了偷懒).如果你想问可以显示多少字,从源码中的Window参数可以得知:
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
所以基本可以显示整个屏幕。
- 第三个参数:显示的时长Toast.LENGTH_SHORT和Toast.LENGTH_LONG,只有这2种分别表示短时间(2s)和长时间(3.5s).
- 注意一定要show().
3.改变显示的位置
~
- 在改变之前我们先看看默认的位置
先看看Toast的构造参数,可以看出修改了显示的位置和Y轴的偏移量
public Toast(Context context)
{
mContext = context;
mTN = new TN();
mTN.mY = context.getResources().getDimensionPixelSize( com.android.internal.R.dimen.toast_y_offset);
mTN.mGravity = context.getResources().getInteger( com.android.internal.R.integer.config_toastDefaultGravity);
}
再进一步看看定义的值
<dimen name="toast_y_offset">64dip</dimen>
<!-- Default Gravity setting for the system Toast view. Equivalent to: Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM -->
<integer name="config_toastDefaultGravity">0x00000051</integer>
由此可以得出:Toast默认的显示是位于屏幕底部且水平居中,Y轴方向的偏移量为64dp
- 修改Toast显示位置方法
toast.setGravity(Gravity.CENTER,0,0);
- 第一个参数:显示的基本位置可以是全局居中,水平居中等等,可以自行尝试.
- 第二个参数:x轴方向的偏移量,单位是dp,正数向左偏移,负数向右偏移.
- 第三个参数:y轴方向的偏移量,单位是dp,正数向下偏移,负数向上偏移.
4.添加自定义View
~
- 添加自定义控件的方法
setView(View view)
- 示例
Toast toast=Toast.makeText(getApplicationContext(),"我是个不可以吃Toast",Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER,0,0);
ImageView imageView=new ImageView(MainActivity.this);
imageView.setImageResource(R.mipmap.ic_launcher);
toast.setView(imageView);
toast.show();
-
效果
device-2016-06-28-162223.png
这里的setView()是重新添加一个View所以之前的文字设置无效。
5.修改原生的Toast属性
~
- 其实Toast也是加载的一个布局,我们只要知道这个布局,并且修改其属性即可:
View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);
TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message);
- transient_notificatoin.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="?android:attr/toastFrameBackground">
<TextView
android:id="@android:id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_horizontal"
android:textAppearance="@style/TextAppearance.Toast"
android:textColor="@color/bright_foreground_dark"
android:shadowColor="#BB000000"
android:shadowRadius="2.75" />
</LinearLayout>
- 我们只要找到这个布局即可,还好Toast提供了一个方法
toast.getView()
- 核心方法以及代码(原地址:http://blog.csdn.net/caroline_wendy):
LinearLayout linearLayout= (LinearLayout) toast.getView();
linearLayout.setBackgroundColor(Color.parseColor("#00ffff"));
TextView textView= (TextView) linearLayout.getChildAt(0);
textView.setTextColor(Color.parseColor("#ff0000"));
-
效果:
修改原生Toast
6.Toast的坑
~
-
坑1:由于Toast是直接由窗口承载的,那么你的Activity或者应用都已经退出了,你的Toast还会在。
解决方法:在退出Activity或者应用的时候,取消Toast.toast.cancel();
-
坑2:只有当上一个Toast消失以后,下一个Toast才会出现
解决方法:建立一个工具类,只允许存在一个Toast实例。在《Android开发艺术探索》一书中有提到,Toast可以同时存在50个,这本书对Toast的原理进行了分析,有兴趣的可以去看看,强力推荐.private static Toast toast; public static Toast show(Context context, String text, int duration) { if (toast == null) { toast = Toast.makeText(context, text, duration); } toast.setText(text); toast.setDuration(duration); toast.setGravity(Gravity.BOTTOM, 0, 0); toast.show(); return toast; }
7.后记
~
由于篇幅太长就不贴出工具类了,之后再单独一篇贴出工具类的代码(还得优化下-。-)。
现在SnackBar的出现确实看起来挺炫酷,但是我觉得两者的使用场景还是有点区别,所以也不能完全代替Toast。