CoordinatorLayout在另一个CoordinatorLayout里面

时间:2015-12-09 14:32:30

标签: android android-viewpager android-coordinatorlayout android-appbarlayout

$(window).load(function() { $(document).scrollTop(200); // set position in pixels (height of image) }); 位于另一个CorodinatorLayout内,以便滚动子视图也应该滚动父CoordinatorLayout

我的CoordinatorLayout coordinatorLayout包含不同的ViewPager FragmentScroll会隐藏tabLayout

我有另一个coordinatorLayout,其viewPager。这个fragment在父级片段ViewPager(父级Coordinator layout)中膨胀。

问题是onScrolling childViewpager中的子片段只反映在coordinator layout的{​​{1}}个fragment中,而不反映在我需要做的父coordinator layout中隐藏tablayout

结构是:

CoordinatorLayout(p) ->(tablayout(p) & ViewPager(p) -> CoordinatorLayout(c)  ->(tablayout(c) & ViewPAger(c) ->recyclerView(cc)))

p -> parent;

c -> child; cc -> child to child

如何滚动回收器视图将影响协调器布局,以便工具栏tablayout(p)将被隐藏。

7 个答案:

答案 0 :(得分:33)

我知道这是一个老问题。 但我搜索了很长时间,在一个片段中加入CoordinatorLayout,该片段位于另一个CoordinatorLayout中。

我稍微修改了dev.bmax的答案,调用两个协调器布局并调用两个布局的附加行为。

所以这是我的解决方案。

@SuppressWarnings("unused")
public class NestedCoordinatorLayout extends CoordinatorLayout implements NestedScrollingChild {

    private NestedScrollingChildHelper mChildHelper;

    public NestedCoordinatorLayout(Context context) {
        super(context);
        mChildHelper = new NestedScrollingChildHelper(this);
        setNestedScrollingEnabled(true);
    }

    public NestedCoordinatorLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        mChildHelper = new NestedScrollingChildHelper(this);
        setNestedScrollingEnabled(true);
    }

    public NestedCoordinatorLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mChildHelper = new NestedScrollingChildHelper(this);
        setNestedScrollingEnabled(true);
    }

    @Override
    public boolean onStartNestedScroll(View child, View target, int     nestedScrollAxes) {
        /* Enable the scrolling behavior of our own children */
        boolean tHandled = super.onStartNestedScroll(child, target, nestedScrollAxes);
        /* Enable the scrolling behavior of the parent's other children  */
        return startNestedScroll(nestedScrollAxes) || tHandled;
    }

    @Override
    public void onStopNestedScroll(View target) {
        /* Disable the scrolling behavior of our own children */
        super.onStopNestedScroll(target);
        /* Disable the scrolling behavior of the parent's other children  */
        stopNestedScroll();
    }

    @Override
    public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
        int[][] tConsumed = new int[2][2];
        super.onNestedPreScroll(target, dx, dy, tConsumed[0]);
        dispatchNestedPreScroll(dx, dy, tConsumed[1], null);
        consumed[0] = tConsumed[0][0] + tConsumed[1][0];
        consumed[1] = tConsumed[0][1] + tConsumed[1][1];
    }

    @Override
    public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
                           int dxUnconsumed, int dyUnconsumed) {
        super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
        dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, null);
    }

    @Override
    public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
        boolean tHandled = super.onNestedPreFling(target, velocityX, velocityY);
        return dispatchNestedPreFling(velocityX, velocityY) || tHandled;
    }

    @Override
    public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
        boolean tHandled = super.onNestedFling(target, velocityX, velocityY, consumed);
        return dispatchNestedFling(velocityX, velocityY, consumed) || tHandled;
    }

    @Override
    public void setNestedScrollingEnabled(boolean enabled) {
        mChildHelper.setNestedScrollingEnabled(enabled);
    }

    @Override
    public boolean isNestedScrollingEnabled() {
        return mChildHelper.isNestedScrollingEnabled();
    }

    @Override
    public boolean startNestedScroll(int axes) {
        return mChildHelper.startNestedScroll(axes);
    }

    @Override
    public void stopNestedScroll() {
        mChildHelper.stopNestedScroll();
    }

    @Override
    public boolean hasNestedScrollingParent() {
        return mChildHelper.hasNestedScrollingParent();
    }

    @Override
    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed,
                                    int dyUnconsumed, int[] offsetInWindow) {
        return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed,
                dyUnconsumed, offsetInWindow);
    }

    @Override
    public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
        return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
    }

    @Override
    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
        return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
    }

    @Override
    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
        return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
    }
}

答案 1 :(得分:9)

这是嵌套协调器布局的简单实现。


/**
 * This variation of CoordinatorLayout also serves as a nested scrolling child,
 * which supports passing nested scrolling operations to it's parent when it's
 * own nested scrolling is locked.
 */
public class NestedCoordinatorLayout extends CoordinatorLayout implements NestedScrollingChild {

    private NestedScrollingChildHelper mChildHelper;
    private volatile boolean mPassToParent;

    public NestedCoordinatorLayout(Context context) {
        super(context);
        mChildHelper = new NestedScrollingChildHelper(this);
        setNestedScrollingEnabled(true);
    }

    public NestedCoordinatorLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        mChildHelper = new NestedScrollingChildHelper(this);
        setNestedScrollingEnabled(true);
    }

    public NestedCoordinatorLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mChildHelper = new NestedScrollingChildHelper(this);
        setNestedScrollingEnabled(true);
    }

    /**
     * Locks the nested scrolling. Further scroll events will
     * be passed to the nested scrolling parent.
     */
    public void lockNestedScrolling() {
        mPassToParent = true;
    }

    /**
     * Unlocks the nested scrolling. Further scroll events will
     * be dispatched to this layout's own scrolling children.
     */
    public void unlockNestedScrolling() {
        mPassToParent = false;
    }

    /*
     * NestedScrollingParent implementation
     */

    @Override
    public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
        /* Enable the scrolling behavior of our own children */
        super.onStartNestedScroll(child, target, nestedScrollAxes);
        /* Enable the scrolling behavior of the parent's other children  */
        startNestedScroll(nestedScrollAxes);
        /* Start tracking the current scroll */
        return true;
    }

    @Override
    public void onStopNestedScroll(View target) {
        /* Disable the scrolling behavior of our own children */
        super.onStopNestedScroll(target);
        /* Disable the scrolling behavior of the parent's other children  */
        stopNestedScroll();
    }

    @Override
    public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
        if (mPassToParent) {
            dispatchNestedPreScroll(dx, dy, consumed, null);
        } else {
            super.onNestedPreScroll(target, dx, dy, consumed);
        }
    }

    @Override
    public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
                               int dxUnconsumed, int dyUnconsumed) {
        if (mPassToParent) {
            dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, null);
        } else {
            super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
        }
    }

    @Override
    public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
        if (mPassToParent) {
            return dispatchNestedPreFling(velocityX, velocityY);
        } else {
            return super.onNestedPreFling(target, velocityX, velocityY);
        }
    }

    @Override
    public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
        if (mPassToParent) {
            return dispatchNestedFling(velocityX, velocityY, consumed);
        } else {
            return super.onNestedFling(target, velocityX, velocityY, consumed);
        }
    }

    /*
     * NestedScrollingChild implementation
     */

    @Override
    public void setNestedScrollingEnabled(boolean enabled) {
        mChildHelper.setNestedScrollingEnabled(enabled);
    }

    @Override
    public boolean isNestedScrollingEnabled() {
        return mChildHelper.isNestedScrollingEnabled();
    }

    @Override
    public boolean startNestedScroll(int axes) {
        return mChildHelper.startNestedScroll(axes);
    }

    @Override
    public void stopNestedScroll() {
        mChildHelper.stopNestedScroll();
    }

    @Override
    public boolean hasNestedScrollingParent() {
        return mChildHelper.hasNestedScrollingParent();
    }

    @Override
    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed,
                                        int dyUnconsumed, int[] offsetInWindow) {
        return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed,
                dyUnconsumed, offsetInWindow);
    }

    @Override
    public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
        return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
    }

    @Override
    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
        return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
    }

    @Override
    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
        return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
    }
}

答案 2 :(得分:3)

我将其设为库,请参阅on GitHub

您只需在布局中使用<NestedScrollCoordinatorLayout>

答案 3 :(得分:3)

Kestlin版本的NestedCoordinator布局与基于@fabian answer的NestedCoordinatorLayouts的多点scrollFlags一起使用。

您将看到的行为是这样的:

enter image description here

NestedCoordinatorLayout实现


import android.content.Context
import android.util.AttributeSet
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.NestedScrollingChild
import androidx.core.view.NestedScrollingChildHelper

class NestedCoordinatorLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : CoordinatorLayout(context, attrs, defStyleAttr), NestedScrollingChild {

    private var mChildHelper: NestedScrollingChildHelper = NestedScrollingChildHelper(this)

    init {
        isNestedScrollingEnabled = true
    }

    override fun onNestedPreScroll(
        target: View,
        dx: Int,
        dy: Int,
        consumed: IntArray,
        type: Int
    ) {
        val tConsumed = Array(2) { IntArray(2) }
        super.onNestedPreScroll(target, dx, dy, consumed, type)
        dispatchNestedPreScroll(dx, dy, tConsumed[1], null)
        consumed[0] = tConsumed[0][0] + tConsumed[1][0]
        consumed[1] = tConsumed[0][1] + tConsumed[1][1]
    }

    override fun onNestedScroll(
        target: View,
        dxConsumed: Int,
        dyConsumed: Int,
        dxUnconsumed: Int,
        dyUnconsumed: Int,
        type: Int
    ) {
        super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type)
        dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, null)
    }

    override fun onStopNestedScroll(target: View, type: Int) {
        /* Disable the scrolling behavior of our own children */
        super.onStopNestedScroll(target, type)
        /* Disable the scrolling behavior of the parent's other children  */
        stopNestedScroll()
    }

    override fun onStartNestedScroll(child: View, target: View, nestedScrollAxes: Int, type: Int): Boolean {
        /* Enable the scrolling behavior of our own children */
        val tHandled = super.onStartNestedScroll(child, target, nestedScrollAxes, type)
        /* Enable the scrolling behavior of the parent's other children  */
        return startNestedScroll(nestedScrollAxes) || tHandled
    }

    override fun onStartNestedScroll(child: View, target: View, nestedScrollAxes: Int): Boolean {
        /* Enable the scrolling behavior of our own children */
        val tHandled = super.onStartNestedScroll(child, target, nestedScrollAxes)
        /* Enable the scrolling behavior of the parent's other children  */
        return startNestedScroll(nestedScrollAxes) || tHandled
    }

    override fun onStopNestedScroll(target: View) {
        /* Disable the scrolling behavior of our own children */
        super.onStopNestedScroll(target)
        /* Disable the scrolling behavior of the parent's other children  */
        stopNestedScroll()
    }

    override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray) {
        val tConsumed = Array(2) { IntArray(2) }
        super.onNestedPreScroll(target, dx, dy, tConsumed[0])
        dispatchNestedPreScroll(dx, dy, tConsumed[1], null)
        consumed[0] = tConsumed[0][0] + tConsumed[1][0]
        consumed[1] = tConsumed[0][1] + tConsumed[1][1]
    }

    override fun onNestedScroll(
        target: View,
        dxConsumed: Int,
        dyConsumed: Int,
        dxUnconsumed: Int,
        dyUnconsumed: Int
    ) {
        super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed)
        dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, null)
    }

    override fun onNestedPreFling(
        target: View,
        velocityX: Float,
        velocityY: Float
    ): Boolean {
        val tHandled = super.onNestedPreFling(target, velocityX, velocityY)
        return dispatchNestedPreFling(velocityX, velocityY) || tHandled
    }

    override fun onNestedFling(
        target: View,
        velocityX: Float,
        velocityY: Float,
        consumed: Boolean
    ): Boolean {
        val tHandled = super.onNestedFling(target, velocityX, velocityY, consumed)
        return dispatchNestedFling(velocityX, velocityY, consumed) || tHandled
    }

    override fun isNestedScrollingEnabled(): Boolean {
        return mChildHelper.isNestedScrollingEnabled
    }

    override fun setNestedScrollingEnabled(enabled: Boolean) {
        mChildHelper.isNestedScrollingEnabled = enabled
    }

    override fun startNestedScroll(axes: Int): Boolean {
        return mChildHelper.startNestedScroll(axes)
    }

    override fun stopNestedScroll() {
        mChildHelper.stopNestedScroll()
    }

    override fun hasNestedScrollingParent() = mChildHelper.hasNestedScrollingParent()

    override fun dispatchNestedScroll(
        dxConsumed: Int,
        dyConsumed: Int,
        dxUnconsumed: Int,
        dyUnconsumed: Int,
        offsetInWindow: IntArray?
    ): Boolean {
        return mChildHelper.dispatchNestedScroll(
            dxConsumed, dyConsumed, dxUnconsumed,
            dyUnconsumed, offsetInWindow
        )
    }

    override fun dispatchNestedPreScroll(
        dx: Int,
        dy: Int,
        consumed: IntArray?,
        offsetInWindow: IntArray?
    ): Boolean {
        return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)
    }

    override fun dispatchNestedFling(
        velocityX: Float,
        velocityY: Float,
        consumed: Boolean
    ): Boolean {
        return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed)
    }

    override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float): Boolean {
        return mChildHelper.dispatchNestedPreFling(velocityX, velocityY)
    }
}

您的 XML 文件实现类似于:


<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout>

    <com.google.android.material.appbar.AppBarLayout>

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/firstScrollingToolbar"
            app:layout_scrollFlags="snap|scroll|enterAlways"/>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <com.google.android.material.appbar.AppBarLayout>

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/tabLayout"
                app:layout_collapseMode="pin" />

        </com.google.android.material.appbar.AppBarLayout>

        <widget.NestedCoordinatorLayout
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <ViewPager
                android:id="@+id/chipsViewPager"
                app:layout_behavior="@string/appbar_scrolling_view_behavior" />

            <com.google.android.material.appbar.AppBarLayout>

                <androidx.appcompat.widget.Toolbar
                    android:id="@+id/switchToolbar"
                    app:layout_scrollFlags="enterAlways|snap|scroll">
                    <androidx.appcompat.widget.SwitchCompat />
                </androidx.appcompat.widget.Toolbar>

                <androidx.appcompat.widget.Toolbar
                    android:id="@+id/chipsTabLayout"
                    app:layout_collapseMode="pin"/>

            </com.google.android.material.appbar.AppBarLayout>

        </widget.NestedCoordinatorLayout>

    </androidx.coordinatorlayout.widget.CoordinatorLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

这是已实施布局层次结构的 Visual View

enter image description here

Video可以使您更好地了解Android Views层次结构的实际工作方式。

答案 4 :(得分:0)

不幸的是,CoordinatorLayout不支持此功能。

检查NestedScrollingChildHelper.startNestedScroll()CoordinatorLayout.onStartNestedScroll()中的代码,嵌套滚动事件是&#34;消费&#34;如果你内心的Behavior CoordinatorLayout之一消耗它,并且不会被进一步传播。

答案 5 :(得分:0)

您需要自定义您的CHILD CoordinatorLayout,让它实现NestedScrollingChild(ori coordinatorlayout没有实现它)并覆盖一些函数以启用将嵌套滚动事件调度到您的PARENT CoordinatorLayout。

答案 6 :(得分:0)

我在我的仓库ChildCoordinatorLayout中写了一个nestrefresh。 在此仓库中,我用ChildCoordinatorLayout包装了一个appbarlayout,还为具有拖动刷新行为的ChildCoordinatorLayout添加了拖动刷新。 然后dyUnConsumed给孩子父母。 这是代码:

class ChildCoordinatorLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0) : CoordinatorLayout(context, attrs, defStyleAttr), NestedScrollingChild2 {

private lateinit var childHelper: NestedScrollingChildHelper

init {
    init()
}

private fun init() {
    childHelper = NestedScrollingChildHelper(this)
    childHelper.isNestedScrollingEnabled = true
}

override fun setNestedScrollingEnabled(enabled: Boolean) {
    childHelper.isNestedScrollingEnabled = enabled
}

override fun isNestedScrollingEnabled(): Boolean {
    return childHelper.isNestedScrollingEnabled
}

override fun startNestedScroll(i: Int, i1: Int): Boolean {
    return childHelper.startNestedScroll(i, i1)
}

override fun stopNestedScroll(i: Int) {
    childHelper.stopNestedScroll(i)
}

override fun hasNestedScrollingParent(i: Int): Boolean {
    return childHelper.hasNestedScrollingParent()
}

override fun dispatchNestedScroll(i: Int, i1: Int, i2: Int, i3: Int, ints: IntArray?, i4: Int): Boolean {
    return childHelper.dispatchNestedScroll(i, i1, i2, i3, ints, i4)
}

override fun dispatchNestedPreScroll(i: Int, i1: Int, ints: IntArray?, ints1: IntArray?, i2: Int): Boolean {
    return childHelper.dispatchNestedPreScroll(i, i1, ints, ints1, i2)
}

override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float): Boolean {
    return childHelper.dispatchNestedPreFling(velocityX, velocityY)
}

override fun dispatchNestedFling(velocityX: Float, velocityY: Float, consumed: Boolean): Boolean {
    return childHelper.dispatchNestedFling(velocityX, velocityY, consumed)
}

override fun onStartNestedScroll(child: View, target: View, axes: Int, type: Int): Boolean {
    if (type == TYPE_TOUCH) {
        stopNestedScroll(TYPE_NON_TOUCH)
        ViewCompat.stopNestedScroll(child, TYPE_NON_TOUCH)
    }
    val handle = super.onStartNestedScroll(child, target, axes, type)
    return startNestedScroll(axes, type) || handle
}

override fun onStopNestedScroll(target: View, type: Int) {
    super.onStopNestedScroll(target, type)
    stopNestedScroll(type)
}

override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) {
    val thisConsume = IntArray(2)
    dispatchNestedPreScroll(dx, dy, thisConsume, null, type)
    consumed[0] += thisConsume[0]
    consumed[1] += thisConsume[1]
    thisConsume[0] = 0
    thisConsume[1] = 0
    super.onNestedPreScroll(target, dx - consumed[0], dy - consumed[1], thisConsume, type)
    consumed[0] += thisConsume[0]
    consumed[1] += thisConsume[1]

}

override fun onNestedScroll(
    target: View,
    dxConsumed: Int,
    dyConsumed: Int,
    dxUnconsumed: Int,
    dyUnconsumed: Int,
    type: Int
) {

    val offsetInWindow = IntArray(2)
    target.getLocationInWindow(offsetInWindow)
    val startX = offsetInWindow[0]
    val startY = offsetInWindow[1]
    super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type)
    target.getLocationInWindow(offsetInWindow)
    offsetInWindow[0] -= startX
    offsetInWindow[1] -= startY
    dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed + offsetInWindow[0]
        , dyUnconsumed + offsetInWindow[1], null, type)
}

override fun onNestedPreFling(target: View, velocityX: Float, velocityY: Float): Boolean {
    val handled = super.onNestedPreFling(target, velocityX, velocityY)
    return dispatchNestedPreFling(velocityX, velocityY) || handled
}

override fun onNestedFling(target: View, velocityX: Float, velocityY: Float, consumed: Boolean): Boolean {
    val handled = super.onNestedFling(target, velocityX, velocityY, consumed)
    return dispatchNestedFling(velocityX, velocityY, consumed) || handled
}

}