blob: ac24ca2276a9c43a43d640a462b7846af72ee121 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.support.design.widget;
import android.content.Context;
import android.support.design.widget.CoordinatorLayout.Behavior;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
/**
* The {@link Behavior} for a scrolling view that is positioned vertically below another view.
* See {@link HeaderBehavior}.
*/
abstract class HeaderScrollingViewBehavior extends ViewOffsetBehavior<View> {
public HeaderScrollingViewBehavior() {}
public HeaderScrollingViewBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onMeasureChild(CoordinatorLayout parent, View child,
int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec,
int heightUsed) {
final int childLpHeight = child.getLayoutParams().height;
if (childLpHeight == ViewGroup.LayoutParams.MATCH_PARENT
|| childLpHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
// If the menu's height is set to match_parent/wrap_content then measure it
// with the maximum visible height
final List<View> dependencies = parent.getDependencies(child);
if (dependencies.isEmpty()) {
// If we don't have any dependencies, return false
return false;
}
final View header = findFirstDependency(dependencies);
if (header != null && ViewCompat.isLaidOut(header)) {
if (ViewCompat.getFitsSystemWindows(header)) {
// If the header is fitting system windows then we need to also,
// otherwise we'll get CoL's compatible layout functionality
ViewCompat.setFitsSystemWindows(child, true);
}
int availableHeight = View.MeasureSpec.getSize(parentHeightMeasureSpec);
if (availableHeight == 0) {
// If the measure spec doesn't specify a size, use the current height
availableHeight = parent.getHeight();
}
final int height = availableHeight - header.getMeasuredHeight()
+ getScrollRange(header);
final int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height,
childLpHeight == ViewGroup.LayoutParams.MATCH_PARENT
? View.MeasureSpec.EXACTLY
: View.MeasureSpec.AT_MOST);
// Now measure the scrolling menu with the correct height
parent.onMeasureChild(child, parentWidthMeasureSpec,
widthUsed, heightMeasureSpec, heightUsed);
return true;
}
}
return false;
}
abstract View findFirstDependency(List<View> views);
int getScrollRange(View v) {
return v.getMeasuredHeight();
}
}