大家好,欢迎来到IT知识分享网。
本篇博客将会给大家带来一个轻量级控件SnackBar,为什么要讲SnackBar?Snackbar:的提出实际上是界于Toast和Dialog的中间产物。因为Toast与Dialog各有一定的不足,使用Toast的时候, 用户无法交互;使用Dialog:用户可以交互,但是体验会打折扣,会阻断用户的连贯性操作;但是使用Snackbar既可以做到轻量级的用户提醒效果,又可以有交互的功能,本博客将会从SnackBar的使用和源码分析两个方面进行介绍。
SnackBar的使用
SnackBar的使用十分简单,其实和Toast的使用方法差不多,我们写一个很简单的例子,来看一下SnackBar的使用,布局上有一个按钮,点击后弹出SnackBar,弹出的逻辑如下,布局代码很简单就不贴了。
public void showSnackBar(View view) {
//LENGTH_INDEFINITE:无穷 Snackbar snackbar = Snackbar.make(view,"您的Wifi已经开启!",Snackbar.LENGTH_INDEFINITE); snackbar.setAction("确定", new View.OnClickListener() {
@Override public void onClick(View v) {
Toast.makeText(MainActivity.this, "确定啦", Toast.LENGTH_SHORT).show(); } }); snackbar.setCallback(new Snackbar.Callback() {
@Override public void onDismissed(Snackbar snackbar, int event) {
Toast.makeText(MainActivity.this, "SnackBar消失了", Toast.LENGTH_SHORT).show(); } @Override public void onShown(Snackbar snackbar) {
Toast.makeText(MainActivity.this, "SnackBar出现了", Toast.LENGTH_SHORT).show(); } }); snackbar.setActionTextColor(Color.BLUE); snackbar.show(); }
可以看到上面代码,setAction方法用于给SnackBar设置按钮,setCallback方法用于设置回调,当SnackBar出现时或者消失时都会有相应的回调,同时setActionTextColor方法可以给改变SnackBar中按钮的颜色。
SnackBar的源码分析
SnackBar是通过make方法进行创建的,所以我们首先需要查看SnackBar的make方法
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; }
里面有一个findSuitableParent方法,Snackbar内部把view传递给了这个方法,查看该方法的逻辑
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; }
发现这里竟然是一个do while的循环,只要view!= null,就会一直循环下去,里面会对view进行判断,是CoordinatorLayout,则直接返回,如果是FrameLayout,并且当view.getId() == android.R.id.content时候,也将view进行返回,大家都知道R.id.content就是decorView下的content部分,否则就会将这个view赋值给fallback,这个fallback就是一个viewGroup。下面这一句非常关键
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; }
取出view的Parent并且只要这个parent是View,就将其赋值给我门的view,到这里我们明白了,这个死循环就是为了无限的从传进来的这个view开始无限的向上寻找view的父亲,直到没有父亲为止,最后会返回fallback。然后我们自然会先去查看Snackbar构造函数,看它里面是进行了什么逻辑
private Snackbar(ViewGroup parent) {
mParent = parent; mContext = parent.getContext(); LayoutInflater inflater = LayoutInflater.from(mContext); mView = (SnackbarLayout) inflater.inflate(R.layout.design_layout_snackbar, mParent, false); }
在这里面最重要的一句就是渲染了一个R.layout.design_layout_snackbar的布局,很明显这个布局是系统自带的,很明显在这里已经写死了,所以我们想修改这个SnackBar显然是不行的,而且它还强转成了SnackbarLayout布局,我们可以查看一下这个布局的代码,这个布局在design包的layout下
<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=
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/136278.html