精华内容
下载资源
问答
  • SnackBar

    2021-03-27 22:06:46
    SnackBar

    SnackBar 用于在询问短暂地显示信息消息。

    展开全文
  • Snackbar

    2020-07-14 23:59:16
    目录什么是SnackBar?使用改变SnackBar背景颜色 什么是SnackBar? 类似Toast的提示工具,但是和Toast不同的是,可以在提示中加入一个可交互的按钮,当点击按钮的时候可以执行一些额外的逻辑操作。 会从屏幕底部出现,...

    什么是SnackBar?

    类似Toast的提示工具,但是和Toast不同的是,可以在提示中加入一个可交互的按钮,当点击按钮的时候可以执行一些额外的逻辑操作。

    会从屏幕底部出现,过一段时间会自动消失

    使用

    Snackbar.make(view,"一般用法", Snackbar.LENGTH_SHORT)
                    .setAction("undo", new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            Toast.makeText(SnackBarActivity.this,"撤销",Toast.LENGTH_SHORT).show();
                        }
                    })
                    .show();
    

    说明:
    Snackbar.make(view,content,time)

    1. 通过make创建一个SnackBar,参数1:只要是当前布局的任意一个view都可以,参数2:显示 的内容,参数3:显示的时长;
    2. 调用setAction()设置一个动作,可以和用户交互

    改变SnackBar背景颜色

           //创建Snackbar
            Snackbar mSnackbar = Snackbar.make(view, "已加入行程", Snackbar.LENGTH_INDEFINITE);
            
            //设置Snackbar的背景颜色
            mSnackbar.getView().setBackgroundColor(ContextCompat.getColor(SnackBarActivity.this, R.color.colorPrimary));
            
            //设置Action文字的背景颜色
            mSnackbar.setActionTextColor(Color.WHITE);
            
            //添加操作
            mSnackbar.setAction("知道了", new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(SnackBarActivity.this,"完成",Toast.LENGTH_SHORT).show();
                }
            });
            //显示
            mSnackbar.show();
    
    展开全文
  • snackBar

    2016-02-01 18:05:06
    这个文章系统的阐述了 snackbar和toast的区别和正确使用snackbar的方式。 我简单归纳如下: 1.比toast更加好,毕竟snackbar 可以响应点击事件 2.snackbar 同一时间有且只有一个在显示。 3....

    下面这篇文章写的很细致。


    原文:http://www.open-open.com/lib/view/open1437460246974.html


    在谷歌提出 material design 之后,终于推出了 android.support.design 这个官方的material design库,这几天我也简单浏览了下这个库,基本上我们常用的组件都有了,从今天开始,就可以一步步替换掉

    以前使用的github上的那些开源控件了,毕竟谷歌出品 才属精品~~另外分析这个design库的源码我认为是非常有意义的,android上的app 在以前各家都有各家的风格,但是在谷歌出了material design这门新的

    设计语言以及官方的库以后,相信越来越多的app 会逐步优化自己的ui 来符合官方的标准,学习这个design库的源码可以让我们以后改写自定义控件的时候更加柔韧有余。

    首先,来看一下这个官方的介绍。http://www.google.com/design/spec/components/snackbars-toasts.html#

    这个文章系统的阐述了 snackbar和toast的区别和正确使用snackbar的方式。

    我简单归纳如下:

    1.比toast更加好,毕竟snackbar 可以响应点击事件

    2.snackbar 同一时间有且只有一个在显示。

    3.snackbar 上不要有图标

    4.snackbar上action 只能有一个。

    5.如果有悬浮按钮 floating action button的话,snackbar 在弹出的时候 不要覆盖这个button.

    6.此外我个人认为snackbar 在一定程度上可以替代dialog的某些应用场景。比如以前网络不通的情况下 我们登陆失败,会给一个dialog提示,现在就可以用snackbar 来做这个有action的提示 更加方便快捷。

    使用snackbar:

    1.导入support design 库 (这一步在以后的design库的 控件文章里都会舍去)

    首先找到你app的build gradle文件

    Android Support Design 库 之 Snackbar使用及源码分析

    然后增加一个compile语句即可

    compile 'com.android.support:design:22.2.0'

    Android Support Design 库 之 Snackbar使用及源码分析

    2.编写xml文件以及java文件

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".MainActivity"
        android:id="@+id/layout">
     
     
        <!-- 因为snackbar 需要有一个父控件所以 我们暂时就用tv 来做他的父控件-->
        <TextView
            android:id="@+id/tv"
            android:layout_width="match_parent"
            android:layout_height="30dp"
            android:layout_centerVertical="true"
            android:gravity="center"
            android:text="Bottom layout" />
     
    </RelativeLayout>

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    package com.example.burning.myapplication;
     
    import android.os.Bundle;
    import android.support.design.widget.Snackbar;
    import android.support.v7.app.ActionBarActivity;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.TextView;
     
     
    public class MainActivity extends ActionBarActivity {
     
        private TextView tv;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            tv = (TextView) this.findViewById(R.id.tv);
            tv.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //这个地方第一个参数    传进去的是tv    但是实际上你无论传进去什么值 snackbar都一定是从屏幕的最底端出现的    原因在源码
                    //分析那边可以看到
                    Snackbar.make(tv, "connection error", Snackbar.LENGTH_LONG).setAction("retry"new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            tv.setText("aleady click snackbar");
                        }
                    }).show();
     
                }
            });
        }
     
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.menu_main, menu);
            return true;
        }
     
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
     
            //noinspection SimplifiableIfStatement
            if (id == R.id.action_settings) {
                return true;
            }
     
            return super.onOptionsItemSelected(item);
        }
    }

    最后我们来看下效果

    Android Support Design 库 之 Snackbar使用及源码分析

     

     

     然后我们来看一下 如果和正常的FAB(悬浮按钮)在一起会有什么效果(注意这里的悬浮按钮我们也使用design库里的并不使用github上开源的)

    先看一下xml文件

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".MainActivity">
     
     
        <FrameLayout
            android:id="@+id/layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
     
            <android.support.design.widget.FloatingActionButton
                android:id="@+id/btnFloatingAction"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom|right"
                android:src="@drawable/ic_plus"
                app:borderWidth="0dp"
                app:fabSize="normal" />
        </FrameLayout>
    </RelativeLayout>

    activity代码
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    package com.example.burning.myapplication;
     
    import android.os.Bundle;
    import android.support.design.widget.Snackbar;
    import android.support.v7.app.ActionBarActivity;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewGroup;
     
     
    public class MainActivity extends ActionBarActivity {
     
        private ViewGroup layout;
     
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            layout = (ViewGroup) this.findViewById(R.id.layout);
            layout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Snackbar.make(layout, "connection error", Snackbar.LENGTH_LONG).setAction("retry"new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                        }
                    }).show();
     
                }
            });
        }
     
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.menu_main, menu);
            return true;
        }
     
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
     
            //noinspection SimplifiableIfStatement
            if (id == R.id.action_settings) {
                return true;
            }
     
            return super.onOptionsItemSelected(item);
        }
    }

    来看一下运行效果

    Android Support Design 库 之 Snackbar使用及源码分析

    大家可以看到当我们的snackbar在弹出的时候    会覆盖到我们的FAB,那这体验是非常糟糕的,这里也给出一个完美的解决方案

    其实也很简单用一下design库里的layout即可    java代码不需要改变    只要稍微改一下布局文件即可

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".MainActivity">
     
     
        <android.support.design.widget.CoordinatorLayout
            android:id="@+id/layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
     
            <android.support.design.widget.FloatingActionButton
                android:id="@+id/btnFloatingAction"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom|right"
                android:src="@drawable/ic_plus"
                app:borderWidth="0dp"
                app:fabSize="normal" />
        </android.support.design.widget.CoordinatorLayout>
    </RelativeLayout>

    就是换了一个新的layout而已。

    来看下运行的效果。

     

     Android Support Design 库 之 Snackbar使用及源码分析

     

    当然了 你要改变这个snackbar的背景色也是可以的 只需要

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    Snackbar sb=Snackbar.make(layout, "connection error", Snackbar.LENGTH_LONG).setAction("retry"new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                        }
                    });
                    //红色
                    sb.getView().setBackgroundColor(0xfff44336);
                    sb.show();

    基本的用法 要点就是这些,我们来看一下这个snackbar的源码   看看谷歌官方是如何编写 material design 风格控件的

    这里我无法贴上全部源码 因为太多,只挑重要的流程说 可以从make开始。

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    //这个地方就是构造函数
        Snackbar(ViewGroup parent) {
            this.mParent = parent;
            this.mContext = parent.getContext();
            LayoutInflater inflater = LayoutInflater.from(this.mContext);
            this.mView = (Snackbar.SnackbarLayout)inflater.inflate(layout.layout_snackbar, this.mParent, false);
        }
     
        //这个地方就是我们调用的make函数 也就是整个类的一个入口 在这里可以看到 我们的代码转入了snackbar的构造函数
        public static Snackbar make(View view, CharSequence text, int duration) {
            //注意看这个地方调用了 findsuitableparent这个函数
            Snackbar snackbar = new Snackbar(findSuitableParent(view));
            snackbar.setText(text);
            snackbar.setDuration(duration);
            return snackbar;
        }
     
        public static Snackbar make(View view, int resId, int duration) {
            return make(view, view.getResources().getText(resId), duration);
        }
     
        //这个函数其实作用就是无论你传进去的是什么view 我最终都会遍历到framlayout为止,因为activity的最外层实际上就是一个framlayout
        //所以你在调用make函数的时候无论传什么值进去 snackabr都会从最底部弹出来 就是因为这个函数做了这样的工作 但是!!!!
                    //如果在遍历到最顶部的framlayout之前 遇到了一个framelayout 那么就会从这个framlayout的底部弹出,而不会从屏幕的最下方弹出了。
        //这个地方CoordinatorLayout的优先级比framlayout还要高 所以你如果穿进去的view是CoordinatorLayout的话 这个snackbar 就一定会从
        //CoordinatorLayout 底部弹出了。如果你CoordinatorLayout的最底部恰好在屏幕中间 那么snackbar 就会从屏幕中间弹出  而不会从底部弹出 这一点一定要注意
        @Nullable
        private static ViewGroup findSuitableParent(View view) {
            ViewGroup fallback = null;
     
            do {
                if(view instanceof CoordinatorLayout) {
                    return (ViewGroup)view;
                }
     
                if(view instanceof FrameLayout) {
                    if(view.getId() == 16908290) {
                        return (ViewGroup)view;
                    }
     
                    fallback = (ViewGroup)view;
                }
     
                if(view != null) {
                    ViewParent parent = view.getParent();
                    view = parent instanceof View?(View)parent:null;
                }
            while(view != null);
     
            return fallback;
        }

    大家可以看一下第六行。实际上这个mView就是一个内部类的对象

    1 private final Snackbar.SnackbarLayout mView;

    Android Support Design 库 之 Snackbar使用及源码分析

     

    然后接着看第六行的xml文件(到这里其实我们也能猜到了 真正自定义view的snackbar是由snackbar的内部类snackbarlayout来完成的)

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <?xml version="1.0" encoding="utf-8"?>
    <!--
      ~ Copyright (C) 2015 The Android Open Source Project
      ~
      ~ Licensed under the Apache License, Version 2.0 (the "License");
      ~ you may not use this file except in compliance with the License.
      ~ You may obtain a copy of the License at
      ~
      ~      http://www.apache.org/licenses/LICENSE-2.0
      ~
      ~ Unless required by applicable law or agreed to in writing, software
      ~ distributed under the License is distributed on an "AS IS" BASIS,
      ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      ~ See the License for the specific language governing permissions and
      ~ limitations under the License.
    -->
     
    <!--注意看class那边的写法  那个$就是代表内部类的一个符号 这个技巧 以后我们自己自定义控件的时候也可以学习-->
    <view xmlns:android="http://schemas.android.com/apk/res/android"
          class="android.support.design.widget.Snackbar$SnackbarLayout"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:layout_gravity="bottom"
          style="@style/Widget.Design.Snackbar" /><!-- From: file:/usr/local/google/buildbot/repo_clients/https___googleplex-android.googlesource.com_a_platform_manifest.git/lmp-mr1-supportlib-release/frameworks/support/design/res/layout/layout_snackbar.xml -->

    继续看下内部类

    Android Support Design 库 之 Snackbar使用及源码分析

    找到我们真正的snackbar的布局文件 注意这个地方讨巧的使用了merge标签 这是一个比较好的优化xml的 写法

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    <?xml version="1.0" encoding="utf-8"?>
    <!--
      ~ Copyright (C) 2015 The Android Open Source Project
      ~
      ~ Licensed under the Apache License, Version 2.0 (the "License");
      ~ you may not use this file except in compliance with the License.
      ~ You may obtain a copy of the License at
      ~
      ~      http://www.apache.org/licenses/LICENSE-2.0
      ~
      ~ Unless required by applicable law or agreed to in writing, software
      ~ distributed under the License is distributed on an "AS IS" BASIS,
      ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      ~ See the License for the specific language governing permissions and
      ~ limitations under the License.
    -->
     
    <merge xmlns:android="http://schemas.android.com/apk/res/android">
     
        <TextView
                android:id="@+id/snackbar_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:paddingTop="@dimen/snackbar_padding_vertical"
                android:paddingBottom="@dimen/snackbar_padding_vertical"
                android:paddingLeft="@dimen/snackbar_padding_horizontal"
                android:paddingRight="@dimen/snackbar_padding_horizontal"
                android:textAppearance="@style/TextAppearance.Design.Snackbar.Message"
                android:maxLines="@integer/snackbar_text_max_lines"
                android:layout_gravity="center_vertical|left|start"
                android:ellipsize="end"/>
     
        <TextView
                android:id="@+id/snackbar_action"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/snackbar_extra_spacing_horizontal"
                android:layout_marginStart="@dimen/snackbar_extra_spacing_horizontal"
                android:layout_gravity="center_vertical|right|end"
                android:background="?attr/selectableItemBackground"
                android:paddingTop="@dimen/snackbar_padding_vertical"
                android:paddingBottom="@dimen/snackbar_padding_vertical"
                android:paddingLeft="@dimen/snackbar_padding_horizontal"
                android:paddingRight="@dimen/snackbar_padding_horizontal"
                android:visibility="gone"
                android:textAppearance="@style/TextAppearance.Design.Snackbar.Action"/>
     
    </merge><!-- From: file:/usr/local/google/buildbot/repo_clients/https___googleplex-android.googlesource.com_a_platform_manifest.git/lmp-mr1-supportlib-release/frameworks/support/design/res/layout/layout_snackbar_include.xml -->

    到这里 主要的snackbar的一个加载流程就分析完毕了,很多诸如动画的代码部分 我就暂时不去分析他了,大家可以自己仔细分析。

    另外有心的同学可能发现了这么一个代码

    Android Support Design 库 之 Snackbar使用及源码分析

     

    实际上Behavior 我个人认为是这次support design库里面最重要的一个东西,以后我会单独出来讲一下。基本上support design包里 每一个控件都有她的身影出没。

    ----------------------------------

    关于以上,需要补充两点:

    1.Toast是可以在Service中使用,但是snackBar初始化时需要传入View,因此不可以再service里使用。

    2.setAction设置的 点击事件,执行时会自动隐藏snackBar,不能在这里主动调用snackBar.dismiss(),否则fab会不执行动画效果,无法回到原来的位置。



    展开全文
  • Snackbar使用

    2016-08-04 16:36:09
    Snackbar