BottomSheet
参考: https://github.com/itdais/MaterialDesignDing
注意: behavior必须在
CoordinatorLayout
中使用
BottomSheet
属性 | 说明 |
---|---|
app:behavior_hideable=”true” | 下滑可以隐藏 |
app:behavior_peekHeight=”50dp” | 默认显示的高度 |
app:layout_behavior=”@string/bottom_sheet_behavior”` | 设置behavior |
behavior所在的控件必须在CoordinatorLayout中
behavior所在的控件必须设置behavior属性app:layout_behavior="@string/bottom_sheet_behavior"
效果图
xml设置
只需要我们给可以scroll
的控件设置layout_behavior
+behavior_peekHeight
即可,如果我们希望下拉可以隐藏,那么必须设置app:behavior_hideable="true"
(默认是false)。这样就我们在滑动时就会是sheet
全部显示或显示一部分(高度peekHeight
)。
在NestedScrollView
中定义Button
,点击后调用
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
是无效的。
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
android:id="@+id/activity_main"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.cqc.supportlibary01.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="打开bottom sheet"
android:textAllCaps="false"/>
<Button
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="打开bottom sheet dialog"
android:textAllCaps="false"/>
<Button
android:id="@+id/btn3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="fragment"
android:textAllCaps="false"/>
</LinearLayout>
<!--app:behavior_peekHeight="50dp"-->
<!--@string/bottom_sheet_behavior-->
<!--app:behavior_hideable="true" 默认是false-->
<android.support.v4.widget.NestedScrollView
android:id="@+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:behavior_hideable="true"
app:behavior_peekHeight="50dp"
app:layout_behavior="@string/bottom_sheet_behavior"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/colorPrimary"
android:gravity="center"
android:text="可以上拉,可以下拉"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@mipmap/banner"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
behavior的回调
一般用不到
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
// newState:1 2 3 4 5
LogUtil.d(TAG, "newState=" + newState);
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
//slideOffset: (0,1]
//LogUtil.d(TAG,"slideOffset="+slideOffset);
}
});
怎么获取behavior?
nestedScrollView = (NestedScrollView) findViewById(R.id.nestedScrollView);
behavior = BottomSheetBehavior.from(nestedScrollView);
怎么使用Button控制sheet的显示与隐藏?
通常情况下,我们希望可以通过Button
控制sheet
的显示与隐藏,需要先获取behavior
,在Button
的点击事件中判断behavior
的state
。
只有设置了下面3个属性和值,
app:behavior_hideable="true"
app:behavior_peekHeight="50dp"
app:layout_behavior="@string/bottom_sheet_behavior"
下面的方法才有效:
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int state = behavior.getState();
if (state == BottomSheetBehavior.STATE_EXPANDED) {
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
} else {
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
}
});
state
共有5种。
BottomSheetDialog
其实就是一个dialog
,只不过它的xml
布局使用了behavior
。首先创建BottomSheetDialog
对象,调用show()
方法显示,调用dismiss()
隐藏
效果图
BottomSheetDialog的xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--NestedScrollView跟ScrollView一样,里面只放1个layout-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@color/colorAccent"
android:gravity="center"
android:text="AAAAA"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@mipmap/banner"/>
//下面放了多个 TextView + ImageView,便于观看效果
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
代码
dialog创建和显示:
BottomSheetDialog dialog = new BottomSheetDialog(MainActivity.this);
//View view = getLayoutInflater().inflate(R.layout.dialog_bottom_sheet, null);
//View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.dialog_bottom_sheet,null);
// dialog.setContentView(view);
dialog.setContentView(R.layout.dialog_bottom_sheet);
dialog.show();
隐藏dialog:
dialog.dismiss();
BottomSheetDialogFragment
- 创建类继承
BottomSheetDialogFragment
- 重写
onCreateDialog()
方法 - 创建
BottomSheetDialog
对象,并将其作为返回 - 重写
`方法,设置
Fragment可见时,
sheet的
state`
设置布局有2种方法,第一种:在onCreateDialog(...)
获取dialog,给dialog.setContentView(…)。第二种:在onCreateView(...)
中给Fragment设置布局
效果图
代码设置
xml和BottomSheetDialog
一样,
public class MyBottomSheetDialogFragment extends BottomSheetDialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// BottomSheetDialog dialog = new BottomSheetDialog(getActivity());
BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
dialog.setContentView(R.layout.dialog_bottom_sheet);
return dialog;
}
}
如果我们需要Fragment可见时,该sheet全部显示,俺么需要设置behavior的state.
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// BottomSheetDialog dialog = new BottomSheetDialog(getActivity());
// dialog.setContentView(R.layout.dialog_bottom_sheet);
BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
View view = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_bottom_sheet, null);
dialog.setContentView(view);
behavior = BottomSheetBehavior.from((View) view.getParent());
return dialog;
}
@Override
public void onStart() {
super.onStart();
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);//默认显示STATE_COLLAPSED
}
在onCreateView()
填充布局:
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.dialog_bottom_sheet, container, false);
}
如何禁止上下滑动,只可以使用代码控制显示与隐藏?
参考:如何禁止使用bottomsheetdialogfragment拖动?
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
bottomSheetDialog.setContentView(R.layout.dialog_frag_2);
try {
Field mBehaviorField = bottomSheetDialog.getClass().getDeclaredField("mBehavior");
mBehaviorField.setAccessible(true);
final BottomSheetBehavior behavior = (BottomSheetBehavior) mBehaviorField.get(bottomSheetDialog);
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_DRAGGING) {
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return bottomSheetDialog;
}
源码
https://git.oschina.net/AndroidUI/BottomSheet
CoordinatorTabLayout
github:https://github.com/hugeterry/CoordinatorTabLayout
这个不是Android原生的,是github上的开源控件。用法比较简单,下面的是复制的README.md,自己写的Demo:https://git.oschina.net/libraryDemo/CoordinatorTablayout01
CoordinatorTabLayout是一个自定义组合控件,可快速实现TabLayout与CoordinatorLayout相结合的样式
继承至CoordinatorLayout, 在该组件下面使用了CollapsingToolbarLayout包含TabLayout
用法
Step 1
在gradle文件中加入下面的依赖:
dependencies {
compile 'cn.hugeterry.coordinatortablayout:coordinatortablayout:1.0.6'
}
Step 2
在你自己的XML中使用它:
<cn.hugeterry.coordinatortablayout.CoordinatorTabLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinatortablayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/vp"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</cn.hugeterry.coordinatortablayout.CoordinatorTabLayout>
Step 3
在使用它的界面添加以下设置:
1.setTitle(String title)
:设置Toolbar标题
2.setupWithViewPager(ViewPager viewPager)
:将写好的viewpager设置到该控件当中
3.setImageArray(int[] imageArray)
:根据tab数量设置好头部的图片数组,并传到该控件当中
//构建写好的fragment加入到viewpager中
initFragments();
initViewPager();
//头部的图片数组
mImageArray = new int[]{
R.mipmap.bg_android,
R.mipmap.bg_ios,
R.mipmap.bg_js,
R.mipmap.bg_other};
mCoordinatorTabLayout = (CoordinatorTabLayout) findViewById(R.id.coordinatortablayout);
mCoordinatorTabLayout.setTitle("Demo")
.setImageArray(mImageArray)
.setupWithViewPager(mViewPager);
大功告成,好好享用吧
更多功能
添加折叠后的颜色变化效果
setImageArray(int[] imageArray, int[] colorArray)
:如果你想要有头部折叠后的颜色变化,可将之前设置好的图片数组以及根据tab数量设置的颜色数组传到该控件当中
mColorArray = new int[]{
android.R.color.holo_blue_light,
android.R.color.holo_red_light,
android.R.color.holo_orange_light,
android.R.color.holo_green_light};
mCoordinatorTabLayout.setImageArray(mImageArray, mColorArray);
```
###添加返回
`setBackEnable(Boolean canBack)`:设置Toolbar的返回按钮
@Override
protected void onCreate(Bundle savedInstanceState) {
...
mCoordinatorTabLayout.setBackEnable(true);
...
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
}
return super.onOptionsItemSelected(item);
}
###通过网络加载头部图片
选择用网络来加载图片。可实现以下接口:
`setLoadHeaderImagesListener(LoadHeaderImagesListener loadHeaderImagesListener)`:设置获取头部图片的操作
@Override
protected void onCreate(Bundle savedInstanceState) {
...
mCoordinatorTabLayout.setTitle("Demo")
.setBackEnable(true)
.setContentScrimColorArray(mColorArray)
.setLoadHeaderImagesListener(new LoadHeaderImagesListener() {
@Override
public void loadHeaderImages(ImageView imageView, TabLayout.Tab tab) {
switch (tab.getPosition()) {
case 0:
//加载图片
break;
...
}
}
})
.setupWithViewPager(mViewPager);
}
你也可以选择用Glide/Picasso等网络框架来实现,[代码例子](https://github.com/hugeterry/CoordinatorTabLayout/blob/master/sample/src/main/java/cn/hugeterry/coordinatortablayoutdemo/LoadHeaderImageFromNetworkActivity.java)
###获取子控件
`getActionBar()`:获取该组件中的ActionBar<br/>
`getTabLayout()`:获取该组件中的TabLayout<br/>
`getImageView()`:获取该组件中的ImageView
[更多代码](https://github.com/hugeterry/CoordinatorTabLayout/blob/master/sample/src/main/java/cn/hugeterry/coordinatortablayoutdemo/MainActivity.java)
##属性
- `app:contentScrim` -> color.默认为?attr/colorPrimary
- `app:tabIndicatorColor` -> color.
- `app:tabTextColor` -> color.
# FloatingActionButton相关的开源库 #
## 第一个:makovkastar/FloatingActionButton ##
[gihub:makovkastar/FloatingActionButton](https://github.com/makovkastar/FloatingActionButton)
### 实现的功能 ###
当`AbsListView`、`RecyclerView`、`ScrollView` 向上滚动的时候,Fab消失;
当向下滚动的时候,FAB出现。
**注意:**FAB的父布局必须是`FrameLayout`,`RelativeLayout`都无效。
###**gradle** ###
`dependencies {
compile 'com.melnykov:floatingactionbutton:1.3.0'
}`
### XML ###