CoordinatorLayout inside another CoordinatorLayout

coordinatorlayout nestedscrollview
coordinatorlayout tutorial
coordinatorlayout recyclerview scroll
android coordinatorlayout behavior
coordinator layout with recyclerview
collapsing toolbar with recyclerview android example
android coordinatorlayout scrollview
appbar_scrolling_view_behavior

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

I have a coordinatorLayout with ViewPager that contains different Fragment such that on Scroll will hide the tabLayout

I have another coordinatorLayout that has a viewPager. This fragment is inflated in ViewPager of parent fragment(parent Coordinator layout).

The problem is onScrolling the child fragment in childViewpager only reflects in coordinator layout of child fragment and not in the Parent coordinator layout that I need to do to hide the tablayout.

the structure is:

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

p -> parent;

c -> child; cc -> child to child

How to make on scrolling recycler view will affect both coordinator layout so that the toolbar tablayout(p) will be get hides.


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

Handling Scrolls with CoordinatorLayout, So long as the CoordinatorLayout is used as the primary layout, this animation Add an app:layout_behavior to a RecyclerView or any other View capable of nested toolbar effect, we must wrap the Toolbar inside CollapsingToolbarLayout: CoordinatorLayout is a super-powered FrameLayout. CoordinatorLayout is intended for two primary use cases: As a top-level application decor or chrome layout. As a container for a specific interaction with one or more child views.


Here's a simple implementation of a nested coordinator layout.

/**
 * 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);
    }
}

Using CoordinatorLayout in Android apps, How to use CoordinatorLayout in different ways to simplify Android (or any other View really) that is apparently attached to another widget,  CoordinatorLayout is intended for two to coordinate the animations and transitions of the views within it. a single parent and those views can also interact with one another.


I made this a library, see it on GitHub.

You just use <NestedScrollCoordinatorLayout> in your layout.

Nested scrolling with CoordinatorLayout on Android , This explains why AppBarLayout is changing its location when placed inside a CoordinatorLayout . Now the question is how CoordinatorLayout  3. CollapsingToolbar and Appbar. Another excellent use of the CoordinatorLayout is with the CollapsingToolbar and Appbar. The CollapsingToolbar is another of the amazing features of the Android Support Design Library. For this activity, we are going to build a layout with a FAB that is anchored to the Appbar.


Hopefully, this will help others. The idea I implemented during preScroll calculates how much the parent is able to consume, if it is already 0, then call super.onNestedPreScroll.

Here's the code:

import android.content.Context;
import android.support.annotation.Nullable;
import android.support.design.widget.CoordinatorLayout;
import android.support.v4.view.NestedScrollingChild2;
import android.support.v4.view.NestedScrollingChildHelper;
import android.util.AttributeSet;
import android.view.View;

public class NestedScrollCoordinatorLayout extends CoordinatorLayout implements NestedScrollingChild2 {

  private NestedScrollingChildHelper mChildHelper;

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

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

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

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

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

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

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

  @Override
  public boolean onStartNestedScroll(View child, View target, int axes, int type) {
    boolean superResult = super.onStartNestedScroll(child, target, axes, type);
    return startNestedScroll(axes, type) || superResult;
  }

  @Override
  public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
    boolean superResult = super.onStartNestedScroll(child, target, nestedScrollAxes);
    return startNestedScroll(nestedScrollAxes) || superResult;
  }

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

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

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

  @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 void onStopNestedScroll(View target, int type) {
    super.onStopNestedScroll(target, type);
    stopNestedScroll(type);
  }

  @Override
  public void onStopNestedScroll(View target) {
    super.onStopNestedScroll(target);
    stopNestedScroll();
  }

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

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

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

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

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

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

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

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

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

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

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

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

Intercepting everything with CoordinatorLayout Behaviors, By attaching a Behavior to a direct child of CoordinatorLayout , you'll be As a bonus though, you can declare any other custom attributes you  Home » Android » android – Coordinatorlayout adjustresize not working android – Coordinatorlayout adjustresize not working Posted by: admin May 10, 2020 Leave a comment


I have wrote one ChildCoordinatorLayout in my repo nestrefresh. In this repo, I wrap one AppBarLayout with ChildCoordinatorLayout and also add pull refresh for the ChildCoordinatorLayout with pull refresh behavior. And dyUnConsumed give parent firstly then to the child. This is the code:

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
    }

}

Using Coordinator Layout in Android, Another example of Coordinator Layout can be seen below: Here, we can see that one view is going over the other and the transaction or  In this case, a CoordinatorLayout.Behavior<FloatingAcctionButton>, which depending on some factors including the scroll, shows the FAB or not, interesting, right?. ###SwipeDismissBehavior Keep diving into the code, if you look inside the widget package of the design support library , we’ll find a public class called: SwipeDismissBehavior .


Build Fun UI With CoordinatorLayout, So you won't see the basic usage of the CoordinatorLayout which it is a single parent and Duration: 0:07 Posted: Mar 22, 2017 By specifying Behaviors for child views of a CoordinatorLayout you can provide many different interactions within a single parent and those views can also interact with one another. View classes can specify a default behavior when used as a child of a CoordinatorLayout using the CoordinatorLayout.DefaultBehavior annotation.


CoordinatorLayout Basic, app:layout_anchor: This attribute can be set on children of the CoordinatorLayout to attach them to another view. The value would be the id of an anchor view that  CoordinatorLayout in Action CoordinatorLayout is a super-powered FrameLayout. CoordinatorLayout is a general-purpose container that allows for coordinating interactive behaviorsbetween its children. CoordinatorLayout manages interactions between its children, and as such needs to contain all the View s that interact with each other.


Design Support Library (III): Coordinator Layout, That´s what this new layout is all about: based on a set of rules defined in Behaviors, we can define how views inside the Coordinator Layout relate each other  By specifying Behaviors for child views of a CoordinatorLayout you can provide many different interactions within a single parent and those views can also interact with one another. As the figure, the CoordinatorLayout opens a backdoor for us to coordinate its child View with the ways of consuming the additional dx or dy .