Snackbar是5.0推出的新控件,主要作用是一种新的软提醒,也可以与用户进行简单的交互。
效果图如下:
直接看下snackbar的主要创建方法
Snackbar.make(target, "请事件输入标题", Snackbar.LENGTH_LONG)//设置目标容器,事件标题,显示时间
.setActionTextColor(Color.WHITE)//设置事件文字颜色
.setAction("按鈕文字", new View.OnClickListener() {//设置按钮文字和监听
@Override
public void onClick(View v) {
}
})
.show();//显示
直接看下make方法的里面实现了什么
@NonNull
public static Snackbar make(@NonNull View view, @NonNull CharSequence text,
@Duration int duration) {
final ViewGroup parent = findSuitableParent(view);
if (parent == null) {
throw new IllegalArgumentException("No suitable parent found from the given view. "
+ "Please provide a valid 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;
}
先看第一行代码final ViewGroup parent = findSuitableParent(view);
通过传递过来目标view,寻找合适的
父控件,来加入snackbar。看方法里面实现找到合适的父容器
private static ViewGroup findSuitableParent(View view) {
ViewGroup fallback = null;
//循环获取
do {
if (view instanceof CoordinatorLayout) {
//如果这里传过来是协调布局,想当然容器viewgroup了,直接返回
// 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.
//DecorView是PhoneWindow类的内部类 相当于DecorView是一个FrameLayout,对布局进行装饰的作用。然后会根据theme去选择系统中的布局文件,将布局文件通过inflate转化为view,加入到DecorView中;所以这里直接寻找android.R.id.content的控件,找到就是一个适合的容器布局
这些布局文件中都包含一个id为content的FrameLayout,
return (ViewGroup) view;
} else {
// It's not the content view but we'll use it as our fallback
fallback = (ViewGroup) view;
}
}
if (view != null) {
// 否则,我们会循环并寻找上视图层级并试图找到一个父类
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;
}
内容很好理解,就是寻找一个合适的父类而已。
往下看下面代码:
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
final SnackbarContentLayout content =
(SnackbarContentLayout) inflater.inflate(
R.layout.design_layout_snackbar_include, parent, false);
更好理解了,将snackbar的布局加入到合适的父控件里面。
再往下就是
final Snackbar snackbar = new Snackbar(parent, content, content);
snackbar.setText(text);
snackbar.setDuration(duration);
return snackbar;
返回一个Snackbar的实例,设置标题文字,显示时间参数。
snackbar的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2015 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<view
xmlns:android="http://schemas.android.com/apk/res/android"
class="android.support.design.internal.SnackbarContentLayout"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom">
<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:minWidth="48dp"
android:visibility="gone"
android:textColor="?attr/colorAccent"
style="?attr/borderlessButtonStyle"/>
</view>
发现里面控件相对于父控件属性为android:layout_gravity=”bottom”,所以显示在底部
发现button默认为隐藏掉的,只有设置setAction才会显示。
既然知道了布局文件及其id,就可以自定义其他属性,比如设置背景颜色之类的
View snackbarView = snackbar.getView();
((Button) snackbarView.findViewById(R.id.snackbar_action)).setBackground(null);
snackbarView.setBackgroundColor(Color.parseColor("#87CEFA"));
简单分析到此