在Android中提示信息的控件主要用Toast或者Dialog,当然也有自定义的View,各种自定义Dialog或者Toast。
这里将介绍一种比Toast重,比Dialog轻的控件,它叫Snackbar。
同样是Android support design Library中的一员,而它却显得非常自由,不需要XML布局文件的设置,这就跟Toast像极了。说它是Toast的升级版也可以,因为它的功能要比Toast丰富。
compile 'com.android.support:design:23.0.1'
或者更高版本
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.android.support:design:23.0.1'
}
Snackbar构造方法 一
Snackbar.make(View view, CharSequence text, int duration)
Snackbar构造方法 二
Snackbar.make(View view, int resId, int duration)
第一个参数View:根据这个View找到Snackbar的恰当父视图来确保显示在底部,以下会进行一点源码解析。
Snackbar.make(view, text, Snackbar.LENGTH_SHORT).setAction("CaMnter", new View.OnClickListener() {
@Override
public void onClick(View v) {
}
}).show();
Snackbar设置Action 一
Snackbar.setAction(@StringRes int resId, OnClickListener listener)
Snackbar设置Action 二
Snackbar.setAction(CharSequence text, final OnClickListener listener)
Snackbar弹出后,点击”CaMnter”字,就会响应事件,弹出Toast
Snackbar.make(view, text, Snackbar.LENGTH_SHORT).setAction("CaMnter", new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(SnackbarActivity.this,"Hello World",Toast.LENGTH_LONG).show();
}
}).show();
Snackbar设置内容 一
Snackbar.setText(CharSequence message)
Snackbar设置内容 二
Snackbar..setText(@StringRes int resId)
Snackbar设置Action文本颜色 一
Snackbar.setActionTextColor(int color)
Snackbar设置Action文本颜色 二
Snackbar.setActionTextColor(ColorStateList colors)
Snackbar显示
Snackbar.show()
Snackbar隐藏
Snackbar.dismiss()
先看两个make方法
public static Snackbar make(View view, CharSequence text, int duration) {
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后,第一步就放到findSuitableParent(View view)
方法里了。
在看findSuitableParent(View view)方法
@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;
}
view.getId() == 16908290
可以判断是否到最外层的View,因为Activity的最外层实质上是FrameLayout,16908290是这个R.id.content的值。view = parent instanceof View?(View)parent:null;
,开始从新给view赋值,继续走到上一层的View再循环。最后看看构造方法
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);
}
将刚才findSuitableParent(View view)
方法拿到的View最为inflate
方法的根视图参数,进行初始化Snackbar。
总结:Snackbar.findSuitableParent(View view)
的源码还是挺有意思的。疯狂的寻找CoordinatorLayout和FrameLayout,因为有CoordinatorLayout的父视图上,Snackbar显得更加智能。