热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

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

BottomSheetDialog是一个自定义的从底部滑入的对话框,这篇文章主要介绍了androidBottomSheetDialog新控件解析实现知乎评论列表效果,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

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,布局文件如下:

<&#63;xml version="1.0" encoding="utf-8"&#63;>


 

 

 

 

 

布局文件中,主要包含一个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文件中添加透明主题


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


推荐阅读
  • Android 九宫格布局详解及实现:人人网应用示例
    本文深入探讨了人人网Android应用中独特的九宫格布局设计,解析其背后的GridView实现原理,并提供详细的代码示例。这种布局方式不仅美观大方,而且在现代Android应用中较为少见,值得开发者借鉴。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • 国内BI工具迎战国际巨头Tableau,稳步崛起
    尽管商业智能(BI)工具在中国的普及程度尚不及国际市场,但近年来,随着本土企业的持续创新和市场推广,国内主流BI工具正逐渐崭露头角。面对国际品牌如Tableau的强大竞争,国内BI工具通过不断优化产品和技术,赢得了越来越多用户的认可。 ... [详细]
  • 本文探讨了 RESTful API 和传统接口之间的关键差异,解释了为什么 RESTful API 在设计和实现上具有独特的优势。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • Python自动化处理:从Word文档提取内容并生成带水印的PDF
    本文介绍如何利用Python实现从特定网站下载Word文档,去除水印并添加自定义水印,最终将文档转换为PDF格式。该方法适用于批量处理和自动化需求。 ... [详细]
  • 在当前众多持久层框架中,MyBatis(前身为iBatis)凭借其轻量级、易用性和对SQL的直接支持,成为许多开发者的首选。本文将详细探讨MyBatis的核心概念、设计理念及其优势。 ... [详细]
  • 将Web服务部署到Tomcat
    本文介绍了如何在JDeveloper 12c中创建一个Java项目,并将其打包为Web服务,然后部署到Tomcat服务器。内容涵盖从项目创建、编写Web服务代码、配置相关XML文件到最终的本地部署和验证。 ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
  • 本文介绍如何在 Unity 的 XML 配置文件中,将参数传递给自定义生命周期管理器的构造函数。我们将详细探讨 CustomLifetimeManager 类的实现及其配置方法。 ... [详细]
  • 本文详细介绍了 Java 中 org.apache.xmlbeans.SchemaType 类的 getBaseEnumType() 方法,提供了多个代码示例,并解释了其在不同场景下的使用方法。 ... [详细]
  • 本文详细介绍了如何解决MyBatis中常见的BindingException错误,提供了多种排查和修复方法,确保Mapper接口与XML文件的正确配置。 ... [详细]
author-avatar
红颜内
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有