Snackbar getAnchorView() 与父视图

Posted

技术标签:

【中文标题】Snackbar getAnchorView() 与父视图【英文标题】:Snackbar getAnchorView() vs. parent view 【发布时间】:2020-06-24 14:07:47 【问题描述】:

我已阅读 Snackbar documentation

但不确定小吃店的 parentTarget(父视图)和 anchoredView 之间的区别。

如有错误请指正:

1) parent view 是小吃店从该视图沿着 hierchy 视图向上查找 suitable parent view

2) 合适的父视图不是anchoredView。

当一个人设置parentView(ctor 要求)和anchoredView 时会发生什么?

小吃店会在哪里营业?

【问题讨论】:

你自己试过了吗? 【参考方案1】:

SnackBar 的父视图将告诉您哪个容器或布局将 应绘制小吃吧。通常,snackbar 会寻找协调员 布局作为您作为参数传递的视图的父级,如果它 找不到一个它会采取活动内容布局 (android.R.id.content) Framelayout 作为父级。

代码取自SnackBar

@Nullable
    private static ViewGroup findSuitableParent(View view) 
        ViewGroup fallback = null;
        do 
            if (view instanceof CoordinatorLayout) 
                // We've found a CoordinatorLayout, use it
                return (ViewGroup) view;
             else if (view instanceof FrameLayout) 
                if (view.getId() == android.R.id.content) 
                    // If we've hit the decor content view, then we didn't find a CoL in the
                    // hierarchy, so use it.
                    return (ViewGroup) view;
                 else 
                    // It's not the content view but we'll use it as our fallback
                    fallback = (ViewGroup) view;
                
            
            if (view != null) 
                // Else, we will loop and crawl up the view hierarchy and try to find a parent
                final ViewParent parent = view.getParent();
                view = parent instanceof View ? (View) parent : null;
            
         while (view != null);
        // If we reach here then we didn't find a CoL or a suitable content view so we'll fallback
        return fallback;
    

BaseTransientBottomBar 的锚点会告诉你在哪个视图之上 将显示小吃吧。

代码取自BaseTransientBottomBar

private int calculateBottomMarginForAnchorView() 
    if (anchorView == null) 
      return 0;
    

    int[] anchorViewLocation = new int[2];
    anchorView.getLocationOnScreen(anchorViewLocation);
    int anchorViewAbsoluteYTop = anchorViewLocation[1];

    int[] targetParentLocation = new int[2];
    targetParent.getLocationOnScreen(targetParentLocation);
    int targetParentAbsoluteYBottom = targetParentLocation[1] + targetParent.getHeight();

    return targetParentAbsoluteYBottom - anchorViewAbsoluteYTop;
  

...

/** Sets the view the @link BaseTransientBottomBar should be anchored above. */
  @NonNull
  public B setAnchorView(@Nullable View anchorView) 
    this.anchorView = anchorView;
    return (B) this;
  

  /**
   * Sets the id of the view the @link BaseTransientBottomBar should be anchored above.
   *
   * @throws IllegalArgumentException if the anchor view is not found.
   */
  @NonNull
  public B setAnchorView(@IdRes int anchorViewId) 
    this.anchorView = targetParent.findViewById(anchorViewId);
    if (this.anchorView == null) 
      throw new IllegalArgumentException("Unable to find anchor view with id: " + anchorViewId);
    
    return (B) this;
  

你可以在这里找到 SnackBar 的源代码Material SnackBar 和 BaseTransientBottomBar 这里BaseTransientBottomBar

【讨论】:

谢谢,你能用一个例子解释一下两者的区别吗? on top of which view snackbar will be shownon which container or layout will the snackbar should be drawn.

以上是关于Snackbar getAnchorView() 与父视图的主要内容,如果未能解决你的问题,请参考以下文章