android BottomSheetDialog新控件解析實現知乎評論列表效果(實例代碼)
BottomSheetDialog使用解析
Android Support Library 23.2里的 Design Support Library新加了一個Bottom Sheets控件,Bottom Sheets顧名思義就是底部操作控件,用于在屏幕底部創建一個可滑動關閉的視圖,可以替代對話框和菜單。其中包含BottomSheets、BottomSheetDialog和BottomSheetDialogFragment三種可以使用。其中應用較多的控件是BottomSheetDialog,主要運用在界面底部分享列表,評論列表等,最近在知乎評論列表界面看到知乎運用到了這個效果,所有在這里詳細介紹一下該控件的使用,以及簡單實現知乎評論列表功能。本文實現效果如下:
首先我們想要使用BottomSheets相關控件,需要先在build.gradle中添加design依賴,本文中使用的是:
compile ’com.android.support:design:25.3.0’
BottomSheetDialog可以替代大多數網格顯示和列表展示的dialog和popupwindow,默認寬度撐滿,并且在BottomSheetDialog 區域中向下滑動也讓對話框消失。
接下來創建BottomSheetDialog的布局文件dialog_bottomsheet.xml,布局文件如下:
<?xml version='1.0' encoding='utf-8'?><RelativeLayout xmlns:android='http://schemas.android.com/apk/res/android' android:layout_width='match_parent' android:layout_height='wrap_content'> <RelativeLayout android: android:layout_width='match_parent' android:layout_height='45dp' android:background='@drawable/dialog_bottomsheet_shape'> <ImageView android: android:layout_width='45dp' android:layout_height='45dp' android:layout_centerVertical='true' android:layout_marginLeft='5dp' android:padding='5dp' android:src='http://www.aoyou183.cn/bcjs/@drawable/img_close' /> <TextView android:layout_width='wrap_content' android:layout_height='wrap_content' android:layout_centerVertical='true' android:layout_marginLeft='10dp' android:layout_toRightOf='@id/dialog_bottomsheet_iv_close' android:text='評論' android:textColor='#333' android:textSize='16sp' /> </RelativeLayout> <android.support.v7.widget.RecyclerView android: android:layout_width='match_parent' android:layout_height='match_parent' android:layout_below='@id/dialog_bottomsheet_rl_title' android:background='#fff' /></RelativeLayout>
布局文件中,主要包含一個RecyclerView和一個頭布局。
然后,我們在Activity界面添加BottomSheetDailog初始化方法,
private void showSheetDialog() { View view = View.inflate(BottomSheetDialogActivity.this, R.layout.dialog_bottomsheet, null); iv_dialog_close = (ImageView) view.findViewById(R.id.dialog_bottomsheet_iv_close); rv_dialog_lists = (RecyclerView) view.findViewById(R.id.dialog_bottomsheet_rv_lists); iv_dialog_close.setOnClickListener(this); bottomSheetAdapter = new BottomSheetAdapter(BottomSheetDialogActivity.this, list_strs); rv_dialog_lists.setHasFixedSize(true); rv_dialog_lists.setLayoutManager(new LinearLayoutManager(BottomSheetDialogActivity.this)); rv_dialog_lists.setItemAnimator(new DefaultItemAnimator()); rv_dialog_lists.setAdapter(bottomSheetAdapter); bottomSheetDialog = new BottomSheetDialog(BottomSheetDialogActivity.this, R.style.dialog); bottomSheetDialog.setContentView(view); }
在改方法中,我們首先獲取BottomSheetDialog的布局文件,獲取該布局文件中相關控件,通過創建模擬列表數據,為RecyclerView添加適配器
for (int i=0; i<20; i++) { list_strs.add('評論' + i); }
通過如下代碼,創建BottomSheetDialog對象
bottomSheetDialog = new BottomSheetDialog(BottomSheetDialogActivity.this, R.style.dialog);bottomSheetDialog.setContentView(view);
至此,我們即可以通過調用
bottomSheetDialog.show();
方法來查看BottomSheetDialog顯示效果
使用過程中出現的問題
當我們向下滑動BottomSheetDialog隱藏Dialog后,無法用bottomSheetDialog.show()再次打開,為什么呢?我們先看下源碼的實現:
@Overridepublic void setContentView(View view, ViewGroup.LayoutParams params) { super.setContentView(wrapInBottomSheet(0, view, params));}private View wrapInBottomSheet(int layoutResId, View view, ViewGroup.LayoutParams params) { final CoordinatorLayout coordinator = View.inflate(getContext(),R.layout...., null); FrameLayout bottomSheet = (FrameLayout) coordinator.findViewById(R.id.design_bottom_sheet); BottomSheetBehavior.from(bottomSheet).setBottomSheetCallback(mBottomSheetCallback); ... return coordinator;}private BottomSheetCallback mBottomSheetCallback = new BottomSheetCallback() { @Override public void onStateChanged(@NonNull View bottomSheet, int newState) { if (newState == BottomSheetBehavior.STATE_HIDDEN) { dismiss(); //關鍵代碼 } } @Override public void onSlide(@NonNull View bottomSheet, float slideOffset) { }};
通過源碼文件我們可以看出,系統的BottomSheetDialog是基于BottomSheetBehavior封裝的,當我們滑動隱藏了BottomSheetBehavior中的View后,內部是設置了BottomSheetBehavior的狀態為STATE_HIDDEN,接著它替我們關閉了Dialog,所以我們再次調用show()的時候Dialog沒法再此打開狀態為HIDE的Dialog了。 查看了源文件,我們就通過復寫BottomSheetCallback的回調方法,來實現我們的效果,這里就引入了BottomSheetBehavior,下面先介紹BottomSheetBehavior的使用。
BottomSheetBehavior的作用
根據官方Api,BottomSheetBehavior有一個靜態方法BottomSheetBehavior.from(View),會返回這個View引用的BottomSheetBehavior,這個方法會檢查這個View是否是CoordinatorLayout的子View,如果是就會得到這個View的Behavior。通過BottomSheetBehavior,我們可以通過setPeekHeight(int height)設置dialog的顯示高度,通過setBottomSheetCallback(callback)實現BottomSheetDialog的狀態監聽。其中,在BottomSheetCallback回調方法中,onStateChanged監聽狀態的改變,onSlide是拖拽的回調,onStateChanged可以監聽到的回調一共有五種:
STATE_HIDDEN: 隱藏狀態。默認是false,可通過app:behavior_hideable屬性設置。 STATE_COLLAPSED: 折疊關閉狀態。可通過app:behavior_peekHeight來設置顯示的高度,peekHeight默認是0。 STATE_DRAGGING: 被拖拽狀態 STATE_SETTLING: 拖拽松開之后到達終點位置(collapsed or expanded)前的狀態。 STATE_EXPANDED: 完全展開的狀態。那么如何獲取到BottomSheetDialog的BottomSheetBehavior呢?
第一種:在BottomSheetDialog調用setContentView方法之后,調用
BottomSheetBehavior mDialogBehavior = BottomSheetBehavior.from((View) mContentView.getParent());
第二種:在BottomSheetDialog調用setContentView方法之后,調用
final FrameLayout frameLayout = (FrameLayout) dialog.findViewById(android.support.design.R.id.design_bottom_sheet);frameLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { frameLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this); BottomSheetBehavior behavior = BottomSheetBehavior.from(frameLayout); //調用behavior相關方法 ... frameLayout.forceLayout();}
通過上面的介紹,修改上文中的showSheetDialog()用于解決上文中出現的問題,代碼如下:
private void showSheetDialog() { View view = View.inflate(BottomSheetDialogActivity.this, R.layout.dialog_bottomsheet, null); iv_dialog_close = (ImageView) view.findViewById(R.id.dialog_bottomsheet_iv_close); rv_dialog_lists = (RecyclerView) view.findViewById(R.id.dialog_bottomsheet_rv_lists); iv_dialog_close.setOnClickListener(this); bottomSheetAdapter = new BottomSheetAdapter(BottomSheetDialogActivity.this, list_strs); rv_dialog_lists.setHasFixedSize(true); rv_dialog_lists.setLayoutManager(new LinearLayoutManager(BottomSheetDialogActivity.this)); rv_dialog_lists.setItemAnimator(new DefaultItemAnimator()); rv_dialog_lists.setAdapter(bottomSheetAdapter); bottomSheetDialog = new BottomSheetDialog(BottomSheetDialogActivity.this, R.style.dialog); bottomSheetDialog.setContentView(view); mDialogBehavior = BottomSheetBehavior.from((View) view.getParent()); mDialogBehavior.setPeekHeight(getWindowHeight()); mDialogBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { @Override public void onStateChanged(@NonNull View bottomSheet, int newState) { if (newState == BottomSheetBehavior.STATE_HIDDEN) { bottomSheetDialog.dismiss(); mDialogBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); } } @Override public void onSlide(@NonNull View bottomSheet, float slideOffset) { } }); }
在監聽到用戶滑動關閉BottomSheetDialog后,我們把BottomSheetBehavior的狀態設置為BottomSheetBehavior.STATE_COLLAPSED,也就是半個打開狀態(BottomSheetBehavior.STATE_EXPANDED為全打開),至此就解決了調用show()方法無法正常打開的問題。同時我們通過設置setPeekHeight和BottomSheetDialog的透明主題來實現知乎評論列表的效果。 在values/styles.xml文件中添加透明主題
<style name='dialog' parent='@android:style/Theme.Dialog'> <item name='android:windowFrame'>@null</item> <item name='android:windowIsFloating'>true</item> <item name='android:windowIsTranslucent'>true</item> <item name='android:windowNoTitle'>true</item> <item name='android:background'>@android:color/transparent</item> <item name='android:windowBackground'>@android:color/transparent</item> <item name='android:backgroundDimEnabled'>true</item> <item name='android:backgroundDimAmount'>0.6</item> </style>
最后附上Activity界面完整代碼如下:
public class BottomSheetDialogActivity extends AppCompatActivity implements View.OnClickListener { private Button bt_start; private ImageView iv_dialog_close; private RecyclerView rv_dialog_lists; private BottomSheetAdapter bottomSheetAdapter; private BottomSheetDialog bottomSheetDialog; private BottomSheetBehavior mDialogBehavior; private List<String> list_strs; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_bottom_sheet_dialog); list_strs = new ArrayList<>(); initView(); showSheetDialog(); } private void initView() { bt_start = (Button) findViewById(R.id.main_bt_start); for (int i=0; i<20; i++) { list_strs.add('評論' + i); } bt_start.setOnClickListener(this); } private void showSheetDialog() { View view = View.inflate(BottomSheetDialogActivity.this, R.layout.dialog_bottomsheet, null); iv_dialog_close = (ImageView) view.findViewById(R.id.dialog_bottomsheet_iv_close); rv_dialog_lists = (RecyclerView) view.findViewById(R.id.dialog_bottomsheet_rv_lists); iv_dialog_close.setOnClickListener(this); bottomSheetAdapter = new BottomSheetAdapter(BottomSheetDialogActivity.this, list_strs); rv_dialog_lists.setHasFixedSize(true); rv_dialog_lists.setLayoutManager(new LinearLayoutManager(BottomSheetDialogActivity.this)); rv_dialog_lists.setItemAnimator(new DefaultItemAnimator()); rv_dialog_lists.setAdapter(bottomSheetAdapter); bottomSheetDialog = new BottomSheetDialog(BottomSheetDialogActivity.this, R.style.dialog); bottomSheetDialog.setContentView(view); mDialogBehavior = BottomSheetBehavior.from((View) view.getParent()); mDialogBehavior.setPeekHeight(getWindowHeight()); mDialogBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { @Override public void onStateChanged(@NonNull View bottomSheet, int newState) { if (newState == BottomSheetBehavior.STATE_HIDDEN) { bottomSheetDialog.dismiss(); mDialogBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); } } @Override public void onSlide(@NonNull View bottomSheet, float slideOffset) { } }); } private int getWindowHeight() { Resources res = BottomSheetDialogActivity.this.getResources(); DisplayMetrics displayMetrics = res.getDisplayMetrics(); return displayMetrics.heightPixels; } @Override public void onClick(View v) { switch (v.getId()) { case R.id.main_bt_start: if (bottomSheetDialog != null) { bottomSheetDialog.show(); } break; case R.id.dialog_bottomsheet_iv_close: if (bottomSheetDialog != null) { bottomSheetDialog.dismiss(); } break; } }}
到此這篇關于android BottomSheetDialog新控件解析實現知乎評論列表效果的文章就介紹到這了,更多相關android 知乎評論列表內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!
相關文章: