版权声明:转载必须注明本文转自严振杰的博客:
http://blog.csdn.net/yanzhenjie1003
今天的效果在支付宝、淘宝、京东等电商App中很常见。比如支付宝输入密码弹窗、商城下单时选择商品属性时,从下面浮动上来一个
PopupWindow
,那么今天就带大家用
Behavior
来实现这两个效果,结果你会发现简直只需要一行代码。
总结下现在用的APP:
1. 仿支付宝弹出的输入支付密码窗口。
2. 仿淘宝/天猫弹出商品属性选择框。
3. 知乎首页上下滑动隐藏ToolBar和NavigationBar。
4. …
系列博客:
1.
Material Design系列,Behavior之BottomSheetBehavior与BottomSheetDialog
2.
Material Design系列,Behavior之SwipeDismissBehavior
3.
Material Design系列,自定义Behavior之上滑显示返回顶部按钮
4.
Material Design系列,自定义Behavior实现Android知乎首页
5.
Material Design系列,自定义Behavior支持所有 View
源码下载:
http://download.csdn.net/detail/yanzhenjie1003/9578770
,推荐先阅读博客理解原理。
在我的技术群里有小伙伴们讨论Behavior,我也去玩了玩,我也对Behavior写了系列博客。选中
Behavior
然后
ctrol + t
后发现
Behavior
的一个实现类:
BottomSheetBehavior
,我就到
Android官网上翻了下资料
,一翻就发现了惊喜啊,下面就把这些惊喜介绍给大家。
更多文章请Google/百度搜索我名字:严振杰,排名第一的就是我。
BottomSheetBehavior怎么玩(知乎Bottom隐藏和显示)
玩这个东西,首先
Behavior
作为
CoordinatorLayout
的子View的
LayoutParams
(原因看后文解释),所以
CoordinatorLayout
是万万不能少的,先来亮出整个布局:
<android.support.design.widget.CoordinatorLayout 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">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/tab_layout"
android:gravity="center"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<Button
android:id="@+id/btn_bottom_sheet_control"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="sheet 显示/隐藏" />
</LinearLayout>
<LinearLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:layout_alignParentBottom="true"
android:background="@android:color/holo_purple"
app:layout_behavior="@string/bottom_sheet_behavior">
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="第一" />
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="第二" />
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="第三" />
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="第四" />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
大概介绍下,页面上只能看到
Toolbar
和一个
Button
:
sheet 显示/隐藏
,然后
android:id="@+id/tab_layout"
这个布局是横向的,给它设置了
Behavior
:
app:layout_behavior="@string/bottom_sheet_behavior"
,经过测试发现,如果不给
tab_layout
设置
BottomSheetBehavior
,它会浮动在整个页面的顶部,并在
Toolbar
的下面。设置了
BottomSheetBehavior
它会被
BottomSheetBehavior
自动移动到页面底部外边,所以在页面上是看不到
android:id="@+id/tab_layout"
这个布局的。
页面画好了,难道它会自动开关吗,怎么去控制它的打开和关闭呢?那么我们就来看看这货的真实面貌,经过我看
Android
的官方api发现,
BottomSheetBehavior
这个货有一个静态方法
BottomSheetBehavior.from(View)
,会返回这个View引用的
BottomSheetBehavior
:
public static <V extends View> BottomSheetBehavior<V> from(V view) {
ViewGroup.LayoutParams params = view.getLayoutParams();
if (!(params instanceof CoordinatorLayout.LayoutParams)) {
throw new Exception("The view is not a child of CoordinatorLayout");
CoordinatorLayout.Behavior behavior = params.getBehavior();
if (!(behavior instanceof BottomSheetBehavior)) {
throw new IllegalArgumentException("...");
return (BottomSheetBehavior<V>) behavior;
这个方法会检查这个View是否是CoordinatorLayout的子View,如果是才会去拿到这个View的Behavior,所以诸位也应该明白为什么我开头说Behavior作为CoordinatorLayout子View的LayoutParams了。
接下来我们看看拿到这个货后怎么用:
private BottomSheetBehavior mBottomSheetBehavior;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bsbehavior_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
findViewById(R.id.btn_bottom_sheet_control).setOnClickListener(onClickListener);
mBottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.tab_layout));
findViewById(R.id.btn_bottom_sheet_control).setOnClickListener(onClickListener);是给刚才说的页面中的Button设置了监听,我们用这个按钮来控制tab_layout的显示和隐藏。
我发现有一个方法可以获取到它所依附的View此时的状态:mBottomSheetBehavior.getState(),翻阅了源码后发现它的返回值有以下几种:
* The bottom sheet is dragging.
public static final int STATE_DRAGGING = 1;
* The bottom sheet is settling.
public static final int STATE_SETTLING = 2;
* The bottom sheet is expanded.
public static final int STATE_EXPANDED = 3;
* The bottom sheet is collapsed.
public static final int STATE_COLLAPSED = 4;
* The bottom sheet is hidden.
public static final int STATE_HIDDEN = 5;
当我看到STATE_EXPANDED和STATE_COLLAPSED就明白了它的用法了,不就是展开和隐藏起来了麽?所以我们判断这个状态,如果是隐藏就显示,如果是显示就隐藏:
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_bottom_sheet_control) {
if (mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED) {
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
} else if (mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED) {
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
到这里,知乎首页的Bottom的隐藏和显示也就讲玩了,接下来我们来看看支付宝淘宝的下方弹窗如何实现。
BottomSheetDialog怎么玩(商城下单商品属性选择弹窗)
这个类的发现也是在Android官网搜索BottomSheetBehavior时发现的,一看到BottomSheetDialog后心中狂喜,后来经过我验证,它显示的效果和我猜想的一模一样啊,既然是个Dialog,那么用法应该和普通Dialog没啥去区别了吧。
然后我就顺势new了一个BottomSheetDialog:
private BottomSheetDialog mBottomSheetDialog;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
createBottomSheetDialog();
private void createBottomSheetDialog() {
mBottomSheetDialog = new BottomSheetDialog(this);
View view = LayoutInflater.from(this).inflate(R.layout.dialog_bottom_sheet, null, false);
mBottomSheetDialog.setContentView(view);
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
recyclerView.setAdapter(adapter);
View里面是一个RecyclerView:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
然后用下面的代码去控制它的显示和隐藏。
if (mBottomSheetDialog.isShowing()) {
mBottomSheetDialog.dismiss();
} else {
mBottomSheetDialog.show();
当这个Dialog Show出来的时候发现它显示了一半,嗯这个效果确实不错,这样就达到了我们最初说的支付宝密码弹窗和淘宝/天猫商品属性选择。我们滑动的时候如果下面有内容它就会EXPANDED,如果是一个普通的View(非RecyclerView、NestedScrollView)将不会继续往上滑动,下面的内容会继续跟着出来,但是同样可以向下滑动隐藏,也可以调用dismiss和close关闭。
BottomSheetDialog的神坑
作为一个有情怀的程序员,这里把我踩过的坑和解决方案跟大家分享一下。
我发现当这个Dilaog打开再关闭后,无法用Dialog.show()再次打开,为什么呢?
我去阅读了一下BottomSheetDialog源代码,发现了如下代码:
@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,所以我们再次调用dialog.show()的时候Dialog没法再此打开状态为HIDE的dialog了。
这里就有个疑问了:
Google为啥没有提供我们自己设置BottomSheetCallback的接口呢?
没有关系,看了源码发现很简单,我们自己来实现,并且在监听到用户滑动关闭BottomSheetDialog后,我们把BottomSheetBehavior的状态设置为BottomSheetBehavior.STATE_COLLAPSED,也就是半个打开状态(BottomSheetBehavior.STATE_EXPANDED为全打开),根据源码我把设置的方法提供下:
private void setBehaviorCallback() {
View view = mBottomSheetDialog.getDelegate().findViewById(android.support.design.R.id.design_bottom_sheet);
final BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(view);
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
mBottomSheetDialog.dismiss();
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
这样就解决了BottomSheetDialog关闭后不能再次打开的问题了。
源码下载:http://download.csdn.net/detail/yanzhenjie1003/9578770
版权声明:转载必须注明本文转自严振杰的博客: http://blog.csdn.net/yanzhenjie1003
今天的效果在支付宝、淘宝、京东等电商App中很常见。比如支付宝输入密码弹窗、商城下单时选择商品属性时,从下面浮动上来一个`PopupWindow`,那么今天就带大家用`Behavior`来实现这两个效果,结果你会发现简直只需要一行代码。
val bottomSheetBehavior = BottomSheetBehavior.from(binding.rootBottomSheet)
bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
bottomSheetBehavior.skipCollapsed = true
bottomSheetBehavior.peekHeight = 0
bottomSh.
只需将下面的属性添加到要用作可锚定底页的View即可。
app:layout_behavior="com.trafi.anchorbottomsheetbehavior.AnchorBottomSheetBehavior"
在布局文件中,您可以像这样指定它。
< android xss=removed xss=removed>
<!-- background content -->
< FrameLayout
原文:https://blog.csdn.net/qjay_dev/article/details/51289267
本文使用的 com.android.support:design 版本为 23.3.0
BottomSheetBehavior
此类类似一个工具类,并不能在布局中使用,下面我们看看怎么实现我们效果图中的功能
layout
<FrameLayout
android:id="@+id/bottom_sheet"
andro.
很奇怪的问题,原因不明
我的bottomsheetbehavior这个下拉布局里面有2个子布局,其中一个子布局里面有recycleview,我发现会导致另外一个布局无法下拉(拉上去就下不来了),后面把recycleview换成listview就正常了,原因不明以后看看能否找到(在NearbyActivity)
bottomSheetbehavior的下拉布局里面的页面,如果布局发生了变
android:id="@+id/drawer_layout"
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:fitsSystemWindows=“true”
tools:openDrawer=“start”>
<include
layout="@layout/app_bar_main"
android:layout_width=“match_parent”
android:la
1. BottomSheetBehavior 简介
An interaction behavior plugin for a child view of CoordinatorLayout
to make it work as a bottom sheet.
链接:https://developer.android.google.cn/reference/android/support/desi...
实现这种效果有几种不同的方式,如果是在一个固定的页面上添加这种效果,可以在该页面布局中添加BoottomSheet相关的控件。如果是作为通用控件来提供给不同页面使用,则可以使用BottomSheetDialog实现,本文将对两种方法进行讲解,其中会讲到一些使用上的细节,处理不好这些细节,会出现非常怪异的效果。
单页面添加BottomSheet效果
首先引入依赖包:
需要的依赖:
compile ‘com.android.support:appcompat-v7:23.2.1’
compile ‘com.android.support:design:23.2.1’
效果图如下:
一直出现的问题是弹出窗口只显示部分,很烦人,浪费半个下午终于解决了
下面看代码:package com.example.mybottomdialog;import andr
本文使用的 com.android.support:design 版本为 23.3.0
效果图相关类BottomSheetBehavior此类类似一个工具类,并不能在布局中使用,下面我们看看怎么实现我们效果图中的功能layout<FrameLayout
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
Material Design,中文名:材料设计语言,是由Google推出的全新的设计语言,谷歌表示,这种设计语言旨在为手机、平板电脑、台式机和“其他平台”提供更一致、更广泛的“外观和感觉”。
目 的为不同平台”提供更一致、更广泛的“外观和感觉”适用平台手机、平板电脑、台式机等重要功能系统字体Roboto的升级版本等