Android ToastUtil

Android ToastUtil

自定义的一套ToastUtil,包括SuperToast、ToastStyle、ToastHandler、ToastUtil四个类。

/**
 * toast显示,用来代替系统toast和snackbar。相对于系统控件更加灵活,比如可以设置任意时间等。<br/>
 * <p>
 * 如果要系统层级显示toast设置参数{@link ToastStyle#LEVEL_SYSTEM},如果是在App页面内显示即页面退出toast也消失,设置参数{@link
 * ToastStyle#LEVEL_ACTIVITY}。<br/>
 * <p>
 * {@link #create()}必须调用,且在设置参数之后{@link #show()}方法之前。<br/>
 * <p>
 * 显示时间默认3000毫秒。
 *
 * @author 己师
 */

public class SuperToast {

    private Context mContext;

    private OnDismissListener mDismissListener;

    private ToastStyle mToastStyle;

    private View mView;

    private TextView mTvMessage;

    private ViewGroup mViewGroup;

    public SuperToast(Context context) {
        mContext = context;
        mToastStyle = new ToastStyle();
    }

    public OnDismissListener getDismissListener() {
        return mDismissListener;
    }

    @PriorityLevel
    public int getPriorityLevel() {
        return mToastStyle.priorityLevel;
    }

    public Animator getShowAnimator() {
        return mToastStyle.showAnimator;
    }

    public Animator getHideAnimator() {
        return mToastStyle.hideAnimator;
    }

    public Context getContext() {
        return mContext;
    }

    public int getDisplayLevel() {
        return mToastStyle.displayLevel;
    }

    public int getDuration() {
        return mToastStyle.duration;
    }

    public long getTimestamp() {
        return mToastStyle.timestamp;
    }

    public View getView() {
        return mView;
    }

    public ViewGroup getViewGroup() {
        if (mViewGroup == null) {
            if (!(mContext instanceof Activity)) {
                throw new IllegalArgumentException("使用LEVEL_ACTIVITY层级的toast Context需要是Activity");
            }
            mViewGroup = ((Activity) mContext).findViewById(android.R.id.content);
        }
        return mViewGroup;
    }

    public LayoutParams getWindowParams() {
        WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
        layoutParams.height = mToastStyle.height;
        layoutParams.width = mToastStyle.width;
        if (mToastStyle.canTouch) {
            layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                    WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
                    WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
                    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
                    WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR |
                    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
        } else {
            layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
        }
        layoutParams.format = PixelFormat.TRANSLUCENT;
        layoutParams.type = WindowManager.LayoutParams.TYPE_TOAST;
        layoutParams.windowAnimations = mToastStyle.animationId;
        layoutParams.gravity = mToastStyle.gravity;
        layoutParams.x = mToastStyle.xOffset;
        layoutParams.y = mToastStyle.yOffset;
        return layoutParams;
    }

    /**
     * 自定义显示样式
     */
    public SuperToast setToastStyle(ToastStyle toastStyle) {
        mToastStyle = toastStyle;
        return this;
    }

    /**
     * 自定义显示的View
     *
     * @param viewId 自定义view的layout
     */
    public SuperToast setView(@LayoutRes int viewId) {
        mToastStyle.layoutId = viewId;
        return this;
    }

    /**
     * 自定义显示的View
     *
     * @param view 自定义view
     */
    public SuperToast setView(View view) {
        mView = view;
        return this;
    }

    /**
     * LEVEL_ACTIVITY显示层级,设置toast依附的ViewGroup,默认是根ViewGroup
     */
    public SuperToast setViewGroup(ViewGroup viewGroup) {
        mViewGroup = viewGroup;
        return this;
    }

    /**
     * 设置显示的文本
     */
    public SuperToast setMessage(String message) {
        mToastStyle.message = message;
        return this;
    }

    /**
     * 设置显示的文本
     *
     * @param message 资源id
     */
    public SuperToast setMessage(@StringRes int message) {
        mToastStyle.message = mContext.getString(message);
        return this;
    }

    /**
     * 设置显示文本的颜色
     *
     * @param color 色值
     */
    public SuperToast setTextColor(@ColorInt int color) {
        mToastStyle.messageTextColor = color;
        return this;
    }

    /**
     * 设置显示文本的大小
     *
     * @param textSize px值
     */
    public SuperToast setTextSize(int textSize) {
        mToastStyle.messageTextSize = textSize;
        return this;
    }

    /**
     * 设置文本旁边的icon
     *
     * @param iconRes icon资源id
     */
    public SuperToast setIconRes(@DrawableRes int iconRes) {
        mToastStyle.messageIconRes = iconRes;
        return this;
    }

    /**
     * 设置icon在文字显示的位置
     *
     * @param position 上下左右
     */
    public SuperToast setIconPosition(@IconPosition int position) {
        mToastStyle.messageIconPosition = position;
        return this;
    }

    /**
     * 设置背景色
     *
     * @param background 色值
     */
    public SuperToast setBackground(@ColorInt int background) {
        mToastStyle.backgroundColor = background;
        return this;
    }

    /**
     * 设置背景图片
     *
     * @param background 图片
     */
    public SuperToast setBackground(Drawable background) {
        mToastStyle.background = background;
        return this;
    }


    /**
     * 设置toast的圆角度数
     */
    public SuperToast setRadius(int radius) {
        mToastStyle.radius = radius;
        return this;
    }

    /**
     * 系统层级显示toast设置参数{@link ToastStyle#LEVEL_SYSTEM};<br/>
     * App页面内显示即页面退出toast也消失,设置参数{@link ToastStyle#LEVEL_ACTIVITY}。
     *
     * @param displayLevel 显示层级
     */
    public SuperToast setDisplayLevel(@DisplayLevel int displayLevel) {
        mToastStyle.displayLevel = displayLevel;
        return this;
    }

    /**
     * 设置toast是否可操作。默认不可操作。在LEVEL_ACTIVITY层级一直可以操作。
     *
     * @param canTouch true 可以操作
     */
    public SuperToast setCanTouch(boolean canTouch) {
        mToastStyle.canTouch = canTouch;
        return this;
    }


    /**
     * 设置toast显示时间,小于0表示一直显示。默认三秒
     *
     * @param duration 毫秒值
     */
    public SuperToast setDuration(int duration) {
        mToastStyle.duration = duration;
        return this;
    }

    /**
     * 设置toast显示的优先级,
     *
     * @param priorityLevel 高({@link ToastStyle#PRIORITY_HIGH}),中({@link ToastStyle#PRIORITY_MEDIUM}),低({@link
     *                      ToastStyle#PRIORITY_LOW})
     */
    public SuperToast setPriorityLevel(@PriorityLevel int priorityLevel) {
        mToastStyle.priorityLevel = priorityLevel;
        return this;
    }

    /**
     * 设置toast显示动画,该动画只在{@link ToastStyle#LEVEL_ACTIVITY}层级有效果
     */
    public SuperToast setShowAnimator(Animator showAnimator) {
        mToastStyle.showAnimator = showAnimator;
        return this;
    }

    /**
     * 设置toast显示动画,该动画只在{@link ToastStyle#LEVEL_ACTIVITY}层级有效果
     *
     * @param showAnimator 动画id
     */
    public SuperToast setShowAnimator(@AnimatorRes int showAnimator) {
        mToastStyle.showAnimator = AnimatorInflater.loadAnimator(mContext, showAnimator);
        return this;
    }

    /**
     * 设置toast隐藏动画,该动画只在{@link ToastStyle#LEVEL_ACTIVITY}层级有效果
     */
    public SuperToast setHideAnimator(Animator hideAnimator) {
        mToastStyle.hideAnimator = hideAnimator;
        return this;
    }

    /**
     * 设置toast隐藏动画,该动画只在{@link ToastStyle#LEVEL_ACTIVITY}层级有效果
     *
     * @param hideAnimator 动画id
     */
    public SuperToast setHideAnimator(@AnimatorRes int hideAnimator) {
        mToastStyle.hideAnimator = AnimatorInflater.loadAnimator(mContext, hideAnimator);
        return this;
    }

    /**
     * 用于{@link ToastStyle#LEVEL_SYSTEM}层级的toast的显示隐藏动画,且只能用系统动画资源,默认效果{@link android.R.style#Animation_Toast}
     *
     * @param animId 系统动画id
     */
    public SuperToast setAnimations(int animId) {
        mToastStyle.animationId = animId;
        return this;
    }

    /**
     * 设置toast的显示位置
     */
    public SuperToast setGravity(@GravityStyle int gravity) {
        mToastStyle.gravity = gravity;
        return this;
    }

    /**
     * 设置水平方向偏移量,左右的margin值
     *
     * @param xOffset 偏移量值px
     */
    public SuperToast setXOffset(int xOffset) {
        mToastStyle.xOffset = xOffset;
        return this;
    }

    /**
     * 设置竖直方向偏移量,上下的margin值
     *
     * @param yOffset 偏移量值px
     */
    public SuperToast setYOffset(int yOffset) {
        mToastStyle.yOffset = yOffset;
        return this;
    }

    /**
     * 设置宽 px,如果要用Match和Wrap 请使用{@link android.view.ViewGroup.LayoutParams#MATCH_PARENT } 或 {@link
     * ViewGroup.LayoutParams#WRAP_CONTENT}
     */
    public SuperToast setWidth(int width) {
        mToastStyle.width = width;
        return this;
    }

    /**
     * 设置高 px;如果要用Match和Wrap 请使用{@link ViewGroup.LayoutParams#MATCH_PARENT } 或 {@link
     * ViewGroup.LayoutParams#WRAP_CONTENT}
     */
    public SuperToast setHeight(int height) {
        mToastStyle.height = height;
        return this;
    }

    /**
     * 是否是一直显示
     */
    public boolean isIndeterminate() {
        return mToastStyle.duration < 0;
    }

    /**
     * 判断是不是横竖屏转换,如果是,就不执行toast动画,否则就执行。
     */
    protected boolean isFromOrientationChange() {
        return false;
    }

    /**
     * 判断当前toast是否正在显示中
     */
    public boolean isShowing() {
        return mView != null && mView.isShown();
    }

    /**
     * 创建toast显示的View,默认是系统toast的布局
     */
    protected View onCreateView() {
        if (mView != null) {
            return mView;
        }
        View view;
        if (mToastStyle.displayLevel == ToastStyle.LEVEL_ACTIVITY) {
            if (!(mContext instanceof Activity)) {
                throw new IllegalArgumentException("使用LEVEL_ACTIVITY层级的toast Context需要是Activity");
            }
            mViewGroup = ((Activity) mContext).findViewById(android.R.id.content);
            view = LayoutInflater.from(mContext)
                    .inflate(mToastStyle.layoutId, mViewGroup, false);
        } else {
            view = LayoutInflater.from(mContext)
                    .inflate(mToastStyle.layoutId, null);
        }
        //如果用的自定义的布局就不存在。
        try {
            mTvMessage = view.findViewById(R.id.tv_toast_message);
        } catch (NotFoundException e) {
            mTvMessage = null;
        }
        return view;
    }

    public SuperToast show() {
        ToastHandler.getInstance().add(this);
        sendAccessibilityEvent();
        return this;
    }

    /**
     * 创建布局,一定要在参数设置之后,show之前调用。
     */
    public SuperToast create() {
        mView = onCreateView();
        if (mView.getBackground() == null) {
            mView.setBackground(getBackground());
        }
        //api21以上加阴影效果。
        if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
            mView.setElevation(3F);
        }
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(mToastStyle.width, mToastStyle.height);
        layoutParams.width = mToastStyle.width;
        layoutParams.height = mToastStyle.height;
        layoutParams.bottomMargin = mToastStyle.yOffset;
        layoutParams.topMargin = mToastStyle.yOffset;
        layoutParams.leftMargin = mToastStyle.xOffset;
        layoutParams.rightMargin = mToastStyle.xOffset;
        layoutParams.gravity = mToastStyle.gravity;
        mView.setLayoutParams(layoutParams);
        mView.setMinimumWidth(ResUtil.getDimen(R.dimen.x342));
        mToastStyle.timestamp = System.currentTimeMillis();

        //不等于空说明用的是默认布局。
        if (mTvMessage != null) {
            mTvMessage.setText(mToastStyle.message);
            mTvMessage.setTextColor(mToastStyle.messageTextColor);
            mTvMessage.setTextSize(TypedValue.COMPLEX_UNIT_PX, mToastStyle.messageTextSize);
            if (mToastStyle.messageIconRes > 0) {
                switch (mToastStyle.messageIconPosition) {
                    case ToastStyle.ICON_POSITION_LEFT:
                        mTvMessage.setCompoundDrawablesWithIntrinsicBounds(mToastStyle.messageIconRes, 0, 0, 0);
                        break;
                    case ToastStyle.ICON_POSITION_TOP:
                        mTvMessage.setCompoundDrawablesWithIntrinsicBounds(0, mToastStyle.messageIconRes, 0, 0);
                        break;
                    case ToastStyle.ICON_POSITION_RIGHT:
                        mTvMessage.setCompoundDrawablesWithIntrinsicBounds(0, 0, mToastStyle.messageIconRes, 0);
                        break;
                    case ToastStyle.ICON_POSITION_BOTTOM:
                        mTvMessage.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, mToastStyle.messageIconRes);
                        break;
                    default:
                }
            }
        }
        //好像不起作用
        if (!mToastStyle.canTouch) {
            mView.setOnTouchListener(new OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    return true;
                }
            });
        }
        return this;
    }

    /**
     * 取消正在显示的toast并清空消息队列。
     */
    public void cancelAllToasts() {
        ToastHandler.getInstance().cancelAllToasts();
    }

    /**
     * toast的背景
     */
    private Drawable getBackground() {
        if (mToastStyle.background == null) {
            GradientDrawable gradientDrawable = new GradientDrawable();
            gradientDrawable.setColor(mToastStyle.backgroundColor);
            gradientDrawable.setCornerRadius(mToastStyle.radius);
            return gradientDrawable;
        } else {
            return mToastStyle.background;
        }
    }

    /**
     * 发送辅助功能事件。主要是了为了辅助残疾人士更好使用设备。
     */
    private void sendAccessibilityEvent() {
        AccessibilityManager am = (AccessibilityManager) mContext.getApplicationContext()
                .getSystemService(Context.ACCESSIBILITY_SERVICE);
        if (am == null || !am.isEnabled()) {
            return;
        }
        final AccessibilityEvent accessibilityEvent = AccessibilityEvent
                .obtain(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
        accessibilityEvent.setClassName(mView.getClass().getName());
        accessibilityEvent.setPackageName(mContext.getPackageName());
        mView.dispatchPopulateAccessibilityEvent(accessibilityEvent);
        am.sendAccessibilityEvent(accessibilityEvent);
    }

    /**
     * 手动让toast的消失。
     */
    public void dismiss() {
        ToastHandler.getInstance().removeToast(this);
    }

    public SuperToast setOnDismissListener(OnDismissListener dismissListener) {
        mDismissListener = dismissListener;
        return this;
    }

    /**
     * toast消失时的回调
     */
    public interface OnDismissListener {

        /**
         * toast消失时会回调该方法。
         */
        void onDismiss(View view);
    }


}

/**
 * toast的样式
 * @author 己师
 */
 class ToastStyle {

    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag = true, value = {PRIORITY_HIGH, PRIORITY_MEDIUM, PRIORITY_LOW})
    public @interface PriorityLevel {}

    public static final int PRIORITY_HIGH = 1;

    public static final int PRIORITY_MEDIUM = 2;

    public static final int PRIORITY_LOW = 3;

    @SuppressLint("RtlHardcoded")
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({Gravity.BOTTOM, Gravity.CENTER, Gravity.CENTER_HORIZONTAL,
            Gravity.CENTER_VERTICAL, Gravity.END, Gravity.LEFT, Gravity.NO_GRAVITY,
            Gravity.RIGHT, Gravity.START, Gravity.TOP})
    public @interface GravityStyle {}

    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag = true, value = {LEVEL_SYSTEM, LEVEL_ACTIVITY})
    public @interface DisplayLevel{}

    public static final int LEVEL_SYSTEM = 10;

    public static final int LEVEL_ACTIVITY = 20;


    @Retention(RetentionPolicy.SOURCE)
    @IntDef({ICON_POSITION_LEFT, ICON_POSITION_RIGHT, ICON_POSITION_BOTTOM, ICON_POSITION_TOP})
    public @interface IconPosition {

    }

    public static final int ICON_POSITION_LEFT = 1;

    public static final int ICON_POSITION_RIGHT = 2;

    public static final int ICON_POSITION_BOTTOM = 3;

    public static final int ICON_POSITION_TOP = 4;

    public static final int DURATION_SHORT = 1000;

    public static final int DURATION_LONG = 3000;

    public static final int DURATION_INDEFINITE = -1;

    /**
     * 自定义view布局id
     */
    @LayoutRes
    public int layoutId;

    public int style;

    /**
     * toast的显示层级,{@link #LEVEL_ACTIVITY} Activity层级,只显示在当前页面。{@link #LEVEL_SYSTEM} 系统层级,显示在所有页面最上层
     */
    public int displayLevel;

    /**
     * toast显示时间
     */
    public int duration;

    /**
     * toast的高度
     */
    public int height;

    /**
     * toast的宽度
     */
    public int width;

    /**
     * toast的显示层级是{@link #LEVEL_SYSTEM} 只能用系统的动画资源,如{@link android.R.style#Animation_Toast}
     */
    public int animationId;

    /**
     * toast显示动画
     */
    public Animator showAnimator;

    /**
     * toast隐藏动画
     */
    public Animator hideAnimator;

    /**
     * toast显示位置
     */
    public int gravity;

    /**
     * 水平方向偏移量,左右的margin值
     */
    public int xOffset;

    /**
     * 竖直方法偏移量,上下的margin值
     */
    public int yOffset;

    /**
     * toast的时间戳
     */
    public long timestamp;

    /**
     * toast显示的文字
     */
    public String message;

    /**
     * toast文字颜色,色值
     */
    public int messageTextColor;

    /**
     * toast文字大小,px
     */
    public float messageTextSize;

    /**
     * toast文字旁边的icon资源id
     */
    public int messageIconRes;

    /**
     * icon在toast文字的位置,上下左右
     */
    public int messageIconPosition;

    /**
     * toast背景色, 色值
     */
    public int backgroundColor;

    /**
     * toast背景图, 图片
     */
    public Drawable background;

    /**
     * toast的圆角度数
     */
    public float radius;

    /**
     * toast的优先级,高中低,默认是中
     */
    public int priorityLevel;

    /**
     * 设置toast是否可以操作。
     */
    public boolean canTouch;

    public ToastStyle() {
        layoutId = R.layout.layout_normal_toast;

        width = LayoutParams.WRAP_CONTENT;
        height = ResUtil.getDimen(R.dimen.y90);
        animationId = android.R.style.Animation_Toast;
        duration = DURATION_LONG;
        gravity = Gravity.CENTER;
        yOffset = -ResUtil.getDimen(R.dimen.y136);
        radius = ResUtil.getDimen(R.dimen.m4);
        backgroundColor = ResUtil.getColor(R.color.information_main_color);
        priorityLevel = PRIORITY_MEDIUM;
        messageTextColor = ResUtil.getColor(R.color.text_color_1);
        messageTextSize = ResUtil.getDimen(R.dimen.text_size1);
        messageIconPosition = ICON_POSITION_LEFT;

        ObjectAnimator objectAnimator1 = new ObjectAnimator();
        objectAnimator1.setPropertyName("alpha");
        objectAnimator1.setDuration(250).setFloatValues(0F,1F);
        showAnimator = objectAnimator1;
        ObjectAnimator objectAnimator2 = new ObjectAnimator();
        objectAnimator2.setPropertyName("alpha");
        objectAnimator2.setDuration(250).setFloatValues(1F,0F);
        hideAnimator = objectAnimator2;

        canTouch = false;
        displayLevel = LEVEL_SYSTEM;
    }
}

/**
 * toast消息队列
 * @author 己师
 */
class ToastHandler extends Handler {

    private static ToastHandler mToastHandler;

    private final PriorityQueue<SuperToast> mToastPriorityQueue;

    private ToastHandler() {
        mToastPriorityQueue = new PriorityQueue<>(10, new ToastComparator());
    }

    static ToastHandler getInstance() {
        if (mToastHandler == null) {
            synchronized (ToastHandler.class) {
                if (mToastHandler == null) {
                    mToastHandler = new ToastHandler();
                }
            }
        }
        return mToastHandler;
    }

    /**
     * 添加一个toast对象到信息队列
     */
    void add(SuperToast superToast) {
        mToastPriorityQueue.add(superToast);
        showNextToast();
    }

    /**
     * 在当前队列显示下一条toast,如果有toast正在显示就不执行任何操作。当当前正在显示的toast消失后会调用该方法
     */
    private void showNextToast() {
        if (mToastPriorityQueue.isEmpty()) {
            return;
        }
        //从队列最顶部取toast
        final SuperToast superToast = mToastPriorityQueue.peek();
        if (!superToast.isShowing()) {
            final Message message = obtainMessage(Messages.DISPLAY_TOAST);
            message.obj = superToast;
            sendMessage(message);
        }
    }

    @Override
    public void handleMessage(Message msg) {
        final SuperToast superToast = (SuperToast) msg.obj;
        switch (msg.what) {
            case Messages.SHOW_NEXT:
                showNextToast();
                break;
            case Messages.DISPLAY_TOAST:
                displayToast(superToast);
                break;
            case Messages.REMOVE_TOAST:
                removeToast(superToast);
                break;
            default:
                super.handleMessage(msg);
                break;
        }
    }

    /**
     * 该方法是显示toast的具体方法。
     * <p></p>
     * 既可以使用WindowManager来显示,这样会显示在全局和系统toast一样;
     * 也可以使用外部提供的ViewGroup,这样只会显示在当前页面,和系统的snackbar一样,页面关闭toast也消失。
     */
    private void displayToast(SuperToast superToast) {
        if (superToast.isShowing()) {
            return;
        }
        long animDuration = 0;
        //如果toast显示层级是系统级别就使用WindowManager,层级和系统toast一样。
        if (superToast.getDisplayLevel() == ToastStyle.LEVEL_SYSTEM) {
            WindowManager wm = (WindowManager) superToast.getContext().getApplicationContext()
                    .getSystemService(Context.WINDOW_SERVICE);
            if (wm != null) {
                View view = superToast.getView();
                view.setMinimumWidth(ResUtil.getDimen(R.dimen.x342));
                wm.addView(view, superToast.getWindowParams());
            }

            //toast显示层级是activity级别,就使用外部提供的ViewGroup,层级和系统snackbar一样。
        } else {
            if (superToast.getViewGroup() == null) {
                Log.e("ToastHandler", "displayToast: ViewGroup不能为空");
                return;
            }
            try {
                superToast.getViewGroup().addView(superToast.getView());
                if (superToast.getShowAnimator() != null) {
                    Animator showAnimator = superToast.getShowAnimator();
                    animDuration = showAnimator.getDuration();
                    showAnimator.setTarget(superToast.getView());
                    showAnimator.start();
                }
            }catch (IllegalStateException e){
                e.printStackTrace();
            }

        }
        //如果不是一直显示就延迟取消
        if (!superToast.isIndeterminate()) {
            sendDelayedMessage(superToast, Messages.REMOVE_TOAST, superToast.getDuration() + animDuration);
        }
    }

    /**
     * 延迟发送消息
     */
    private void sendDelayedMessage(SuperToast superToast, int what, long delay) {
        Message message = obtainMessage(what);
        message.obj = superToast;
        sendMessageDelayed(message, delay);
    }

    /**
     * 移除正在显示的toast。该方法会检索队列,如果队列中还有消息就会显示下一条。
     */
    void removeToast(final SuperToast superToast) {
        //移除队列第一条信息
        mToastPriorityQueue.poll();
        if (superToast.getDisplayLevel() == ToastStyle.LEVEL_SYSTEM) {
            WindowManager wm = (WindowManager) superToast.getContext().getApplicationContext()
                    .getSystemService(Context.WINDOW_SERVICE);
            if (wm != null) {
                View view = superToast.getView();
                if (view != null && ViewCompat.isAttachedToWindow(view)){
                    wm.removeView(view);
                }
            }
            if (superToast.getDismissListener() != null) {
                superToast.getDismissListener().onDismiss(superToast.getView());
            }
            //彻底隐藏有个时间,所以等到彻底隐藏在显示下一条
            sendDelayedMessage(superToast, Messages.SHOW_NEXT, 250);
        } else {
            //如果改toast已经消失了,就不要再尝试让它消失。
            if (!superToast.isShowing()) {
                mToastPriorityQueue.remove(superToast);
                return;
            }
            if (superToast.getHideAnimator() != null) {
                Animator hideAnimator = superToast.getHideAnimator();
                hideAnimator.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        dismiss(superToast);
                    }
                });
                hideAnimator.setTarget(superToast.getView());
                hideAnimator.start();
            }else {
                dismiss(superToast);
            }

        }

    }

    private void dismiss(SuperToast superToast) {
        if (superToast.getDismissListener() != null) {
            superToast.getDismissListener().onDismiss(superToast.getView());
        }
        superToast.getViewGroup().removeView(superToast.getView());
        showNextToast();
    }
    public void cancelAllToasts() {
        removeMessages(Messages.SHOW_NEXT);
        removeMessages(Messages.DISPLAY_TOAST);
        removeMessages(Messages.REMOVE_TOAST);
        for (SuperToast toast : mToastPriorityQueue) {
            if (toast.isShowing()){
                if (toast.getDisplayLevel() == ToastStyle.LEVEL_ACTIVITY){
                    try {
                        toast.getViewGroup().removeView(toast.getView());
                    }catch (NullPointerException | IllegalStateException e){
                        e.printStackTrace();
                    }
                }else {
                    WindowManager wm = (WindowManager) toast.getContext().getApplicationContext()
                            .getSystemService(Context.WINDOW_SERVICE);
                    try {
                        wm.removeView(toast.getView());
                    }catch (NullPointerException | IllegalStateException e){
                        e.printStackTrace();
                    }
                }
            }
        }
        mToastPriorityQueue.clear();
    }

    /**
     * 消息类型
     */
    private static final class Messages {

        /**
         * 显示当前toast
         */
        private static final int DISPLAY_TOAST = 101;

        /**
         * 显示下一条
         */
        private static final int SHOW_NEXT = 102;

        /**
         * 取消
         */
        private static final int REMOVE_TOAST = 103;
    }

    /**
     * toast消息队列比较器,根据优先级排序。优先级一样就更加时间,先来后到顺序。
     */
    private static class ToastComparator implements Comparator<SuperToast> {

        @Override
        public int compare(SuperToast o1, SuperToast o2) {
            if (o1.isShowing()) {
                return -1;
            }
            if (o1.getPriorityLevel() < o2.getPriorityLevel()) {
                return -1;
            } else if (o1.getPriorityLevel() > o2.getPriorityLevel()) {
                return 1;
            } else {
                return o1.getTimestamp() <= o2.getTimestamp() ? -1 : 1;
            }
        }
    }
}
/**
 * toast工具类
 * @author 己师
 */

public class ToastUtil {

    private static SuperToast mToast;

    /**
     * 普通toast,就是默认样式
     */
    public static void showNormal(Context context, String msg) {
        SuperToast toast = new SuperToast(context)
                .setMessage(msg)
                .create()
                .show();

    }

    /**
     * 普通toast,就是默认样式
     */
    public static void showNormal(Context context, @StringRes int resId) {
        showNormal(context, ResUtil.getString(resId));
    }


    /**
     * 只显示当前的toast,取消所有正在显示或等待显示的toast
     */
    public static void showOnly(Context context, String msg) {
        SuperToast toast = new SuperToast(context);
        toast.cancelAllToasts();
        toast.setMessage(msg)
                .setDuration(ToastStyle.DURATION_LONG)
                .create()
                .show();
    }

    public static void showOnly(Context context, @StringRes int resId) {
        showOnly(context, ResUtil.getString(resId));
    }

    /**
     * 在当前页面显示toast。显示前会取消所有正在显示或等待显示的toast
     *
     * @param context 必须是activity
     */
    public static void showOnActivity(Context context, String msg) {
        SuperToast toast = new SuperToast(context);
        toast.cancelAllToasts();
        toast.setMessage(msg)
                .setDuration(ToastStyle.DURATION_LONG)
                .setDisplayLevel(ToastStyle.LEVEL_ACTIVITY)
                .create().show();
    }

    /**
     * 在当前页面显示toast。显示前会取消所有正在显示或等待显示的toast
     *
     * @param context 必须是activity
     */
    public static void showOnActivity(Context context, int resId) {
        showOnly(context, ResUtil.getString(resId));
    }


    public static void showInfo(Context context, String msg) {
        //目前所有的toast的显示都一样
        showOnly(context, msg);
    }

    public static void showInfo(Context context, int resId) {
        //目前所有的toast的显示都一样
        showOnly(context, ResUtil.getString(resId));
    }

    public static void showError(Context context, String msg) {
        //目前所有的toast的显示都一样
        showOnly(context, msg);
    }

    public static void showError(Context context, int resId) {
        //目前所有的toast的显示都一样
        showOnly(context, ResUtil.getString(resId));
    }

    /**
     * 持久显示。只在当前activity里显示。退出页面就会消失
     */
    public static void showIndefinite(Context context, String msg) {
        if (mToast != null) {
            mToast.dismiss();
        }
        mToast = new SuperToast(context)
                .setMessage(msg)
                .setDisplayLevel(ToastStyle.LEVEL_ACTIVITY)
                .setRadius(80)
                .setDuration(ToastStyle.DURATION_INDEFINITE)
                .create()
                .show();
    }

    /**
     * 持久显示。只在当前activity里显示。退出页面就会消失
     */
    public static void showIndefinite(Context context, int resId) {
        if (mToast != null) {
            mToast.dismiss();
        }
        mToast = new SuperToast(context)
                .setMessage(resId)
                .setDisplayLevel(ToastStyle.LEVEL_ACTIVITY)
                .setRadius(80)
                .setDuration(ToastStyle.DURATION_INDEFINITE)
                .create()
                .show();
    }

    public static void dismiss() {
        if (mToast != null) {
            mToast.dismiss();
            mToast = null;
        }
    }


    /**
     * 持久显示。只在当前activity里显示。退出页面就会消失
     */
    public static void showScene(Context context, View view) {
        if (mToast != null) {
            mToast.dismiss();
        }
        mToast = new SuperToast(context)
                .setCanTouch(true)
                .setView(view)
                .setWidth(ResUtil.getDimen(R.dimen.x1000))
                .setDisplayLevel(ToastStyle.LEVEL_SYSTEM)
                .setGravity(Gravity.TOP)
                .setXOffset(0)
                .setYOffset(0)
                .setRadius(80)
                .setDuration(-1)
                .setHeight(ViewGroup.LayoutParams.WRAP_CONTENT)
                .create()
                .show();
    }

}
使用方法
    ToastUtil.showOnly(context, getString(R.string.un_subscribe_failed_str));
    ToastUtil.showError(context, R.string.no_net_work_str);
    ToastUtil.showInfo(getApplicationContext(), R.string.network_has_linked);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值