Material Design系列文章(SnakeBar学习笔记)
Material Design系列文章(SnakeBar学习笔记)
1、SnakeBar基本使用
Snackbar.make(activity_main,"今天周五啦!",Snackbar.LENGTH_SHORT)
.setAction("确定", new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"确定",Toast.LENGTH_SHORT).show();
}
}).addCallback(new BaseTransientBottomBar.BaseCallback<Snackbar>() {
//SnakeBar显示的 时候调用
@Override
public void onShown(Snackbar transientBottomBar) {
super.onShown(transientBottomBar);
}
//SnakeBar隐藏的时候调用
@Override
public void onDismissed(Snackbar transientBottomBar, int event) {
super.onDismissed(transientBottomBar, event);
}
}).show();
2、SnakeBar可叠加多个Action,但是只对最后一个Action有效
3、可以使用setActionTextColor()方法设置Action文字的的颜色
4、若想修改SnakeBar的文字的样式,则需要通过获取SnakeBar对象,然后获得其对应的TextView(其id为snackbar_text,具体可以看一下源码的xml文件,里面就是一个TextView和一个Button),对其修改部分属性,如:修改文字颜色:
Snackbar bar = Snackbar.make(activity_main,"今天周五啦!",Snackbar.LENGTH_SHORT).setAction("确定", new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"确定",Toast.LENGTH_SHORT).show();
}
}).addCallback(new BaseTransientBottomBar.BaseCallback<Snackbar>() {
//SnakeBar显示的时候调用
@Override
public void onShown(Snackbar transientBottomBar) {
super.onShown(transientBottomBar);
}
//SnakeBar小时的时候调用
@Override
public void onDismissed(Snackbar transientBottomBar, int event) {
super.onDismissed(transientBottomBar, event);
}
}).setActionTextColor(Color.GREEN);
((TextView)(bar.getView().findViewById(R.id.snackbar_text))).setTextColor(Color.YELLOW);
bar.show();
注意点(踩坑点):
SnakeBar在make方法中的源码如下:
/**
* Make a Snackbar to display a message
*
* <p>Snackbar will try and find a parent view to hold Snackbar's view from the value given
* to {@code view}. Snackbar will walk up the view tree trying to find a suitable parent,
* which is defined as a {@link CoordinatorLayout} or the window decor's content view,
* whichever comes first.
*
* <p>Having a {@link CoordinatorLayout} in your view hierarchy allows Snackbar to enable
* certain features, such as swipe-to-dismiss and automatically moving of widgets like
* {@link FloatingActionButton}.
*
* @param view The view to find a parent from.
* @param text The text to show. Can be formatted text.
* @param duration How long to display the message. Either {@link #LENGTH_SHORT} or {@link
* #LENGTH_LONG}
*/
@NonNull
public static Snackbar make(@NonNull View view, @NonNull CharSequence text,
@Duration int duration) {
final ViewGroup parent = findSuitableParent(view);
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
final SnackbarContentLayout content =
(SnackbarContentLayout) inflater.inflate(
R.layout.design_layout_snackbar_include, parent, false);
final Snackbar snackbar = new Snackbar(parent, content, content);
snackbar.setText(text);
snackbar.setDuration(duration);
return snackbar;
}
其parent为从当前的布局文件中寻找到根布局(为CoordinatorLayout或FragmeLayout),所以当SnakeBar的父控件就是上述两个布局之一时,其显示位置为在父控件的底部,而并不一定在屏幕的底端,除非当其父控件的宽为全屏时,才会得到SnakeBar显示在屏幕底部的效果,具体原因撸波代码即可:
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;
}
从findSuitableParent()方法中可以看到,当前拿到的View为CoordinatorLayout或FragmeLayout时,便结束寻找最终的父控件。