美文网首页控件和规范科技Android developer
你见过这样的Toast吗?——Android Toast自定义使

你见过这样的Toast吗?——Android Toast自定义使

作者: 简名 | 来源:发表于2016-08-12 15:30 被阅读23304次

    之前写过一篇没时间解释了,快使用Snackbar!——Android Snackbar花式使用指南。Toast的自定义使用原理与其类似。

    1.Toast源码分析

    老规矩,我们先去看Toast的源码。

    Toast有两种显示布局方式,一种最常见调用Toast.makeText(),看源码是这样写的

    public static Toast makeText(Context context, CharSequence text, @Duration int duration) {
    Toast result = new Toast(context);
    
    LayoutInflater inflate = (LayoutInflater)
    context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);
    TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message);
    tv.setText(text);
    
    result.mNextView = v;
    result.mDuration = duration;
    
    return result;
    }
    

    transient_notification这个布局文件代码是这样的

    <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根布局和message这个TextView。

    Toast的另外一种显示模式就是自定义布局显示。这个方法不调用Toast.makeText()方法,而是new一个Toast对象,然后调用setView()方法。当然自定义布局就不会加载transient_notification布局了。

    2.实现花式Toast

    先给大家看下我封装的工具类ToastUtil。

    import android.content.Context;
    import android.view.View;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    import android.widget.Toast;
    
    /**
     * Created by 赵晨璞 on 2016/8/11.
     */
    public class ToastUtil {
    
    private  Toast toast;
    private LinearLayout toastView;
    
    /**
     * 修改原布局的Toast
     */
    public ToastUtil() {
    
    }
    
    /**
     * 完全自定义布局Toast
     * @param context
     * @param view
     */
    public ToastUtil(Context context, View view,int duration){
        toast=new Toast(context);
        toast.setView(view);
        toast.setDuration(duration);
    }
    
    /**
     * 向Toast中添加自定义view
     * @param view
     * @param postion
     * @return
     */
    public  ToastUtil addView(View view,int postion) {
        toastView = (LinearLayout) toast.getView();
        toastView.addView(view, postion);
    
        return this;
    }
    
    /**
     * 设置Toast字体及背景颜色
     * @param messageColor
     * @param backgroundColor
     * @return
     */
    public ToastUtil setToastColor(int messageColor, int backgroundColor) {
        View view = toast.getView();
        if(view!=null){
           TextView message=((TextView) view.findViewById(android.R.id.message));
            message.setBackgroundColor(backgroundColor);
            message.setTextColor(messageColor);
        }
        return this;
    }
    
    /**
     * 设置Toast字体及背景
     * @param messageColor
     * @param background
     * @return
     */
    public ToastUtil setToastBackground(int messageColor, int background) {
        View view = toast.getView();
        if(view!=null){
            TextView message=((TextView) view.findViewById(android.R.id.message));
            message.setBackgroundResource(background);
            message.setTextColor(messageColor);
        }
        return this;
    }
    
    /**
     * 短时间显示Toast
     */
    public  ToastUtil Short(Context context, CharSequence message){
        if(toast==null||(toastView!=null&&toastView.getChildCount()>1)){
            toast= Toast.makeText(context, message, Toast.LENGTH_SHORT);
            toastView=null;
        }else{
            toast.setText(message);
            toast.setDuration(Toast.LENGTH_SHORT);
        }
        return this;
    }
    
    /**
     * 短时间显示Toast
     */
    public ToastUtil Short(Context context, int message) {
        if(toast==null||(toastView!=null&&toastView.getChildCount()>1)){
            toast= Toast.makeText(context, message, Toast.LENGTH_SHORT);
            toastView=null;
        }else{
            toast.setText(message);
            toast.setDuration(Toast.LENGTH_SHORT);
        }
      return this;
    }
    
    /**
     * 长时间显示Toast
     */
    public ToastUtil Long(Context context, CharSequence message){
        if(toast==null||(toastView!=null&&toastView.getChildCount()>1)){
            toast= Toast.makeText(context, message, Toast.LENGTH_LONG);
            toastView=null;
        }else{
            toast.setText(message);
            toast.setDuration(Toast.LENGTH_LONG);
        }
        return this;
    }
    
    /**
     * 长时间显示Toast
     *
     * @param context
     * @param message
     */
    public ToastUtil Long(Context context, int message) {
        if(toast==null||(toastView!=null&&toastView.getChildCount()>1)){
            toast= Toast.makeText(context, message, Toast.LENGTH_LONG);
            toastView=null;
        }else{
            toast.setText(message);
            toast.setDuration(Toast.LENGTH_LONG);
        }
        return this;
    }
    
    /**
     * 自定义显示Toast时间
     *
     * @param context
     * @param message
     * @param duration
     */
    public ToastUtil Indefinite(Context context, CharSequence message, int duration) {
        if(toast==null||(toastView!=null&&toastView.getChildCount()>1)){
            toast= Toast.makeText(context, message,duration);
            toastView=null;
        }else{
            toast.setText(message);
            toast.setDuration(duration);
        }
         return this;
    }
    
    /**
     * 自定义显示Toast时间
     *
     * @param context
     * @param message
     * @param duration
     */
    public ToastUtil Indefinite(Context context, int message, int duration) {
        if(toast==null||(toastView!=null&&toastView.getChildCount()>1)){
            toast= Toast.makeText(context, message,duration);
            toastView=null;
        }else{
            toast.setText(message);
            toast.setDuration(duration);
        }
        return this;
    }
    
    /**
     * 显示Toast
     * @return
     */
    public ToastUtil show (){
        toast.show();
    
        return this;
    }
    
    /**
     * 获取Toast
     * @return
     */
    public Toast getToast(){
        return toast;
    }
    }
    

    修改Toast背景色的使用法方法如下:

    ToastUtil toastUtil=new ToastUtil();
    toastUtil.Short(MainActivity.this,"自定义message字体、背景色").setToastColor(Color.WHITE, getResources().getColor(R.color.colorAccent)).show();
    
    修改Toast背景色

    方形的Toast看上去有些呆板,我自定义了一个名为toast_radius.xml的背景,代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <!-- 填充的颜色 -->
    <solid android:color="#ffc107" />
    
    <!-- android:radius 弧形的半径 -->
    <corners android:radius="20dip" />
    
    </shape>
    

    然后上面设置背景的代码改成:

    toastUtil.Short(MainActivity.this,"自定义message字体颜色和背景").setToastBackground(Color.WHITE,R.drawable.toast_radius).show();
    
    修改了背景的Toast

    虽然官方认为Toast和Snackbar都应该是短文本的形式,不能包含图标,但是个人感觉加上图标还是挺好玩的...

    向Toast中添加图标可以这样:

     ImageView toastImage = new ImageView(getApplicationContext());
     toastImage.setImageResource(R.mipmap.ic_launcher);
     toastUtil.Short(MainActivity.this,"向Toast添加了一个ImageView").setToastBackground(Color.WHITE,R.drawable.toast_radius).addView(toastImage,0).show();
    
    添加图标的Toast

    如果你想要Toast显示自定义的布局,可以这样:

     View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.image,null);
     new ToastUtil(MainActivity.this,view,Toast.LENGTH_SHORT).show();
    
    自定义布局Toast,我的布局文件中只有一个默认图标的ImageView

    大家都知道,连续触发Toast的show()方法的时候,Toast就会排着队连续展示,感觉上不太友好。所以我先判断了toast是否没被创建或者是否被添加了额外的view,如果是的话就重新生成一个toast对象;如果否的话就只修改message文字和显示时间。

    Toast布局修改,不排队显示

    我这个工具类不是完全体,大家再根据自己项目的具体需求进行修改。 []( ̄▽ ̄)*

    相关文章

      网友评论

      • Hframe:ToastUtil为什么不写成单例
      • 白帽子耗子:8.0 之后关闭通知权限连 Toast 都显示不出来,能加上兼容处理就更好了
        白帽子耗子:@做梦枯岛醒 可能是个别机型吧。我是华为Android8.0,EMUI系统
        做梦枯岛醒:@白帽子耗子 我的是Android9.0 MIUI系统,我把通知关了为啥还能显示,你说的是原生的嘛
      • AWeiLoveAndroid:楼主好人 学习了
      • 174232d9bdc9:如果用户关闭通知权限呢。我看你最后还是调用 系统 Toast 的 show 方法。
        Judy_li:是的,关闭通知权限,Toast都无法显示的
      • MonkiRayman:这是自定义toast吧?
      • 泽Sama:请问下设置了view为透明色后,toast显示时还是会闪现一下原始的灰色外框再变回透明,请问下如何避免
      • 贝贝ovo:学到了,建议把这个也写到文章里。http://www.jianshu.com/p/330a05963e64 更改Toast位置,
        Toast toast = Toast.makeText(this, "改变Toast位置", Toast.LENGTH_LONG);
        toast.setGravity(Gravity.CENTER,100,50);
        toast.show();
        这样感觉用Toast完全可以写成Snackbar
      • 沈凤德:显示时间自定义不好使
      • a5ff9c6191f1:371718330@qq.com
      • a5ff9c6191f1:请问一下源码是在哪里下载呀?求分享,谢了
        凌川江雪:@到处是狼 左手按ctrl,右手鼠标点击方法名或者类名
      • JellyCai:哎,就一定要放美女图片上去吗?
      • 2a5276452da4:可以自定义动画吗?
      • cyq7on:lz,我用你的util出来的效果没截图好看,左右的margin比你小多了,所以会有适配问题?
      • ElonYanJ:有适配问题吗
      • 火萌:棒
      • EitanLiu:够花的
      • Wing_Li:这个动画的背景真不错 :smile: :smile: :smile:
      • sendtion:真是强大的吐司
        简名:@sendtion 我更喜欢Snackbar ,之前的文章有介绍
        sendtion:@sendtion 不过现在流行Snakebar?
      • 98eac8a283ce:已经过时了
        简名:@斜川雨 我前面文章提到的Snackbar
        张贤同学:@总很有神叔 那么请问现在流行什么?
      • CokeNello:简直完美,很早就想改它了
      • c009b94342c6:你好,请问修改背景颜色后出现了四个黑角怎么弄? :confounded:
        CokeNello:@ibuer 设置Toast的view就可以了:view.setBackgroundColor(Color.TRANSPARENT);
        c009b94342c6:@简名 谢谢啦,已经好了
        简名:@ibuer 我这个是修改的message那个textview的背景,你试试修改toast根view的背景为透明。
      • 不爱思考的老鼠: :smile: 花式Toast 真不错
      • 4fb0ed2e1b29:这图片 gank干货来的吗
        简名:@JoshuaJan 对
      • 聪葱忙忘:花式使用Toast,强无敌!

      本文标题:你见过这样的Toast吗?——Android Toast自定义使

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