I am trying to set a layout_behavior
on an element that is a child of the CollapsingToolbarLayout
but the behavior is never called on the iv_header
view. It works perfectly when anchored outside such as with the tv_follow
view.
The documentation doesn't specifically say a layout_behavior
cannot be applied within the AppBarLayout
or CollapsingToolbarLayout
so I'm at a loss for why it isn't working.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="@dimen/full_header_height"
android:focusable="true"
android:focusableInTouchMode="true">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/iv_header"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:contentDescription="@null"
app:layout_behavior="com.package.view.HidingBehavior"
app:layout_collapseMode="parallax"
android:src="@drawable/profile_background"/>
<android.support.v7.widget.Toolbar
android:id="@+id/header_toolbar"
android:layout_height="@dimen/action_bar_height"
android:layout_width="match_parent"
android:background="@drawable/toolbar_dark_gradient_half"
android:gravity="top"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
<TextView
android:id="@+id/tv_follow"
android:textSize="20sp"
android:textColor="@android:color/white"
android:text="@string/follow"
android:drawableLeft="@drawable/comm_follow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_anchor="@id/header"
app:layout_anchorGravity="center"
app:layout_behavior="com.package.view.HidingBehavior"
android:drawablePadding="8dp"
android:gravity="center"
android:visibility="gone"
android:fitsSystemWindows="true"/>
</android.support.design.widget.CoordinatorLayout>
The Behavior was pulled out of the FloatingActionButton code in the design support library.
public class HidingBehavior extends CoordinatorLayout.Behavior<View>{
private Rect tmpRect;
private boolean isAnimatingOut;
private FastOutSlowInInterpolator fastOutSlowInInterpolator = new FastOutSlowInInterpolator();
public HidingBehavior() {
}
public HidingBehavior(Context context, AttributeSet attrs) {
super();
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
return dependency instanceof AppBarLayout;
}
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
if (dependency instanceof AppBarLayout) {
AppBarLayout appBarLayout = (AppBarLayout) dependency;
if (this.tmpRect == null) {
this.tmpRect = new Rect();
}
Rect rect = this.tmpRect;
ViewGroupUtils.getDescendantRect(parent, dependency, rect);
if (rect.bottom <= getMinimumHeightForContext(appBarLayout)) {
if(!this.isAnimatingOut && child.getVisibility() == View.VISIBLE) {
this.animateOut(child);
}
} else if(child.getVisibility() != View.VISIBLE) {
this.animateIn(child);
}
}
return false;
}
private int getMinimumHeightForContext(AppBarLayout appBarLayout) {
int minHeight = ViewCompat.getMinimumHeight(appBarLayout);
if(minHeight != 0) {
return minHeight*2;
} else {
int childCount = appBarLayout.getChildCount();
return childCount >= 1?ViewCompat.getMinimumHeight(appBarLayout.getChildAt(childCount - 1))*2:0;
}
}
private void animateIn(View view) {
view.setVisibility(View.VISIBLE);
ViewCompat.animate(view)
.scaleX(1.0F)
.scaleY(1.0F)
.alpha(1.0F)
.setInterpolator(fastOutSlowInInterpolator)
.withLayer()
.setListener((ViewPropertyAnimatorListener)null).start();
}
private void animateOut(final View view) {
ViewCompat.animate(view)
.scaleX(0.0F)
.scaleY(0.0F)
.alpha(0.0F)
.setInterpolator(fastOutSlowInInterpolator)
.withLayer()
.setListener(new ViewPropertyAnimatorListener() {
public void onAnimationStart(View view) {
HidingBehavior.this.isAnimatingOut = true;
}
public void onAnimationCancel(View view) {
HidingBehavior.this.isAnimatingOut = false;
}
public void onAnimationEnd(View view) {
HidingBehavior.this.isAnimatingOut = false;
view.setVisibility(View.GONE);
}
}).start();
}
}
If I am not mistaken, this line is unnecessary where you currently have it...
app:layout_behavior="com.package.view.HidingBehavior"
The layout_behavior
should be applied to the sibling of the of the AppBarLayout
and not to a (nested) child. This is because it tells the siblings, inside the CoordinatorLayout
, how they need to coordinate their behaviors in response to what they're doing.
In other words, where you have it, it is not coordinating any behavior with any other view.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With