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:id="@+id/dialog_bottomsheet_rl_title"
 android:layout_width="match_parent"
 android:layout_height="45dp"
 android:background="@drawable/dialog_bottomsheet_shape">

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

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

</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()再次打开,为什么呢?我们先看下源码的实现:

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

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

(0)

相关推荐

  • Android BottomSheetDialog实现底部对话框的示例

    Android 6.0新控件 BottomSheetDialog | 底部对话框 介绍及使用详情 extends AppCompatDialog Base class for Dialogs styled as a bottom sheet 基于Dialog样式的一个底部对话框 先看看效果 对于弹出的内容完全由自己来掌控,想实现什么样子就实现什么样子,很灵活 使用方法 BottomSheetDialog来自design兼容包,使用需要添加依赖.android studio 添加依赖如下: dep

  • Android 仿抖音的评论列表的UI和效果的实现代码

    抖音是一款音乐创意短视频社交软件,是一个专注年轻人的15秒音乐短视频社区.用户可以通过这款软件选择歌曲,拍摄15秒的音乐短视频,形成自己的作品.此App已在Android各大应用商店和APP Store均有上线. 在design包里面 有一个 BottomSheetDialogFragment 这个Fragment,他已经帮我们处理好了手势,所以实现起来很简单.下面是代码: public class ItemListDialogFragment extends BottomSheetDialog

  • Android实现朋友圈评论回复列表

    本文实例为大家分享了Android实现朋友圈评论回复列表的具体代码,供大家参考,具体内容如下 Android实现朋友圈评论回复列表 Android实现朋友圈点赞列表 Android实现朋友圈多图显示功能 正文 还是老流程,先来看一下效果图: 然后是主要实现代码: CommentsView public class CommentsView extends LinearLayout { private Context mContext; private List<CommentsBean> mD

  • Android 之BottomsheetDialogFragment仿抖音评论底部弹出对话框效果(实例代码)

    实现的效果图: 自定义Fragment继承BottomSheetDialogFragment 重写它的三个方法: onCreateDialog() onCreateView() onStart() 他们的执行顺序是从上到下 import android.app.Dialog; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.ColorDrawable;

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

    BottomSheetDialog使用解析 Android Support Library 23.2里的 Design Support Library新加了一个Bottom Sheets控件,Bottom Sheets顾名思义就是底部操作控件,用于在屏幕底部创建一个可滑动关闭的视图,可以替代对话框和菜单.其中包含BottomSheets.BottomSheetDialog和BottomSheetDialogFragment三种可以使用.其中应用较多的控件是BottomSheetDialog,主要

  • Android实现ListView控件的多选和全选功能实例

    本文实例讲述了Android实现ListView控件的多选和全选功能.分享给大家供大家参考,具体如下: 主程序代码 MainActivity.Java package yy.test; import java.util.ArrayList; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.view.Menu; import android.vi

  • Android自定义View控件实现多种水波纹涟漪扩散效果

    效果图 实现思路 这个效果实现起来并不难,重要的是思路 此View满足了多种水波纹涟漪扩散效果,这要求它能满足很多的变化 根据上面的样式,可以看出此View需要满足以下变化 圆圈从中心可循环向外扩散 圆圈之间的扩散间距可以改变 可控制扩散圆的渐变度 圆圈可以是线条样式或者实心样式 圆圈扩散的速度可以控制 适配圆圈不同大小下的扩散效果 具体实现 创建自定义属性 首先为View创建自定义的xml属性 在工程的values目录下新建attrs.xml文件 <declare-styleable name

  • Android自定义view系列之99.99%实现QQ侧滑删除效果实例代码详解

    首先声明本文是基于GitHub上"baoyongzhang"的SwipeMenuListView修改而来,该项目地址: https://github.com/baoyongzhang/SwipeMenuListView 可以说这个侧滑删除效果是我见过效果最好且比较灵活的项目,没有之一!!! 但是在使用它之前需要给大家提两点注意事项: 1,该项目支持Gradle dependence,但是目前作者提供的依赖地址对应的项目不是最新的项目,依赖过后的代码与demo中使用的不一致,会提示没有B

  • Android APT 实现控件注入框架SqInject的示例

    作者 大家好,我叫小鑫,也可以叫我蜡笔小鑫

  • Android 自定义Button控件实现按钮点击变色

    效果图如下所示: 一.shape 样式:(在drawable新建-->new-->Drawable resource file 在父级标签selector添加Item ) <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item and

  • 漂亮的Android音乐歌词控件 仿网易云音乐滑动效果

    前言: 项目有个音乐播发器功能,实现音乐在线播放,同时需要带有歌词显示功能.网上也找过,在github找到勉强能用的控件,只是效果还是差强人意,不是特别好.于是趁有空的时间,参考了网上的部分demo,自己也写了个歌词控件. 只要demo可以拉到最底部. 一.歌词控件效果. 目前的歌词控件效果如下: 主要效果有以下: 1.实现自动滑动切换到下一句. 2.实现滑动歌词切换播放时间. 3.实现拖动歌词时仿网易云音乐显示时间线,将要选择的歌词颜色变化. 4.音乐进度跳转时,歌词跳转可以滑动切换. 二.歌

  • Android 使用SwipeRefreshLayout控件仿抖音做的视频下拉刷新效果

    SwipeRefreshLayout(这个控件),我先跟大家介绍一下这个控件: 一.SwipeRefreshLayout简单介绍 •先看以下官方文档,已有了很详细的描述了. 官方文档说明 •这里我再大概解释一下: •在竖直滑动时想要刷新页面可以用SwipeRefreshLayout来实现.它通过设置OnRefreshListener来监听界面的滑动从而实现刷新.也可以通过一些方法来设置SwipeRefreshLayout是否可以刷新.如:setRefreshing(true),展开刷新动画. s

  • Android5.0新控件实例详解

    谷歌在推出Android5.0的同时推出了一些新控件,Android5.0中最常用的新控件有下面5种. 1. CardView(卡片视图) CardView顾名思义是卡片视图,它继承FrameLayout.它是一个带圆角的背景和阴影FrameLayout.CardView被包装为一种布局,并且经常在ListView和RecyclerView的Item布局中,作为容器使用. CardView的使用非常简单: <android.support.v7.widget.CardView android:l

  • 详解Android 多级联动控件实现思路讨论

    最近有一个需求是选择多级联动数据,数据级别不固定,可能是五级,可能是两级,具体看用户等级. 所以就需要一个多级联动选择控件 ,在网上一番搜索或找到了这个控件, Android-PickerView 这个控件在三级以内的的联动都没有问题,但是最多只能到三级. 我在原有的基础上做了一些扩展,主要是添加了两个 picker MultiWheelPickerView 可以根据数据动态生成多个滚轮,不再局限于两个三个选项 DynamicWheelPickerView 也是动态生成,但可以一级一级的加载数据

随机推荐