AppBarLayout.ScrollingViewBehavior的数学如何运作?

GPa*_*ack 14 android android-coordinatorlayout android-appbarlayout

offsetChildAsNeeded在运行滚动更改时,我会在AppBarLayout.ScrollingViewBehavior中观察该方法的数学流程.

由于它是私有方法和私有方法mOffsetDelta,如何以编程方式监视它们?

(目前尚不清楚该方法是如何使用的offset.)

private void offsetChildAsNeeded(CoordinatorLayout parent, View child, View dependency) {
    final CoordinatorLayout.Behavior behavior =
                ((CoordinatorLayout.LayoutParams) dependency.getLayoutParams()).getBehavior();
    if (behavior instanceof Behavior) {
        // Offset the child, pinning it to the bottom the header-dependency, maintaining
        // any vertical gap, and overlap
        final Behavior ablBehavior = (Behavior) behavior;
        final int offset = ablBehavior.getTopBottomOffsetForScrollingSibling();
        ViewCompat.offsetTopAndBottom(child, (dependency.getBottom() - child.getTop())
                + ablBehavior.mOffsetDelta
                + getVerticalLayoutGap()
                - getOverlapPixelsForOffset(dependency));
        }
    }
Run Code Online (Sandbox Code Playgroud)

注意:欢迎,也可以接受回复那些解释数学的逻辑getTopBottomOffsetForScrollingSibling(),和(dependency.getBottom() - child.getTop()),和内容的细节mOffsetDelta

kri*_*son 4

您可以对这段代码进行逆向工程,但最终它是学术性的,因为我们这些凡人(即非 Google)程序员无法访问此处显示的值和方法。我猜他们认为我们实际可以使用的库越少,我们提交的错误报告就越少。叹。

但这里有一个简短的解释:

首先是代码行

    final int offset = ablBehavior.getTopBottomOffsetForScrollingSibling();
Run Code Online (Sandbox Code Playgroud)

似乎是早期修订版的残余,因为offset从未实际使用过。新的表达方式在更多情况下肯定会更准确一些。

ViewCompat.offsetTopAndBottom()不是集合(绝对)运算,而是加法(相对)运算。因此,让我们假设正常的逻辑,并考虑这种行为本质上是将滚动视图直接放在应用栏布局的下方。通常,应用栏的底部和滚动视图的顶部具有相同的值。由于应用栏布局(依赖项)已更改并且滚动视图(子视图)尚未更改,因此

    dependency.getBottom() - child.getTop()
Run Code Online (Sandbox Code Playgroud)

是子项的垂直偏移需要调整的相对量。

如果我对代码的阅读是正确的,那么mOffsetDelta只有在应用程序栏布局具有偏移插值器的情况下,应用程序栏布局的行为才为非零。通常,应用程序栏本身不会以视差方式移动,因此mOffsetDelta对于我们关心的几乎所有情况都是零。 getVerticalLayoutGapgetOverlapPixelsForOffset处理布局参数,例如overlapTop.

但事实证明,您可以通过执行以下操作来完成大部分工作,而无需在自己的行为子类中使用那些边缘情况:

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child,
                                          View dependency) {
        // get the bottom of the app bar layout
        int bottom = dependency.getBottom();

        // position the top of the scrolling view there
        return setTopAndBottomOffset(bottom);
    }
Run Code Online (Sandbox Code Playgroud)

我发现使用绝对偏移比相对偏移更容易一些。因此,实现滚动行为主要是确定依赖视图在哪里以及滚动视图需要基于该视图的位置。