Material Design学习之 Snackbars(详细分析,Toast的加强版)

转载请注明出处:王亟亟的大牛之路

昨天把Material Design Button部分的内容分析完了,不知道大家理解了他的实现没有。如果没看的话,可以看下,传送门:http://blog.csdn.net/ddwhan0123/article/details/50555958

这几篇关于Material Design文章的代码几乎都是Git上摘录的,我做的事主要是分享给大家+解释分析。

昨天有小伙伴看完后希望我像以前一样把按钮那一部分的代码单独提取出来单独打成一个包,想单独使用或者学习而不是去扣源码看(懒人打屁股),那既然有需求我也就做了,今天的事例代码我单独做了一个包了,大家可以直接去下载,地址:https://github.com/ddwhan0123/BlogSample/blob/master/MaterialDesignToast.zip 直接下载然后解压就行了,可以run,我2台机器都试过了,并未出现问题(记得点个赞,支持下劳动成果,谢谢)


废话结束,开始我们具体内容,还是分为2部分,P1为概念讲解,P2为实例分析。

Snackbars

Snackbar 是一种针对操作的轻量级反馈机制,常以一个小的弹出框的形式,出现在手机屏幕下方或者桌面左下方。它们出现在屏幕所有层的最上方,包括浮动操作按钮。

它们会在超时或者用户在屏幕其他地方触摸之后自动消失。Snackbar
可以在屏幕上滑动关闭。当它们出现时,不会阻碍用户在屏幕上的输入,并且也不支持输入。屏幕上同时最多只能现实一个 Snackbar。

Android 也提供了一种主要用于提示系统消息的胶囊状的提示框 Toast。Toast 同 Snackbar 非常相似,但是 Toast
并不包含操作也不能从屏幕上滑动关闭。

我们来上下效果图,看看是怎么样的:

这里写图片描述

从屏幕底部弹出的一个试图,一种是有交互的,一种是没有交互的。跟我们的Toast一样会自动消失,他消失的方式跟入场时的效果相反。

看完效果我们来读一些理论知识。

通常 Snackbar 的高度应该仅仅用于容纳所有的文本,而文本应该与执行的操作相关。Snackbar
中不能包含图标,操作只能以文本的形式存在。

这里写图片描述

样式尽量的精简不要附带复杂的布局内容

尽量不要附带过多的操作(样例里为一个点击事件),注意Snackbar不要打断任何UI界面其他元素正操进行的行为,就是如果有个dialog在跑,不要用Snackbar把他dimiss掉。

也不要遮蔽我们的悬浮按钮,尽量 让悬浮按钮置于Snackbar的上方。

原文地址:http://www.google.com/design/spec/components/snackbars-toasts.html#snackbars-toasts-specs


理论讲完了,我们来看一下代码是如何实现的。

先贴下目录结构

这里写图片描述

正好Snackbar的布局里需要我们昨天用到的按钮,我就整合进来了,然后就是一些素材文件,大家根据自己的需求操作吧,Button部分的实现,这篇不解释了,大家往前翻吧。

public class SnackBar extends Dialog 

24行,我们的SnackBar是一个Dialog的实现,而不是昨天的Rel的实现了(重要的是,要一看到继承Dialog就意识到,他有show() dismiss() 之类的功能)

    String text;
    float textSize = 14;//Roboto Regular 14sp
    String buttonText;
    View.OnClickListener onClickListener;
    Activity activity;
    View view;
    ButtonFlat button;
    int backgroundSnackBar = Color.parseColor("#333333");
    int backgroundButton = Color.parseColor("#1E88E5");

    OnHideListener onHideListener;
    // Timer
    private boolean mIndeterminate = false;
    private int mTimer = 3 * 1000;

26-39行,一系列的初始化,定义了颜色啊,声明了一些参数的变量,设置了默认的持续时间

 // With action button
    public SnackBar(Activity activity, String text, String buttonText, View.OnClickListener onClickListener) {
        super(activity, android.R.style.Theme_Translucent);
        this.activity = activity;
        this.text = text;
        this.buttonText = buttonText;
        this.onClickListener = onClickListener;
    }

    // Only text
    public SnackBar(Activity activity, String text) {
        super(activity, android.R.style.Theme_Translucent);
        this.activity = activity;
        this.text = text;
    }

41-55行,2种不同的构造函数,一种是带按钮,带监听的。还有种事更纯粹的文本内容提示。

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.snackbar);
        setCanceledOnTouchOutside(false);
        ((TextView) findViewById(R.id.text)).setText(text);
        ((TextView) findViewById(R.id.text)).setTextSize(textSize); //set textSize
        button = (ButtonFlat) findViewById(R.id.buttonflat);
        if (text == null || onClickListener == null) {
            button.setVisibility(View.GONE);
        } else {
            button.setText(buttonText);
            button.setBackgroundColor(backgroundButton);

            button.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    dismiss();
                    onClickListener.onClick(v);
                }
            });
        }
        view = findViewById(R.id.snackbar);
        view.setBackgroundColor(backgroundSnackBar);
    }

58-83行,对一系列所需的控件进行初始化操作,设置了背景颜色,设置了监听,设置了标题文字内容等。

     @Override
    public boolean onTouchEvent(MotionEvent event) {
        return activity.dispatchTouchEvent(event);
    }

    @Override
    public void onBackPressed() {
    }

85-92,进行了事件分发的操作,如果不太清楚可以看 http://blog.csdn.net/xyz_lmn/article/details/12517911

  @Override
    public void show() {
        super.show();
        view.setVisibility(View.VISIBLE);
        view.startAnimation(AnimationUtils.loadAnimation(activity, R.anim.snackbar_show_animation));
        if (!mIndeterminate) {
            dismissTimer.start();
        }
    }

94-102行,呈现我们视图,并且是执行了慢慢上升的动画,动画结束后开始计时

    Thread dismissTimer = new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                Thread.sleep(mTimer);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            handler.sendMessage(new Message());
        }
    });

    Handler handler = new Handler(new Handler.Callback() {

        @Override
        public boolean handleMessage(Message msg) {
            if (onHideListener != null) {
                onHideListener.onHide();
            }
            dismiss();
            return false;
        }
    });

105-127行,线程睡到相应事件,然后关闭我们的SnackBar

    @Override
    public void dismiss() {
        Animation anim = AnimationUtils.loadAnimation(activity, R.anim.snackbar_hide_animation);
        anim.setAnimationListener(new AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                SnackBar.super.dismiss();
            }
        });
        view.startAnimation(anim);
    }

133-152行,具体消失的方法,动画结束后 dismiss控件

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        // TODO 自动生成的方法存根
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            dismiss();
        }
        return super.onKeyDown(keyCode, event);
    }

154-161行,返回键的操作。

再接下来就是一系列的set方法了,这里不做解释,下面贴个MainActivity的操作,大家就理解了。

public class MainActivity extends AppCompatActivity {
    ButtonFlat button,button1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (ButtonFlat) findViewById(R.id.button);
        button1=(ButtonFlat)findViewById(R.id.button1);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SnackBar snackbar = new SnackBar(MainActivity.this, "这是一段很长的文字", "按钮的文字内容",
                        new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                Toast.makeText(MainActivity.this, "按钮被点击后吐出的内容", Toast.LENGTH_SHORT).show();
                            }
                        });
                snackbar.setDismissTimer(9000);
                snackbar.show();
            }
        });

        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SnackBar snackBar=new SnackBar(MainActivity.this,"只有文字");
                snackBar.setBackgroundSnackBar(getResources().getColor(R.color.BrulyWood));
                snackBar.setMessageTextSize(20);
                snackBar.show();
            }
        });

    }

}

如何调用,如何设置看这里就理解了,很简单易懂。
建议修改下默认的持续时间,感觉有点短。

相比昨天的Button这部分还算简单,大家一定也可以做出类似的效果。

以下广告为广告可不看:
博主微博:http://weibo.com/u/5298245888
微信:
这里写图片描述

一般我QQ回复会比较慢,微信可以随时找我。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值