CoordinatorLayout inside another CoordinatorLayout

后端 未结 8 1834
梦如初夏
梦如初夏 2020-12-02 11:41

CorodinatorLayout inside another CoordinatorLayout such that scrolling the child-view should also scroll the Parent CoordinatorLayout.

相关标签:
8条回答
  • 2020-12-02 12:05

    Kotlin Version of NestedCoordinator Layout to use with multiple point scrollFlags for NestedCoordinatorLayouts based on @fabian answer.

    The beHavior you will see is someThing like this:

    And The NestedCoordinatorLayout Implementation:

    
    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)
        }
    }
    
    

    And your XML file Implementation is like:

    
    <?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>
    
    

    And This is a Visual View of implemented layout hierarchy:

    This Video can give you a better view of how Android Views Hierarchy works actualy.

    0 讨论(0)
  • 2020-12-02 12:08

    I know it's an old question. But I searched a long time to include an CoordinatorLayout in a fragment, which is in another CoordinatorLayout.

    I modified the answer of dev.bmax a little bit to call both coordinator layouts and call the attached behaviors of both layouts.

    So here is my solution.

    @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);
        }
    }
    
    0 讨论(0)
提交回复
热议问题