Home | History | Annotate | Download | only in views
      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 
     17 package com.android.systemui.recents.views;
     18 
     19 import android.content.Context;
     20 import android.graphics.Rect;
     21 import android.util.AttributeSet;
     22 import 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  */
     30 public 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