Android BottomSheet效果的兩種實(shí)現(xiàn)方式
本文介紹了Android BottomSheet效果的兩種實(shí)現(xiàn)方式,分享給大家,具體如下:
BottomSheet效果
BottomSheet的效果是指從屏幕底部向上滑的效果,是MaterialDesign風(fēng)格的一種,視覺效果如下:
BottomSheet效果
實(shí)現(xiàn)這種效果有幾種不同的方式,如果是在一個固定的頁面上添加這種效果,可以在該頁面布局中添加BoottomSheet相關(guān)的控件。如果是作為通用控件來提供給不同頁面使用,則可以使用BottomSheetDialog實(shí)現(xiàn),本文將對兩種方法進(jìn)行講解,其中會講到一些使用上的細(xì)節(jié),處理不好這些細(xì)節(jié),會出現(xiàn)非常怪異的效果。
單頁面添加BottomSheet效果
首先引入依賴包:
compile 'com.android.support:design:27.1.1'
頁面布局如下:
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:id="@+id/customActionWebView" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="文本一"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="文本二"/> </LinearLayout> <android.support.v4.widget.NestedScrollView android:id="@+id/nested_scroll_view" android:layout_width="match_parent" android:layout_height="match_parent" app:behavior_hideable="true" app:behavior_peekHeight="150dp" android:layout_gravity="bottom" app:layout_behavior="@string/bottom_sheet_behavior"> <WebView android:id="@+id/web_view" android:layout_width="match_parent" android:layout_height="match_parent"> </WebView> </android.support.v4.widget.NestedScrollView> </android.support.design.widget.CoordinatorLayout>
根布局需要使用CoordinatorLayout,同時在其直接子布局——這里是NestedScrollView——里添加behavior app:layout_behavior = "@string/bottom_sheet_behavior" 。很多文章說指定behavior的控件必須是NestedScrollView,這是錯誤的,實(shí)際上任何view或viewgroup都可以。該behavior配合CoordinateLayout就可以實(shí)現(xiàn)behavior所在控件的上滑效果。如果需要上滑的布局展示的時候先漏出一部分,如上面視頻所示,可以通過設(shè)置 app:behavior_peekHeight 實(shí)現(xiàn),它用來指定漏出的高度。
在代碼部分,首先獲取NestedScrollView的behavior,然后通過behavior控制底部卡片什么時候彈出,同時會有一些狀態(tài)回調(diào)函數(shù)可供調(diào)用。
public class BrowserActivity extends AppCompatActivity { private NestedScrollView nestedScrollView; private BottomSheetBehavior behavior; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.browser_layout); nestedScrollView = (NestedScrollView) findViewById(R.id.nested_scroll_view); behavior = BottomSheetBehavior.from(nestedScrollView); behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { @Override public void onStateChanged(@NonNull View bottomSheet, int newState) { //這里是bottomSheet 狀態(tài)的改變 } @Override public void onSlide(@NonNull View bottomSheet, float slideOffset) { //這里是拖拽中的回調(diào),根據(jù)slideOffset可以做一些動畫 } }); } public void showBottomSheet() { behavior.setState(BottomSheetBehavior.STATE_EXPANDED); } }
通過這種方式可以在特定的頁面添加底部上滑的效果。
BottomSheetDialog實(shí)現(xiàn)通用效果
BottomSheetDialog是BottomSheet效果實(shí)現(xiàn)的一種更加通用的方法,比如我們需要在不同的頁面實(shí)現(xiàn)長按文本彈出卡片列表效果,下面給出實(shí)現(xiàn)。
我們集成BottomSheetDialog實(shí)現(xiàn)自定義的Dialog,其布局如下:
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <view class="com.example.trio.tensordemo.CustomBottomSheetDialogForWebView$NestViewEmbeddedListView" android:id="@+id/card_list_view" android:layout_width="match_parent" android:layout_height="match_parent" android:divider="@color/transparent" android:scrollbars="none" android:dividerHeight="15dp" android:layout_margin="20dp"> </view> </LinearLayout> </android.support.v4.widget.NestedScrollView>
注意,這里最外層布局需要是 NestedScrollView ,而 不能是CoordinateLayout ,因?yàn)锽ottomSheetDialog本身已經(jīng)有個CoordinateLayout根布局,它會把你的布局文件包裹起來,如果你在自己的布局里把最外層布局寫成CoordinateLayout,會導(dǎo)致底部上滑的卡片,在下滑消失后屏幕依舊變暗的問題,這是因?yàn)檎麄€布局變成了兩個CoordinateLayout嵌套,下滑的時候里面的CoordinateLayout滑出屏幕,但外層的CoordinateLayout仍然在展示。通過查閱BottomSheetDialog源碼可以看出,它是這樣包裹你的布局文件的:
public class BottomSheetDialog extends AppCompatDialog { ... @Override public void setContentView(@LayoutRes int layoutResId) { super.setContentView(wrapInBottomSheet(layoutResId, null, null)); } private View wrapInBottomSheet(int layoutResId, View view, ViewGroup.LayoutParams params) { final FrameLayout container = (FrameLayout) View.inflate(getContext(), R.layout.design_bottom_sheet_dialog, null); final CoordinatorLayout coordinator = (CoordinatorLayout) container.findViewById(R.id.coordinator); if (layoutResId != 0 && view == null) { view = getLayoutInflater().inflate(layoutResId, coordinator, false); } FrameLayout bottomSheet = (FrameLayout) coordinator.findViewById(R.id.design_bottom_sheet); mBehavior = BottomSheetBehavior.from(bottomSheet); mBehavior.setBottomSheetCallback(mBottomSheetCallback); mBehavior.setHideable(mCancelable); if (params == null) { bottomSheet.addView(view); } else { bottomSheet.addView(view, params); } // We treat the CoordinatorLayout as outside the dialog though it is technically inside coordinator.findViewById(R.id.touch_outside).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (mCancelable && isShowing() && shouldWindowCloseOnTouchOutside()) { cancel(); } } }); ... return container; } ... }
所以,BottomSheetDialog本身的布局實(shí)際如下:
BottomSheetDialog頁面布局
我們可以看到最外層是FrameLayout,里面有個CoordinateLayout,CoordinateLayout里面有個直接子布局FrameLayout,該CoordinateLayout指定了Behavior,最里面才是用戶自定義的布局,所以不應(yīng)該在自定義布局里再添加CoordinateLayout,也不應(yīng)該再次指定Behavior,直接擺放你的內(nèi)容就行。
我們的自定義布局如下:
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <view class="com.example.trio.tensordemo.CustomBottomSheetDialogForWebView$NestViewEmbeddedListView" android:id="@+id/card_list_view" android:layout_width="match_parent" android:layout_height="match_parent" android:divider="@color/transparent" android:scrollbars="none" android:dividerHeight="15dp" android:layout_margin="20dp"> </view> </LinearLayout> </android.support.v4.widget.NestedScrollView>
布局的核心是一個ListView,注意,由于ListView和behavior都需要處理滑動事件,所以直接使用ListView會導(dǎo)致滑動沖突,解決辦法是采用ScrollView嵌套ListView實(shí)現(xiàn),同時使用自定義的ListView將所有列表項(xiàng)展開。
自定義的NestViewEmbeddedListView如下:
public static class NestViewEmbeddedListView extends ListView { public NestViewEmbeddedListView(android.content.Context context, android.util.AttributeSet attrs){ super(context, attrs); } /** * 設(shè)置不滾動 */ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } }
自定義的BottomSheetDialog代碼如下:
public class CustomBottomSheetDialogForWebView extends BottomSheetDialog { private Context context; private NestViewEmbeddedListView listView; private NerResult nerResult; private CardListAdapter cardListAdapter = new CardListAdapter(); public CustomBottomSheetDialogForWebView(@NonNull Context context, NerResult nerResult) { super(context); this.context = context; this.nerResult = nerResult; createView(); } public void createView() { View bottomSheetView = getLayoutInflater().inflate(R.layout.webview_bottom_sheet_layout, null); setContentView(bottomSheetView); // 注意:這里要給layout的parent設(shè)置peekHeight,而不是在layout里給layout本身設(shè)置,下面設(shè)置背景色同理,坑爹!??! BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(((View) bottomSheetView.getParent())); bottomSheetBehavior.setPeekHeight(730); ((View) bottomSheetView.getParent()).setBackgroundColor(context.getResources().getColor(R.color.transparent)); listView = bottomSheetView.findViewById(R.id.card_list_view); cardListAdapter.setNerItems(nerResult); listView.setAdapter(cardListAdapter); } }
這里需要注意的就是,設(shè)置背景透明和獲取Behavior都是對自定義布局的父布局,也就是bottomSheetView.getParent()進(jìn)行。最終的效果就是下面的效果:
BottomSheet效果
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android超詳細(xì)講解組件AdapterView的使用
AdapterView組件是一組重要的組件,AdapterView本身是一個抽象基類,它派生的子類在用法上十分相似,從AdapterView派生出的三個子類:AdsListView、AdsSpinner、AdapterViewAnimator,這3個子類依然是抽象的,實(shí)際運(yùn)用時需要它們的子類2022-03-03Android studio 3.0上進(jìn)行多渠道打包遇到的問題小結(jié)(超簡潔版)
這篇文章主要介紹了Android studio 3.0上進(jìn)行多渠道打包遇到的問題小結(jié)(超簡潔版),非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-11-11詳解android 視頻圖片混合輪播實(shí)現(xiàn)
這篇文章主要介紹了android 視頻圖片混合輪播實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05Android連接服務(wù)器端的Socket的實(shí)例代碼
這篇文章主要介紹了Android連接服務(wù)器端的Socket的實(shí)例代碼,需要的朋友可以參考下2017-05-05Android利用Theme自定義Activity間的切換動畫
這篇文章主要為大家詳細(xì)介紹了Android利用Theme自定義Activity間的切換動畫,感興趣的小伙伴們可以參考一下2016-09-09Android基礎(chǔ)之startActivityForResult()的用法詳解
這篇文章主要給大家介紹了Android中startActivityForResult()的用法,文中給出了詳細(xì)的介紹與示例代碼,相信對大家的理解和學(xué)習(xí)具有一定參考借鑒價值,有需要的朋友們下面來一起看看吧。2017-01-01Android基于MLKit實(shí)現(xiàn)條形碼掃碼的代碼示例
這篇文章將借助開源庫?MLKit?實(shí)現(xiàn)條形碼掃描,對于商品條形碼也可以很好地識別成功,該庫的使用內(nèi)容非常豐富,除了條碼識別,還有文字識別、圖像標(biāo)記、人臉檢測等等,本文篇文章就只介紹最基本的條形碼掃描使用,需要的朋友可以參考下2023-08-08Android實(shí)現(xiàn)志愿者系統(tǒng)詳細(xì)步驟與代碼
這篇文章主要介紹了Android實(shí)現(xiàn)志愿者系統(tǒng),本系統(tǒng)采用MVC架構(gòu)設(shè)計,SQLite數(shù)據(jù)表有用戶表、成員表和活動表,有十多個Activity頁面。打開應(yīng)用,進(jìn)入歡迎界面,3s后跳轉(zhuǎn)登錄界面,用戶先注冊賬號,登錄成功后進(jìn)入主界面2023-02-02