1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.systemui.recents.views; 18 19import android.content.Context; 20import android.graphics.Rect; 21import android.util.AttributeSet; 22import android.widget.FrameLayout; 23 24/** 25 * This is an optimized FrameLayout whose layout is completely directed by its parent, and as a 26 * result, does not propagate <code>requestLayout()</code> up the view hierarchy. Instead, it will 27 * relayout its children with the last known layout bounds when a layout is requested from a child 28 * view. 29 */ 30public class FixedSizeFrameLayout extends FrameLayout { 31 32 private final Rect mLayoutBounds = new Rect(); 33 34 public FixedSizeFrameLayout(Context context) { 35 super(context); 36 } 37 38 public FixedSizeFrameLayout(Context context, AttributeSet attrs) { 39 super(context, attrs); 40 } 41 42 public FixedSizeFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) { 43 super(context, attrs, defStyleAttr); 44 } 45 46 public FixedSizeFrameLayout(Context context, AttributeSet attrs, int defStyleAttr, 47 int defStyleRes) { 48 super(context, attrs, defStyleAttr, defStyleRes); 49 } 50 51 @Override 52 protected final void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 53 measureContents(MeasureSpec.getSize(widthMeasureSpec), 54 MeasureSpec.getSize(heightMeasureSpec)); 55 } 56 57 @Override 58 protected final void onLayout(boolean changed, int left, int top, int right, int bottom) { 59 mLayoutBounds.set(left, top, right, bottom); 60 layoutContents(mLayoutBounds, changed); 61 } 62 63 @Override 64 public final void requestLayout() { 65 // The base ViewGroup constructor attempts to call requestLayout() before this class's 66 // members are initialized so we should just propagate in that case 67 if (mLayoutBounds == null || mLayoutBounds.isEmpty()) { 68 super.requestLayout(); 69 } else { 70 // If we are already laid out, then just reuse the same bounds to layout the children 71 // (but not itself) 72 // TODO: Investigate whether we should coalesce these to the next frame if needed 73 measureContents(getMeasuredWidth(), getMeasuredHeight()); 74 layoutContents(mLayoutBounds, false); 75 } 76 } 77 78 /** 79 * Measures the contents of this fixed layout. 80 */ 81 protected void measureContents(int width, int height) { 82 super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), 83 MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST)); 84 } 85 86 /** 87 * Lays out the contents of this fixed layout. 88 */ 89 protected void layoutContents(Rect bounds, boolean changed) { 90 super.onLayout(changed, bounds.left, bounds.top, bounds.right, bounds.bottom); 91 92 int width = getMeasuredWidth(); 93 int height = getMeasuredHeight(); 94 onSizeChanged(width, height, width, height); 95 } 96 97} 98