| /* |
| * 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() { |
| super(); |
| } |
| |
| public HeaderScrollingViewBehavior(Context context, AttributeSet attrs) { |
| super(context, attrs); |
| } |
| |
| protected abstract View findFirstDependency(List<View> views); |
| |
| @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; |
| } |
| |
| protected int getScrollRange(View v) { |
| return v.getMeasuredHeight(); |
| } |
| } |