• Android Snackbar使用方法及小技巧-design


    Snackbar和Toast相似,都是为了给用户提供交互信息,Snackbar是固定在底部的,显示时从下往上滑出

    这里写图片描述

    要使用Snackbar,需要在项目的build.gradle中添加依赖

    dependencies {
         compile 'com.android.support:design:23.4.0'
    }

    Snackbar的使用方法和Toast很相似

    Snackbar.make(mOpenTv, "消息内容", Snackbar.LENGTH_SHORT)
                            .setAction("确定", new View.OnClickListener() {
                                @Override
                                public void onClick(View v) {
    
                                }
                            })
                            .show();

    第一个参数需要传入一个View,可以是界面当中的任意一个View控件,Snackbar会自动根据这个控件找到最外层的布局来显示

    第二个参数就是我们需要显示的内容,注意这里的内容最多显示两行哦,超出两行后的内容会变成“…”

    第三个参数为Snackbar显示的时长,有三种模式供选择

    • LENGTH_SHORT:短时间显示

    • LENGTH_LONG:长时间显示

    • LENGTH_INDEFINITE:一直显示,只有当用户触发Action点击事件或手动删除时才会消失

    Snackbar可以通过setAction方法设置一个点击事件,和用户进行交互

    我们还可以通过setCallback方法来监听Snackbar的显示和关闭

            Snackbar sb = Snackbar.make(mOpenTv, "消息内容", Snackbar.LENGTH_SHORT);
            sb.setCallback(new Snackbar.Callback() {
                @Override
                public void onDismissed(Snackbar snackbar, int event) {
                    super.onDismissed(snackbar, event);
                    // Snackbar关闭时回调
                }
    
                @Override
                public void onShown(Snackbar snackbar) {
                    super.onShown(snackbar);
                    // Snackbar打开时回调
                }
            });
            sb.show();

    Snackbar还支持滑出删除,需要在布局文件中使用CoordinatorLayout作为根布局
    这里写图片描述

    建议要使用Snackbar的时候最好是以CoordinatorLayout作为根布局,如果以其它RelativeLayout,LinearLayout等作为根布局的话,会出现以下这种情况

    这里写图片描述

    FloatingActionButton被遮到了,使用CoordinatorLayout作为根布局可以避免这种情况

    这里写图片描述

    Snackbar只能在底部显示吗?
    是也不是,为啥这么说呢,Snackbar确实是在CoordinatorLayout底部显示的,但并不等于是在屏幕顶部
    首先我们要知道Snackbar显示的原理是什么
    之前介绍中的第一个传进去的参数View,Snackbar会通过这个View控件找到它所在的根布局,我们来查看下源码

        public static Snackbar make(@NonNull View view, @NonNull CharSequence text,
                @Duration int duration) {
            Snackbar snackbar = new Snackbar(findSuitableParent(view));
            snackbar.setText(text);
            snackbar.setDuration(duration);
            return snackbar;
        }

    我们传进去的view会经过findSuitableParent方法的处理,我们再来看下这个方法的具体实现

        private static ViewGroup findSuitableParent(View view) {
            ViewGroup fallback = null;
            do {
                if (view instanceof CoordinatorLayout) {
                    // We've found a CoordinatorLayout, use it
                    return (ViewGroup) view;
                } else if (view instanceof FrameLayout) {
                    if (view.getId() == android.R.id.content) {
                        // If we've hit the decor content view, then we didn't find a CoL in the
                        // hierarchy, so use it.
                        return (ViewGroup) view;
                    } else {
                        // It's not the content view but we'll use it as our fallback
                        fallback = (ViewGroup) view;
                    }
                }
    
                if (view != null) {
                    // Else, we will loop and crawl up the view hierarchy and try to find a parent
                    final ViewParent parent = view.getParent();
                    view = parent instanceof View ? (View) parent : null;
                }
            } while (view != null);
    
            // If we reach here then we didn't find a CoL or a suitable content view so we'll fallback
            return fallback;
        }

    详细的过程google的工程师已经写的非常的清楚了,我们主要需要了解的就是当一个View的直接父布局为CoordinatorLayout时,就以这个CoordinatorLayout为标准来显示Snackbar
    我们可以做个小实验验证一下
    在传入的View控件外面套一层CoordinatorLayout

        <android.support.design.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="100dp">
    
            <TextView
                android:id="@+id/tv_open_snackbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="打开Snackbar"
                android:textSize="28sp"/>
        </android.support.design.widget.CoordinatorLayout>

    再运行一下看看,效果就变成了下面这样
    这里写图片描述
    所以说Snackbar的显示位置还是可以通过这个小技巧来改变的

    如果嫌默认的Snackbar太丑怎么办?
    我们可以来自定义它的外观

    1.改变按钮的文字颜色
    通过调用setActionTextColor方法即可改变按钮的文字颜色

            Snackbar sb = Snackbar.make(mOpenTv, "消息内容", Snackbar.LENGTH_SHORT);
            sb.setAction("确定", new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                }
            });
            sb.setActionTextColor(Color.YELLOW);
            sb.show();

    这里写图片描述

    2.改变消息内容的文字颜色
    Snackbar没有给我们提供改变消息文本颜色的api接口,但在查看源码时发现了这个方法getView

        /**
         * Returns the {@link Snackbar}'s view.
         */
        @NonNull
        public View getView() {
            return mView;
        }

    这里返回的mView其实是一个SnackbarLayout布局,在SnackbarLayout的构造方法中找到了它的布局文件design_layout_snackbar_include

                // Now inflate our content. We need to do this manually rather than using an <include>
                // in the layout since older versions of the Android do not inflate includes with
                // the correct Context.
                LayoutInflater.from(context).inflate(R.layout.design_layout_snackbar_include, this);

    design_layout_snackbar_include布局文件里只有两个控件,一个TextView,一个Button

    <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/design_snackbar_padding_vertical"
                android:paddingBottom="@dimen/design_snackbar_padding_vertical"
                android:paddingLeft="@dimen/design_snackbar_padding_horizontal"
                android:paddingRight="@dimen/design_snackbar_padding_horizontal"
                android:textAppearance="@style/TextAppearance.Design.Snackbar.Message"
                android:maxLines="@integer/design_snackbar_text_max_lines"
                android:layout_gravity="center_vertical|left|start"
                android:ellipsize="end"
                android:textAlignment="viewStart"/>
    
        <Button
                android:id="@+id/snackbar_action"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/design_snackbar_extra_spacing_horizontal"
                android:layout_marginStart="@dimen/design_snackbar_extra_spacing_horizontal"
                android:layout_gravity="center_vertical|right|end"
                android:paddingTop="@dimen/design_snackbar_padding_vertical"
                android:paddingBottom="@dimen/design_snackbar_padding_vertical"
                android:paddingLeft="@dimen/design_snackbar_padding_horizontal"
                android:paddingRight="@dimen/design_snackbar_padding_horizontal"
                android:visibility="gone"
                android:textColor="?attr/colorAccent"
                style="?attr/borderlessButtonStyle"/>
    
    </merge>

    相信看到这里大家应该知道怎么做了,TextView的id为snackbar_text,我们通过getView()来获取这个TextView控件

            Snackbar sb = Snackbar.make(mOpenTv, "消息内容", Snackbar.LENGTH_SHORT);
            sb.setAction("确定", new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                }
            });
            sb.setActionTextColor(Color.YELLOW);
    
            View view = sb.getView();
            TextView tv = (TextView) view.findViewById(R.id.snackbar_text);
            tv.setTextColor(Color.RED);
    
            sb.show();

    这里写图片描述
    同样的,我们也可以通过tv.setTextSize设置它的文字大小

    3.改变消息内容的背景
    同理,根据以上方法,得到它的布局,调用对应的api接口就好

            View view = sb.getView();
            view.setBackgroundColor(Color.RED);

    像这种红红的给用户警告的提示,是不是比Toast要来的炫酷多了呢
    这里写图片描述

    这里写图片描述

    4.给消息内容添加图标
    获取到消息内容的TextView后,调用setCompoundDrawables方法设置它的图标,可自由选择图标放置的位置,四个参数分别对应TextView的左、上、右、下

            Snackbar sb = Snackbar.make(mOpenTv, "消息内容", Snackbar.LENGTH_SHORT);
            sb.setAction("确定", new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                }
            });
            sb.setActionTextColor(Color.YELLOW);
    
            View view = sb.getView();
            TextView tv = (TextView) view.findViewById(R.id.snackbar_text);
            Drawable d = ContextCompat.getDrawable(this, R.drawable.warn);
            d.setBounds(0, 0, d.getMinimumWidth(), d.getMinimumHeight());
            tv.setCompoundDrawables(d, null, null, null);   // 给TextView左边添加图标
            tv.setGravity(Gravity.CENTER);  // 让文字居中
    
            sb.show();
        }

    这里写图片描述
    注意要设置setGravity使其居中,不然文字默认在上面不好看啊

    就先介绍这么多,其实只要拿到了它的布局,接下来怎么整就看各位的喜好啦

  • 相关阅读:
    python协程爬取某网站的老赖数据
    python异步回调顺序?是否加锁?
    go语言循环变量
    使用memory_profiler异常
    安装python性能检测工具line_profiler
    等我!
    pytorch代码跟着写
    Python异常类型总结
    Python项目代码阅读【不断更新】
    夏令营体会
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/6039378.html
Copyright © 2020-2023  润新知