Android Snackbar简单解析

著论准过秦,作赋拟子虚。这篇文章主要讲述Android Snackbar简单解析相关的知识,希望能为你提供帮助。
偶然间发现android中有Snackbar类,还是有点意思,类似于toast。与toast相比,最明显的区别是:Snackbar只能在屏幕底部显示。其他用法基本与toast相似。
先来张效果图吧,静态图:

Android Snackbar简单解析

文章图片




大概的用法呢?:

[html] view plain copy
  1. Snackbar.make(btn,"Snackbar  测试",Snackbar.LENGTH_INDEFINITE).show();    
  2. //记得引入库:   
  3. compile  ‘com.android.support:design:xx.xx.xx‘   

接下来我简略翻译下部分源码:
[html] view plain copy
  1. 包名   
  2. package  android.support.design.widget;    
  3.    
  4. /**   
  5.   *  Snackbars为用户操作提供一个轻量级的反馈,   
  6.   *  他在屏幕底部显示一个简略的消息,   
  7.   *  snackbars出现在屏幕上的所有其他要素之上,   
  8.   *  同一时间只会显示一个scankbar,   
  9.   *  在一定时间后他会自动消失,   
  10.   *  如果传递给scankbar的父容器是CoordinatorLayout,则用户可右滑关闭他。   
  11.   *  Snackbars可以包含一个动作,当你调用setAction(CharSequence,            android.view.View.OnClickListener)方法时(设置一个文本,并提供一个关于该文本的点击事件。如果设置了,则文本显示在scankbar的内部右侧)   
  12.   *  如果你讲关注snackbar的显示或隐藏事件,你可以设置回调函数监控addCallback(BaseCallback)   
  13.   */   
  14. public  final  class  Snackbar  extends  BaseTransientBottomBar< Snackbar>   {   
  15.    
  16.         /**   
  17.           *            无限期的显示一个Snackbar。意思也就是说这个Snackbar在被调用show()后显示,直到被调用关闭,或者有另一个被显示时才会关闭。   
  18.           *   
  19.           */   
  20.         public  static  final  int  LENGTH_INDEFINITE  =  BaseTransientBottomBar.LENGTH_INDEFINITE;    
  21.    
  22.         public  static  final  int  LENGTH_SHORT  =  BaseTransientBottomBar.LENGTH_SHORT;    
  23.    
  24.         public  static  final  int  LENGTH_LONG  =  BaseTransientBottomBar.LENGTH_LONG;    
  25.    
  26.         /**   
  27.           *  Snackbar的回调类.   
  28.           *   
  29.           *  @see  BaseTransientBottomBar#addCallback(BaseCallback)   
  30.           */   
  31.         public  static  class  Callback  extends  BaseCallback< Snackbar>   {   
  32.                 /**  表示Snackbar被滑动关闭.*/   
  33.                 public  static  final  int  DISMISS_EVENT_SWIPE  =  BaseCallback.DISMISS_EVENT_SWIPE;    
  34.                 /**  表示Snackbar被点击action后关闭.*/   
  35.                 public  static  final  int  DISMISS_EVENT_ACTION  =  BaseCallback.DISMISS_EVENT_ACTION;    
  36.                 /**  表示Snackbar显示到一定时间后关闭.*/   
  37.                 public  static  final  int  DISMISS_EVENT_TIMEOUT  =  BaseCallback.DISMISS_EVENT_TIMEOUT;    
  38.                 /**  表示Snackbar被调用dismiss()后关闭.*/   
  39.                 public  static  final  int  DISMISS_EVENT_MANUAL  =  BaseCallback.DISMISS_EVENT_MANUAL;    
  40.                 /**  表示Snackbar被一个新的Snackbar显示时关闭.*/   
  41.                 public  static  final  int  DISMISS_EVENT_CONSECUTIVE  =  BaseCallback.DISMISS_EVENT_CONSECUTIVE;    
  42.    
  43.                 @Override   
  44.                 public  void  onShown(Snackbar  sb)  {   
  45.                         //  Stub  implementation  to  make  API  check  happy.   
  46.                 }   
  47.    
  48.                 @Override   
  49.                 public  void  onDismissed(Snackbar  transientBottomBar,  @DismissEvent  int  event)  {   
  50.                         //  Stub  implementation  to  make  API  check  happy.   
  51.                 }   
  52.         }   
  53.    
  54.         private  BaseCallback< Snackbar>   mCallback;    
  55.    
  56.         private  Snackbar(ViewGroup  parent,  View  content,  ContentViewCallback  contentViewCallback)  {   
  57.                 super(parent,  content,  contentViewCallback);    
  58.         }   
  59.    
  60.         /**   
  61.           *  构造一个对象   
  62.           *   
  63.           *  Snackbar会尝试从给定的容器中向上寻找一个合适的父容器来托管他的view.  他的父容器会被认为是CoordinatorLayout或者是decorView.先找到了其中的某一个就结束查找。   
  64.           *  如果给定的容器中包含CoordinatorLayout布局,那么这个Scankbar将会获得更多的特性,比喻滑动删除scankbar.   
  65.           *   
  66.           *  @param  view          The  view  to  find  a  parent  from.   
  67.           *  @param  text          The  text  to  show.    Can  be  formatted  text.   
  68.           *  @param  duration  How  long  to  display  the  message.    Either  {@link  #LENGTH_SHORT}  or  {@link   
  69.           *                                  #LENGTH_LONG}   
  70.           */   
  71.         @NonNull   
  72.         public  static  Snackbar  make(@NonNull  View  view,  @NonNull  CharSequence  text,   
  73.                         @Duration  int  duration)  {   
  74.                 final  ViewGroup  parent  =  findSuitableParent(view);    
  75.                 if  (parent  ==  null)  {   
  76.                         throw  new  IllegalArgumentException("No  suitable  parent  found  from  the  given  view.  "   
  77.                                         +  "Please  provide  a  valid  view.");    
  78.                 }   
  79.    
  80.                 final  LayoutInflater  inflater  =  LayoutInflater.from(parent.getContext());    
  81.                 final  SnackbarContentLayout  content  =   
  82.                                 (SnackbarContentLayout)  inflater.inflate(   
  83.                                                 R.layout.design_layout_snackbar_include,  parent,  false);    
  84.                 final  Snackbar  snackbar  =  new  Snackbar(parent,  content,  content);    
  85.                 snackbar.setText(text);    
  86.                 snackbar.setDuration(duration);    
  87.                 return  snackbar;    
  88.         }   
  89.    
  90.         //查找合适的父容器   
  91.         private  static  ViewGroup  findSuitableParent(View  view)  {   
  92.                 ViewGroup  fallback  =  null;    
  93.                 do  {   
  94.                    
  95.                         if  (view  instanceof  CoordinatorLayout)  {//如果是CoordinatorLayout   
  96.                                 //  We‘ve  found  a  CoordinatorLayout,  use  it   
  97.                                 return  (ViewGroup)  view;    
  98.                         }  else  if  (view  instanceof  FrameLayout)  {   
  99.                                 if  (view.getId()  ==  android.R.id.content)  {   
  100.                                         //  If  we‘ve  hit  the  decor  content  view,  then  we  didn‘t  find  a  CoL  in  the   
  101.                                         //  hierarchy,  so  use  it.   
  102.                                         return  (ViewGroup)  view;    
  103.                                 }  else  {   
  104.                                         //  It‘s  not  the  content  view  but  we‘ll  use  it  as  our  fallback   
  105.                                         fallback  =  (ViewGroup)  view;    
  106.                                 }   
  107.                         }   
  108.    
  109.                         if  (view  !=  null)  {   
  110.                                 //  Else,  we  will  loop  and  crawl  up  the  view  hierarchy  and  try  to  find  a  parent   
  111.                                 final  ViewParent  parent  =  view.getParent();    
  112.                                 view  =  parent  instanceof  View  ?  (View)  parent  :  null;    
  113.                         }   
  114.                 }  while  (view  !=  null);    
  115.    
  116.                 //  If  we  reach  here  then  we  didn‘t  find  a  CoL  or  a  suitable  content  view  so  we‘ll  fallback   
  117.                 return  fallback;    
  118.         }   
  119.    
  120.         /**   
  121.           *  更新文本。看这意思,是可以给一个正在显示的scankbar更新文本?   
  122.           */   
  123.         @NonNull   
  124.         public  Snackbar  setText(@NonNull  CharSequence  message)  {   
  125.                 final  SnackbarContentLayout  contentLayout  =  (SnackbarContentLayout)  mView.getChildAt(0);    
  126.                 final  TextView  tv  =  contentLayout.getMessageView();    
  127.                 tv.setText(message);    
  128.                 return  this;    
  129.         }   
  130.    
  131.         /**   
  132.           *  设置一个带点击动作的文本,以及回调函数。   
  133.           *  点击文本的同时关闭scankbar。   
  134.           *  设置了文本则显示,并设置事件。如果没有设置,则隐藏。看来是已有的布局了   
  135.           *  @param  text          Text  to  display  for  the  action   
  136.           *  @param  listener  callback  to  be  invoked  when  the  action  is  clicked   
  137.           */   
  138.         @NonNull   
  139.         public  Snackbar  setAction(CharSequence  text,  final  View.OnClickListener  listener)  {   
  140.                 final  SnackbarContentLayout  contentLayout  =  (SnackbarContentLayout)  mView.getChildAt(0);    
  141.                 final  TextView  tv  =  contentLayout.getActionView();    
  142.    
  143.                 if  (TextUtils.isEmpty(text)  ||  listener  ==  null)  {   
  144.                         tv.setVisibility(View.GONE);    
  145.                         tv.setOnClickListener(null);    
  146.                 }  else  {   
  147.                         tv.setVisibility(View.VISIBLE);    
  148.                         tv.setText(text);    
  149.                         tv.setOnClickListener(new  View.OnClickListener()  {   
  150.                                 @Override   
  151.                                 public  void  onClick(View  view)  {   
  152.                                         listener.onClick(view);    
  153.                                         //  Now  dismiss  the  Snackbar   
  154.                                         dispatchDismiss(BaseCallback.DISMISS_EVENT_ACTION);    
  155.                                 }   
  156.                         });    
  157.                 }   
  158.                 return  this;    
  159.         }   
  160.    
  161.         /**   
  162.           *  设置点击动作的文本颜色   
  163.           */   
  164.         @NonNull   
  165.         public  Snackbar  setActionTextColor(ColorStateList  colors)  {   
  166.                 final  SnackbarContentLayout  contentLayout  =  (SnackbarContentLayout)  mView.getChildAt(0);    
  167.                 final  TextView  tv  =  contentLayout.getActionView();    
  168.                 tv.setTextColor(colors);    
  169.                 return  this;    
  170.         }   
  171.    
  172.         /**   
  173.           *  设置回调函数,来监控scankbar的显示与隐藏动作.     
  174.           *  什么?这个方法过时了?   
  175.           *  请使用addCallback(BaseCallback)和removeCallback(BaseCallback)函数.   
  176.           *   
  177.           *  @param  callback  Callback  to  notify  when  transient  bottom  bar  events  occur.   
  178.           *  @deprecated  Use  {@link  #addCallback(BaseCallback)}   
  179.           *  @see  Callback   
  180.           *  @see  #addCallback(BaseCallback)   
  181.           *  @see  #removeCallback(BaseCallback)   
  182.           */   
  183.         @Deprecated   
  184.         @NonNull   
  185.         public  Snackbar  setCallback(Callback  callback)  {   
  186.                 //  The  logic  in  this  method  emulates  what  we  had  before  support  for  multiple   
  187.                 //  registered  callbacks.   
  188.                 if  (mCallback  !=  null)  {   
  189.                         removeCallback(mCallback);    
  190.                 }   
  191.                 if  (callback  !=  null)  {   
  192.                         addCallback(callback);    
  193.                 }   
  194.                 //  Update  the  deprecated  field  so  that  we  can  remove  the  passed  callback  the  next   
  195.                 //  time  we‘re  called   
  196.                 mCallback  =  callback;    
  197.                 return  this;    
  198.         }   
  199.    
  200.         ...   
  201. }   


搜嘎,简略的读下源码后发现这个类很简单,那么更奇葩的用法来了:

[html] view plain copy
  1. @Override   
  2. public  void  onClick(View  v)  {   
  3.         Snackbar  sb  =  Snackbar.make(v,"aa",Snackbar.LENGTH_LONG).setAction("是吗?",  new  View.OnClickListener()  {   
  4.                 @Override   
  5.                 public  void  onClick(View  v)  {   
  6.                         //点击了"是吗?"字符串操作   
  7.                 }   
  8.         }).setActionTextColor(Color.RED).setText("aa是不够的").addCallback(new  BaseTransientBottomBar.BaseCallback< Snackbar> ()  {   
  9.                 @Override   
  10.                 public  void  onDismissed(Snackbar  transientBottomBar,  int  event)  {   
  11.                         super.onDismissed(transientBottomBar,  event);    
  12.                         Log.d("MainActivity","onDismissed");    
  13.                 }   
  14.    
  15.                 @Override   
  16.                 public  void  onShown(Snackbar  transientBottomBar)  {   
  17.                         super.onShown(transientBottomBar);    
  18.                         Log.d("MainActivity","onShown");    
  19.                 }   
  20.         });    
  21.         sb.show();    
  22.         //sb.isShown();    
  23.         //sb.dismiss();    
  24.    
  25. }   




注意看,Snackbar sb = make(v,"aa",......
第一个参数我给的v,就是当前点击的按钮,什么情况?
源码中说了,他会从这个view起想上查找一个合适的父容器,直到找到CoordinatorLayout或者decorView。先找到了其中的某一个就结束查找。如果找到了CoordinatorLayout,则可以有右滑删除功能哦。


如果想设置显示的内容,和整个背景色,也很简单。自己添加布局就可以了,跟toast一样,没多大意义不说了。







【Android Snackbar简单解析】这么简单,不贴demo了。动手练习。


















    推荐阅读