饿货!来块Toast尝尝吧!

作者: 积木Blocks | 来源:发表于2016-06-28 17:33 被阅读984次

    ~


    ***面包-吐司(Toast)***

    </br>
    上图只是假象中的Toast,而这篇文章我说需要讲解的Toast是这样的:
    </br>

    ***Android-Toast***

    虽说这个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_SHORTToast.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()
    
    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。

    相关文章

      网友评论

      本文标题:饿货!来块Toast尝尝吧!

      本文链接:https://www.haomeiwen.com/subject/rmaodttx.html