android 评论控件,android BottomSheetDialog新控件解析实现知乎评论列表效果(实例代码)...

本文详细介绍BottomSheetDialog控件的使用方法,包括其布局配置、状态管理及常见问题解决方案。通过实例演示如何实现类似知乎评论列表的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

BottomSheetDialog使用解析

Android Support Library 23.2里的 Design Support Library新加了一个Bottom Sheets控件,Bottom Sheets顾名思义就是底部操作控件,用于在屏幕底部创建一个可滑动关闭的视图,可以替代对话框和菜单。其中包含BottomSheets、BottomSheetDialog和BottomSheetDialogFragment三种可以使用。其中应用较多的控件是BottomSheetDialog,主要运用在界面底部分享列表,评论列表等,最近在知乎评论列表界面看到知乎运用到了这个效果,所有在这里详细介绍一下该控件的使用,以及简单实现知乎评论列表功能。本文实现效果如下:

14bf24c00c88f6c51b9464f03685a60f.gif

首先我们想要使用BottomSheets相关控件,需要先在build.gradle中添加design依赖,本文中使用的是:

compile 'com.android.support:design:25.3.0'

BottomSheetDialog可以替代大多数网格显示和列表展示的dialog和popupwindow,默认宽度撑满,并且在BottomSheetDialog 区域中向下滑动也让对话框消失。

接下来创建BottomSheetDialog的布局文件dialog_bottomsheet.xml,布局文件如下:

android:layout_width="match_parent"

android:layout_height="wrap_content">

android:id="@+id/dialog_bottomsheet_rl_title"

android:layout_width="match_parent"

android:layout_height="45dp"

android:background="@drawable/dialog_bottomsheet_shape">

android:id="@+id/dialog_bottomsheet_iv_close"

android:layout_width="45dp"

android:layout_height="45dp"

android:layout_centerVertical="true"

android:layout_marginLeft="5dp"

android:padding="5dp"

android:src="@drawable/img_close" />

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" />

android:id="@+id/dialog_bottomsheet_rv_lists"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_below="@id/dialog_bottomsheet_rl_title"

android:background="#fff" />

布局文件中,主要包含一个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()再次打开,为什么呢?我们先看下源码的实现:

@Override

public 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文件中添加透明主题

@null

true

true

true

@android:color/transparent

@android:color/transparent

true

0.6

最后附上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 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 知乎评论列表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值