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"
效果圖
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICO2gDOwYjMxEDMyEDM3EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
xml設定
隻需要我們給可以
scroll
的控件設定
layout_behavior
+
behavior_peekHeight
即可,如果我們希望下拉可以隐藏,那麼必須設定
app:behavior_hideable="true"
(預設是false)。這樣就我們在滑動時就會是
sheet
全部顯示或顯示一部分(高度
peekHeight
)。
在
NestedScrollView
中定義
Button
,點選後調用
是無效的。
<?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"-->
<[email protected]/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"
下面的方法才有效:
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:
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()
填充布局:
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 ###