Android Design Support Library实践之Snackbar

    Google在2014年发布了Material Design语言,紧接着第二年发布了官方support包,可以支持在低版本上手机使用这些控件。但是这么长时间过去了,国内主流app几乎都没有遵循这种规范,原因也很好理解了,这篇文章分析的比较到位(为什么Material Design没在国产App中流行起来)。最近有机会重头开始做一个APP,这是一个很好的机会践行Material Design,这里把学习support包的一些心得记录一下,与大家共同交流学习。首先是第一个控件Snackbar:

Snackbar和Toast很相似,不过是从屏幕最下方推出来,并且里面可以带button支持用户点击。它的使用很简单:

Snackbar.make(view, "You Click the Button", Snackbar.LENGTH_LONG).show();

看上面代码几乎可Toast使用一样,上面说了它可以添加button支持点击事件,下面的代码是添加button的:

Snackbar.make(view, "You Click the Button", Snackbar.LENGTH_LONG)
                    .setAction("返回", new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            finish();
                        }
                    })
                    .show();

这里大家注意一下make方法的第一个参数,它是一个View而不是Context,我们可以理解成这个View是Snackbar的容器,如果此View是CoordinatorLayout,那么Snackbar支持向右滑动删除。
    那么是不是Snackbar只能从屏幕底部推出呢?我们看下面部分源码:

private Snackbar(ViewGroup parent) {
        mTargetParent = parent;
        mContext = parent.getContext();

        ThemeUtils.checkAppCompatTheme(mContext);

        LayoutInflater inflater = LayoutInflater.from(mContext);
        mView = (SnackbarLayout) inflater.inflate(
                R.layout.design_layout_snackbar, mTargetParent, false);
    }
public static Snackbar make(@NonNull View view, @NonNull CharSequence text,
            @Duration int duration) {
        <span style="color:#ff0000;">Snackbar snackbar = new Snackbar(findSuitableParent(view));</span>
        snackbar.setText(text);
        snackbar.setDuration(duration);
        return snackbar;
    }
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;
    }

从上面代码可以看出,如果第一个参数是CoordinatorLayout,那么第一个参数直接为它的父容器,否则的话,它会一直找到这个参数的根容器或者decor content view,也就是说第一个参数传CoordinatorLayout时,它是可以在屏幕任意位置显示的。

    还有一个问题,Snackbar中按钮上面的字体颜色可以改变吗?答案是肯定的,它提供了一个方法setActionTextColor(),但是提示文本的颜色就不能修改了,当然你非要改也不是没有办法,毕竟源码都在这里了。
    我看网上有人提到,大量使用Snackbar,会导致内存上升,我测试了一下,确实会有这种情况,但我认为正常使用这种情况可以忽略的。首先是每次使用它产生的内存很小,其实这些内存都是可以回收的,系统GC时都可以释放。下面是效果图,demo代码地址: https://github.com/dfqin/MaterialDesignDemo


你可能感兴趣的:(android,design,material,Snackbar)