全局Toast和Snackbar

在项目中遇到,图片下载的方法封装在imageUtils类中,下载要用Toast到提醒。如果在activity中可以用runOnUiThreadHandler来显示提醒,现在不是在activity,又不想在imageUtils中用Handler。所以想到如果有个全局的Toast就方便多了。

先上效果图:

Toast.gif

全局Toast:
1. 支持默认格式,自上向下布局为ImageView,TextView,TextView,三个控件可以自由组合显示或隐藏
2. 支持Top,Center,Bottom的位置显示
3. 支持多样的显示格式,可以传入自定义的layout的View
4. 共用一个Toast对象,防止多次Toast重叠并显示时间累加,该控件近保留最后一次的设置和显示。
5. 最好在自定义的Application中new该Toast,Activity,Fragment,Adapter中都可以直接调用。

自定义Toast代码如下, 用静态内部类Builder设置Toast的样式:

public class FlexibleToast {

    public static final int GRAVITY_BOTTOM = 0;
    public static final int GRAVITY_CENTER = 1;
    public static final int GRAVITY_TOP = 2;
    public static final int TOAST_SHORT = 0;
    public static final int TOAST_LONG = 1;

    private Context mContext;

    private Toast flexibleToast;

    public void toastShow(Builder builder) {
        if (flexibleToast == null) {
            flexibleToast = new Toast(mContext);
        }
        // toast position
        if (builder.mGravity == GRAVITY_CENTER) {
            flexibleToast.setGravity(Gravity.CENTER | Gravity.CENTER_VERTICAL, 0, 0);
        } else if (builder.mGravity == GRAVITY_TOP) {
            flexibleToast.setGravity(Gravity.TOP | Gravity.CENTER_VERTICAL, 0, Tools.dip2px(mContext, 20));
        } else {
            flexibleToast.setGravity(Gravity.BOTTOM | Gravity.CENTER_VERTICAL, 0, Tools.dip2px(mContext, 20));
        }
        if (builder.mDuration == TOAST_LONG) {
            flexibleToast.setDuration(Toast.LENGTH_LONG);
        } else {
            flexibleToast.setDuration(Toast.LENGTH_SHORT);
        }
        if (builder.hasCustomerView && builder.mCustomerView != null) {
            flexibleToast.setView(builder.mCustomerView);
        } else {
            flexibleToast.setView(builder.mDefaultView);
        }
        flexibleToast.show();
    }

    public FlexibleToast(Context context) {
        mContext = context;
    }

    /**
     * 控制Toast的显示样式
     */
    public static class Builder {
        private View mDefaultView;
        private View mCustomerView;
        private ImageView mIvImage;
        private TextView mTvFirst;
        private TextView mTvSecond;

        private View dividerFirst;
        private View dividerSecond;

        private int mDuration = Toast.LENGTH_SHORT;// 0 short, 1 long
        private int mGravity = 0;
        private boolean hasCustomerView = false; // 是否使用自定义layout


        /**
         * 使用全局的ApplicationContext进行初始化
         * @param context
         */
        public Builder(Context context) {
            mDefaultView = LayoutInflater.from(context).inflate(R.layout.layout_toast_flexible, null);
            mIvImage = (ImageView) mDefaultView.findViewById(R.id.iv_img);
            mTvFirst = (TextView) mDefaultView.findViewById(R.id.tv_text_first);
            mTvSecond = (TextView) mDefaultView.findViewById(R.id.tv_text_second);
            dividerFirst = mDefaultView.findViewById(R.id.divider_first);
            dividerSecond = mDefaultView.findViewById(R.id.divider_second);
        }

        public Builder setImageResource(int resId) {
            this.mIvImage.setImageResource(resId);
            this.mIvImage.setVisibility(View.VISIBLE);
            this.dividerFirst.setVisibility(View.VISIBLE);
            return this;
        }

        public Builder setFirstText(String firstText) {
            this.mTvFirst.setText(firstText);
            this.mTvFirst.setVisibility(View.VISIBLE);
            this.dividerSecond.setVisibility(View.VISIBLE);
            return this;
        }

        public Builder setSecondText(String secondText) {
            this.mTvSecond.setText(secondText);
            this.mTvSecond.setVisibility(View.VISIBLE);
            return this;
        }

        public Builder setDuration(int duration) {
            this.mDuration = duration;
            return this;
        }

        public Builder setGravity(int gravity) {
            this.mGravity = gravity;
            return this;
        }

        /**
         * 为Toast指定自定义的layout,此时上面对ImageView和TextView的设置失效。
         * @param customerView
         * @return
         */
        public Builder setCustomerView(View customerView) {
            this.mCustomerView = customerView;
            this.hasCustomerView = true;
            return this;
        }
    }

}

在Application中初始化自定义Toast:
创建自定义ToastflexibleToast = new FlexibleToast(this),然后提供方法toastShowByBuilder()供调用传builder设置样式

public class BaseApp extends Application {
    // 全局的 handler 对象
    private final Handler appHandler = new Handler();
    // 全局的 Toast 对象
    private FlexibleToast flexibleToast;
    private static BaseApp instance;
    public static void setInstance(BaseApp instance) {
        BaseApp.instance = instance;
    }
    public static BaseApp getInstance() {
        return instance;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        setInstance(this);
        flexibleToast = new FlexibleToast(this);
        Log.i("TAG","主线程"+Thread.currentThread().getId());

    }
    public Handler getAppHandler() {
        return appHandler;
    }
    public void toastShowByBuilder(final FlexibleToast.Builder builder) {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            getAppHandler().post(new Runnable() {
                @Override
                public void run() {
                    flexibleToast.toastShow(builder);
                }
            });
        } else {
            flexibleToast.toastShow(builder);
        }
    }
}

下面分别列出Toast在屏幕中间、子线程、自定义显示的用法:

设置显示位置在屏幕中间:

FlexibleToast.Builder builder = new FlexibleToast.Builder(MainActivity.this)
.setGravity(FlexibleToast.GRAVITY_CENTER)
.setFirstText("中间").setSecondText("提醒");
BaseApp.getInstance().toastShowByBuilder(builder);

在子线程显示:

   new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Log.i("TAG","子线程");
                        FlexibleToast.Builder builder = new FlexibleToast.Builder(MainActivity.this)
                                .setGravity(FlexibleToast.GRAVITY_BOTTOM)
                                .setFirstText("底部").setSecondText("提醒");
                        BaseApp.getInstance().toastShowByBuilder(builder);
                    }
                }).start();

自定义样式:

final View customview= LayoutInflater
                .from(this)
                .inflate(R.layout.item,null,false);

 FlexibleToast.Builder builder = new FlexibleToast.Builder(MainActivity.this)
                        .setGravity(FlexibleToast.GRAVITY_BOTTOM)
                        .setCustomerView(customview);
                BaseApp.getInstance().toastShowByBuilder(builder);

git上源代码地址,欢迎指出错误哈!

SnackBar是 Android Support Library 22.2.0 里面新增提供的一个控件。SnackBar默认从屏幕底部弹出,像Toast一样会自动消失,当然也可以手动划出屏幕消失。Toast是不能交互的,而如果需要,SnackBar默认是可以添加一个点击事件的。效果如下:

snackbar.gif

普通snackbar代码如下:
snckbar可以设置回调setCallback(new Snackbar.Callback())显示和取消分别处理,不知道snackbar的用法,请点击
还在用Toast?试试Snackbar!

 Snackbar snackbar = Snackbar.make(button3,"normalSnackbar", LENGTH_LONG).setActionTextColor(getResources().getColor(R.color.white))
                    /*    .setCallback(new Snackbar.Callback() {
                    @Override
                    public void onDismissed(Snackbar snackbar, int event) {
                        super.onDismissed(snackbar, event);
                        FlexibleToast.Builder builder = new FlexibleToast.Builder(MainActivity.this)
                        .setGravity(FlexibleToast.GRAVITY_CENTER)
                        .setFirstText("回调dismiss");
                        BaseApp.getInstance().toastShowByBuilder(builder);
                    }

                    @Override
                    public void onShown(Snackbar snackbar) {
                        super.onShown(snackbar);
                        FlexibleToast.Builder builder = new FlexibleToast.Builder(MainActivity.this)
                        .setGravity(FlexibleToast.GRAVITY_CENTER).setFirstText("回调show");
                        BaseApp.getInstance().toastShowByBuilder(builder);
                    }
                })*/
                        .setAction("点击", new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        FlexibleToast.Builder builder = new FlexibleToast.Builder(MainActivity.this)
                      .setGravity(FlexibleToast.GRAVITY_CENTER).setFirstText("中间toast");
                        BaseApp.getInstance().toastShowByBuilder(builder);
                    }
                });
                snackbar.show();
         

自定义snackbar代码如下:

Snackbar snackbar = Snackbar.make(findViewById(R.id.button4),"自定义",Snackbar.LENGTH_LONG);
                View view = snackbar.getView();
                ViewGroup.LayoutParams Params = view.getLayoutParams();
                view.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
                CoordinatorLayout.LayoutParams layoutParams = new CoordinatorLayout.LayoutParams(Params.width,Params.height);
                layoutParams.gravity = Gravity.TOP;
//                TODO 为什么设置居中没反应
//                layoutParams.gravity = Gravity.CENTER;为什么设置居中没反应

                view.setLayoutParams(layoutParams);
                view.setBackgroundColor(getResources().getColor(R.color.colorPrimary));


//                view.setAnimation();
                ImageView imageView = new ImageView(MainActivity.this);
                imageView.setLayoutParams(new ViewGroup.LayoutParams(100,100));
                imageView.setImageDrawable(getResources().getDrawable(R.drawable.lufei));
                Snackbar.SnackbarLayout snackbarLayout = (Snackbar.SnackbarLayout) view;
                snackbarLayout.setOrientation(LinearLayout.HORIZONTAL);
                snackbarLayout.addView(imageView);
                snackbar.setAction("点击", new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        FlexibleToast.Builder builder = new FlexibleToast.Builder(MainActivity.this).setGravity(FlexibleToast.GRAVITY_CENTER).setFirstText("自定义的snackbar");
                        BaseApp.getInstance().toastShowByBuilder(builder);
                    }
                }).show();

git上源代码地址,欢迎指出错误哈!
想要设置snackbar剧中显示layoutParams.gravity = Gravity.CENTER;居然没有效果,不知道哪里出错了,有哪个兄弟看到了能指出,不胜感激!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容