自定义Toast 样式

Posted by ijays on May 10, 2017

概述

前段时间接到一个需求,希望能够定制化Android Toast 的样式,于是稍微研究了下,并记录成文。

其实Github 上已经有了现成的很漂亮的第三方库,但是这样又要引入不少代码,稍显有些重,那到底Android 原生支不支持自定义Toast 样式呢?

原理

答案是肯定的。首先从Toast 的使用说起,我们一般都是makeText 这个方法来使用Toast,那么就从这个方法入手。

Toast.makeText(context, message, Toast.LENGTH_LONG).show();
  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;
    }

从这个方法中可以看到,这里首先是实例化了一个Toast 对象,然后inflate 一个布局,其子View 中包含一个TextView,我们的text 最后就是显示在这个TextView 上。看到这里,就应该可以想到接下来我们应该怎么做了,刚好屏幕往上滑看到了setView 这个方法,这不就是上面代码最后设置View 的方法么,那么接下来的事情就变得很简单了。

   /**
     * Set the view to show.
     * @see #getView
     */
    public void setView(View view) {
        mNextView = view;
    }

简单实现

public class ToastUtil {
    private Toast mToast;
    private Context mContext;

    /**
     * 修改原布局的Toast
     */
    public ToastUtil(Context context) {
        mContext = context;
        mToast = new Toast(context);
        View view = View.inflate(context, R.layout.toast_layout, null);
        mToast.setView(view);

    }

    /**
     * @param messageColor    文字的颜色
     * @param backgroundColor 背景的颜色
     * @return 
     */
    public ToastUtil setToastColor(int messageColor, int backgroundColor) {
        View view = mToast.getView();
        if (view != null) {
            TextView message = ((TextView) view.findViewById(R.id.message));
            view.setBackgroundColor(backgroundColor);
            message.setTextColor(messageColor);
        }
        return this;
    }
    

    public ToastUtil shortTime() {
        if (mToast == null) {
            mToast = new Toast(mContext);
        } else {
            mToast.setDuration(Toast.LENGTH_SHORT);
        }
        return this;
    }


    /**
     * 长时间显示Toast
     */
    public ToastUtil longTime() {
        if (mToast == null) {
            mToast = new Toast(mContext);
        } else {
            mToast.setDuration(Toast.LENGTH_LONG);
        }
        return this;
    }


    public ToastUtil setMessage(String message) {
        View view = mToast.getView();
        TextView textView = (TextView) view.findViewById(R.id.message);
        textView.setText(message);
        return this;
    }

    public ToastUtil setMessage(@StringRes int message) {
        View view = mToast.getView();
        TextView textView = (TextView) view.findViewById(R.id.message);
        textView.setText(mContext.getString(message));
        return this;
    }


    public ToastUtil show() {
        mToast.show();
        return this;
    }

    /**
     * 获取Toast
     *
     * @return
     */
    public Toast getToast() {
        return mToast;
    }
}

上面的代码在构造函数中给Toast 设置了一个自定义的layout,其实如果单纯只是修改Toast 的背景或者文字颜色的话,可以直接使用默认的layout,但是在实际使用中发现某些设置上会将边距吃掉,仅仅只有文字,因此使用自定义的layout。

修改后的效果如下: