Search code examples
androidandroid-constraintlayoutandroid-coordinatorlayout

Is it possible to combine CoordinatorLayout with ConstraintLayout?


In one of my views I have a ConstraintLayout on the bottom of my mainview with three ImageButtons inside of it. I also use a Snackbar to show some informations on the bottom. I want to move the complete ConstraintLayout up if the Snackbar is visible. I tried now different things without any result. In a separate Android-Project i played a little bit around with CoordinatorLayouts and my result so far is, that it is not possible for ConstraintLayouts. Is my assumption right?

This is working

public class CustomBehaviourButton extends CoordinatorLayout.Behavior<Button>{

    public CustomBehaviourButton() {
    }

    public CustomBehaviourButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull Button child, @NonNull View dependency) {
        return dependency instanceof Snackbar.SnackbarLayout;
    }

    @Override
    public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent, @NonNull Button child, @NonNull View dependency) {
        float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
        child.setTranslationY(translationY);
        return true;
    }

    @Override
    public void onDependentViewRemoved(@NonNull CoordinatorLayout parent, @NonNull Button child, @NonNull View dependency) {
        float translationY = Math.min(0, dependency.getTranslationY() + dependency.getHeight());
        child.setTranslationY(translationY);
    }
}

And this is not working

public class CustomBehaviourConstraintLayout extends CoordinatorLayout.Behavior<ConstraintLayout> {

    public CustomBehaviourConstraintLayout() {
    }

    public CustomBehaviourConstraintLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull ConstraintLayout child, @NonNull View dependency) {
        return dependency instanceof Snackbar.SnackbarLayout;
    }

    @Override
    public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent, @NonNull ConstraintLayout child, @NonNull View dependency) {
        float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
        child.setTranslationY(translationY);
        return true;
    }

    @Override
    public void onDependentViewRemoved(@NonNull CoordinatorLayout parent, @NonNull ConstraintLayout child, @NonNull View dependency) {
        float translationY = Math.min(0, dependency.getTranslationY() + dependency.getHeight());
        child.setTranslationY(translationY);
    }
}

Is there by any chance a way for a ConstraintLayout to react if a Snackbar is shown??

Edit:

This is my current Layout

<androidx.coordinatorlayout.widget.CoordinatorLayout>
   <androidx.constraintlayout.widget.ConstraintLayout>
      <!-- different widgets -->
      <androidx.constraintlayout.widget.ConstraintLayout>
         <!-- Some Buttons -->
      </androidx.constraintlayout.widget.ConstraintLayout>
   </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

I want that only the second ConstraintLayout is effected by the behaviour. I get it only for the first ConstraintLayout, but the result is not what I want.


Solution

  • It took a while but I found a solution for my problem and I guess this solution is helpfull for others.

    The trick was to dig deeper into the custom Behaviour-Class. It seems that the outer most ConstraintLayout needs to get the Bahviour. In that case I just referenced my inner most ConstraintLayout in onDependendViewChanged to only modify this part of my layout.

    @Override
        public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent, @NonNull ConstraintLayout child, @NonNull View dependency) {
            ConstraintLayout mainControlsPanel = child.findViewById(R.id.mainControlsPanel);
    
            float heightDiff = dependency.getY() - mainControlsPanel.getY();
            float translationY = heightDiff - mainControlsPanel.getHeight() - MARGIN;
    
            mainControlsPanel.setTranslationY(translationY);
    
            return true;
        }