什么是Toast

Toast源码中这样说:Toast对于用户而言就是一个包含一个快捷的短信息的view;
英文:A toast is a view containing a quick little message for the user:

android开发者网站这么描述它的用处:Toast在一小块popup上提供关于一种操作的简单反馈。它只填充消息需要的空间(下面会将为什么)并且当前activity保持可见和互动,Toast过一会儿会自动消失。
英文:A toast provides simple feedback about an operation in a small popup. It only fills the amount of space required for the message and the current activity remains visible and interactive. Toasts automatically disappear after a timeout.

个人总结:Toast是一个包含短信息的view,为某种操作提供一种简单反馈;会自动消失;属于单向信息展示,用户不能与之进行交互。


如何使用Toast

  • 创建Toast
Context context = getApplicationContext();
CharSequence text = "Hello toast!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
  • 展示Toast
toast.show();
  • 自定义Toast
  • 自定义Toast位置
    标准的Toast出现接近屏幕的底部、水平居中。你可以通过setGravity(int, int, int)方法改变Toast的位置。该方法接受三个参数:a Gravity constant, an x-position offset, and a y-position offset.
    如果你想Toast在左上方出现你可以使用下面的代码
toast.setGravity(Gravity.TOP|Gravity.LEFT, 0, 0);
  • 创建一个定制的Toast view
    如果一个简单文本信息不能满足需求,你可以为Toast创建一个自定义的布局,为了创建一个自定义布局,需要定义一个layout,在xml文件中或者应用代码中,并将根视图对象传递给setview(View)方法。
    比如,你可以创建一个自定义布局(layout/custom_toast.xml):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/custom_toast_container"
          android:orientation="horizontal"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:padding="8dp"
          android:background="#DAAA"
          >
<ImageView android:src="@drawable/droid"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_marginRight="8dp"
           />
<TextView android:id="@+id/text"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:textColor="#FFF"
          />
</LinearLayout>

注意这个linearLayout的ID元素是custom_toast_container,你必须用这个ID和xml文件custom_toast去解析加载这个layout,就像如下代码一样:

LayoutInflater inflater = getLayoutInflater();
View layout = inflater.inflate(R.layout.custom_toast,
(ViewGroup) findViewById(R.id.custom_toast_container));
TextView text = (TextView) layout.findViewById(R.id.text);
text.setText("This is a custom toast");
Toast toast = new Toast(getApplicationContext());
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.setDuration(Toast.LENGTH_LONG);
toast.setView(layout);
toast.show();

第一步就是通过getLayoutInflater()获取到LayoutInflater,然后从xml中解析加载这个布局使用inflate(int, ViewGroup)方法。第一个参数是layout的资源ID,第二参数是根view,你可以使用解析过后的布局去找到更多在这个布局上的view对象。所以现在为textview和Imageview获取和定义内容。最终,使用Toast(Context) 创建一个Toast,并且设置一些属性,比如gravity 和 duration。然后通过调用setView(View)设置Toast的布局;现在你就可以使用show方法来显示自定义的Toast。

注意:除非你想使用setView(View)进行自定义Toast布局,否则不要使用Toast的构造方法;如果你没有自定义的布局,你必须使用
makeText(Context, int, int) 方法进行Toast的创建。


源码解析

Toast相关类
  • Toast类图如下:

ios oc toast怎么写 toast ipo_自定义

Toast通过NotificationManagerService、TN(Toast-Notification)进行实现交互;TN为Toast的内部类。

关键的变量有:
Toast:mNextView、sService
TN:mView、mNextView、mHandler
NotificationService:ToastRecord、mToastQueue

mNextView(Toast):文章一开始,我们说Toast是一个View,说的就是它。
sService:获取NotificationService的一个Binder接口,可以使用NotificationService对Toast进行相关处理,比如show,hide、cancle等。
mView(TN):当前TN中正在处理的View;
mNextView(TN):TN将要处理的View,对应于Toast mNextView;由Toast的show方法中进行初始化。

/**
     * Show the view for the specified duration.
     */
    public void show() {
        if (mNextView == null) {
            throw new RuntimeException("setView must have been called");
        }

        INotificationManager service = getService();
        String pkg = mContext.getOpPackageName();
        TN tn = mTN;
        tn.mNextView = mNextView;// 将Toast的布局传递给TN,交由TN进行相关显示的逻辑处理

        try {
            service.enqueueToast(pkg, tn, mDuration);// 由NotificationService统一管理Toast
        } catch (RemoteException e) {
            // Empty
        }
    }

mHandler(TN):由于NotificationService处于System进程,当回调给TN时,通过该Handler将操作发送到Toast线程中执行。
ToastRecord:Notification中记录Toast的数据结构:包含pid、pkg、callback、duration、token;
ToastQueue:Toast队列,队列中的元素为ToastRecord;管理系统中所有的Toast。

关键方法:
Toast:Toast(Context context)、show()、cancel()、setView()、makeText();
TN:TN()、show、hide、cancle、handleShow、handleHide;
Notification:enqueueToast、cancelToast;

Toast(Context context)、makeText():构建Toast的两个方法,详细用法见上面Toast使用章节。
show(Toast):Toast为应用提供的显示接口,主要做两件事,将Toast的布局view传递给TN;通过调用enqueueToast将Toast相关信息交给NotificationService进行处理;
cancel:Toast为应用提供的取消接口。
setView:设置Toast的布局 ,自定义Toast布局时使用。

show、hide(TN):实现ITransientNotification.Stub的接口的方法,对应NotificationService中callback。
cancle、handleShow、handleHide(TN):TN 类中实际处理Toast view取消、显示、隐藏的逻辑实现,后续章节详细讲解策略。

enqueueToast、cancelToast(Notification):Notificatino管理Toast的两个方法,入队(显示)、取消(出队),后续章节详细讲解策略;

Toast时序图:

下一章跟随代码详细讲解一个Toast的显示过程。见Toast解析《二》


小结

归根结底,为用户显示视图都是一个个view,Toast就是对View的一个封装,并设计出相应的管理逻辑策略;可以说系统组件就是自定义view,然后定义相应的控制逻辑。