Material Design系列之Behavior实现支付密码d窗和商品属性选择效果

Material Design系列之Behavior实现支付密码d窗和商品属性选择效果,第1张

概述今天的效果在支付宝、淘宝、京东等电商App中很常见。比如支付宝输入密码d窗、商城下单时选择商品属性时,从下面浮动上来一个PopupWindow,那么今天就带大家用Behavior来实现这两个效果,结果你会发现简直只需要一行

今天的效果在支付宝、淘宝、京东等电商App中很常见。比如支付宝输入密码d窗、商城下单时选择商品属性时,从下面浮动上来一个PopupWindow,那么今天就带大家用Behavior来实现这两个效果,结果你会发现简直只需要一行代码。

总结下现在用的APP:
1. 仿支付宝d出的输入支付密码窗口。
2. 仿淘宝/天猫d出商品属性选择框。
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

效果预览

引文

在我的技术群里有小伙伴们讨论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;@OverrIDeprotected 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); // 拿到这个tab_layout对应的BottomSheetBehavior 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就明白了它的用法了,不就是展开和隐藏起来了麽?所以我们判断这个状态,如果是隐藏就显示,如果是显示就隐藏:

@OverrIDepublic 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的隐藏和显示也就讲玩了,接下来我们来看看支付宝淘宝的下方d窗如何实现。

BottomSheetDialog怎么玩(商城下单商品属性选择d窗)

这个类的发现也是在AndroID官网搜索BottomSheetBehavior时发现的,一看到BottomSheetDialog后心中狂喜,后来经过我验证,它显示的效果和我猜想的一模一样啊,既然是个Dialog,那么用法应该和普通Dialog没啥去区别了吧。

然后我就顺势new了一个BottomSheetDialog:

private BottomSheetDialog mBottomSheetDialog;@OverrIDeprotected 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出来的时候发现它显示了一半,嗯这个效果确实不错,这样就达到了我们最初说的支付宝密码d窗和淘宝/天猫商品属性选择。我们滑动的时候如果下面有内容它就会EXPANDED,如果是一个普通的VIEw(非RecyclerVIEw、nestedScrollVIEw)将不会继续往上滑动,下面的内容会继续跟着出来,但是同样可以向下滑动隐藏,也可以调用dismiss和close关闭。

BottomSheetDialog的神坑

作为一个有情怀的程序员,这里把我踩过的坑和解决方案跟大家分享一下。

我发现当这个Dilaog打开再关闭后,无法用Dialog.show()再次打开,为什么呢?

我去阅读了一下BottomSheetDialog源代码,发现了如下代码:

 @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,所以我们再次调用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://xiazai.jb51.net/201609/yuanma/AndroidBehavior(jb51.net).rar

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的Material Design系列之Behavior实现支付密码d窗和商品属性选择效果全部内容,希望文章能够帮你解决Material Design系列之Behavior实现支付密码d窗和商品属性选择效果所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1148137.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存