• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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 android.support.v7.widget;
18 
19 import android.content.Context;
20 import android.graphics.Rect;
21 import android.support.v4.view.ViewCompat;
22 import android.util.AttributeSet;
23 import android.util.DisplayMetrics;
24 import android.util.TypedValue;
25 import android.widget.FrameLayout;
26 
27 import static android.view.View.MeasureSpec.AT_MOST;
28 import static android.view.View.MeasureSpec.EXACTLY;
29 import static android.view.View.MeasureSpec.getMode;
30 
31 /**
32  * @hide
33  */
34 public class ContentFrameLayout extends FrameLayout {
35 
36     public interface OnAttachListener {
onDetachedFromWindow()37         void onDetachedFromWindow();
onAttachedFromWindow()38         void onAttachedFromWindow();
39     }
40 
41     private TypedValue mMinWidthMajor;
42     private TypedValue mMinWidthMinor;
43     private TypedValue mFixedWidthMajor;
44     private TypedValue mFixedWidthMinor;
45     private TypedValue mFixedHeightMajor;
46     private TypedValue mFixedHeightMinor;
47 
48     private final Rect mDecorPadding;
49 
50     private OnAttachListener mAttachListener;
51 
ContentFrameLayout(Context context)52     public ContentFrameLayout(Context context) {
53         this(context, null);
54     }
55 
ContentFrameLayout(Context context, AttributeSet attrs)56     public ContentFrameLayout(Context context, AttributeSet attrs) {
57         this(context, attrs, 0);
58     }
59 
ContentFrameLayout(Context context, AttributeSet attrs, int defStyleAttr)60     public ContentFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
61         super(context, attrs, defStyleAttr);
62         mDecorPadding = new Rect();
63     }
64 
65     /**
66      * @hide
67      */
dispatchFitSystemWindows(Rect insets)68     public void dispatchFitSystemWindows(Rect insets) {
69         fitSystemWindows(insets);
70     }
71 
setAttachListener(OnAttachListener attachListener)72     public void setAttachListener(OnAttachListener attachListener) {
73         mAttachListener = attachListener;
74     }
75 
76     /**
77      * Notify this view of the window decor view's padding. We use these values when working out
78      * our size for the window size attributes.
79      *
80      * @hide
81      */
setDecorPadding(int left, int top, int right, int bottom)82     public void setDecorPadding(int left, int top, int right, int bottom) {
83         mDecorPadding.set(left, top, right, bottom);
84         if (ViewCompat.isLaidOut(this)) {
85             requestLayout();
86         }
87     }
88 
89     @Override
onMeasure(int widthMeasureSpec, int heightMeasureSpec)90     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
91         final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
92         final boolean isPortrait = metrics.widthPixels < metrics.heightPixels;
93 
94         final int widthMode = getMode(widthMeasureSpec);
95         final int heightMode = getMode(heightMeasureSpec);
96 
97         boolean fixedWidth = false;
98         if (widthMode == AT_MOST) {
99             final TypedValue tvw = isPortrait ? mFixedWidthMinor : mFixedWidthMajor;
100             if (tvw != null && tvw.type != TypedValue.TYPE_NULL) {
101                 int w = 0;
102                 if (tvw.type == TypedValue.TYPE_DIMENSION) {
103                     w = (int) tvw.getDimension(metrics);
104                 } else if (tvw.type == TypedValue.TYPE_FRACTION) {
105                     w = (int) tvw.getFraction(metrics.widthPixels, metrics.widthPixels);
106                 }
107                 if (w > 0) {
108                     w -= (mDecorPadding.left + mDecorPadding.right);
109                     final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
110                     widthMeasureSpec = MeasureSpec.makeMeasureSpec(
111                             Math.min(w, widthSize), EXACTLY);
112                     fixedWidth = true;
113                 }
114             }
115         }
116 
117         if (heightMode == AT_MOST) {
118             final TypedValue tvh = isPortrait ? mFixedHeightMajor : mFixedHeightMinor;
119             if (tvh != null && tvh.type != TypedValue.TYPE_NULL) {
120                 int h = 0;
121                 if (tvh.type == TypedValue.TYPE_DIMENSION) {
122                     h = (int) tvh.getDimension(metrics);
123                 } else if (tvh.type == TypedValue.TYPE_FRACTION) {
124                     h = (int) tvh.getFraction(metrics.heightPixels, metrics.heightPixels);
125                 }
126                 if (h > 0) {
127                     h -= (mDecorPadding.top + mDecorPadding.bottom);
128                     final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
129                     heightMeasureSpec = MeasureSpec.makeMeasureSpec(
130                             Math.min(h, heightSize), EXACTLY);
131                 }
132             }
133         }
134 
135         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
136 
137         int width = getMeasuredWidth();
138         boolean measure = false;
139 
140         widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, EXACTLY);
141 
142         if (!fixedWidth && widthMode == AT_MOST) {
143             final TypedValue tv = isPortrait ? mMinWidthMinor : mMinWidthMajor;
144             if (tv != null && tv.type != TypedValue.TYPE_NULL) {
145                 int min = 0;
146                 if (tv.type == TypedValue.TYPE_DIMENSION) {
147                     min = (int) tv.getDimension(metrics);
148                 } else if (tv.type == TypedValue.TYPE_FRACTION) {
149                     min = (int) tv.getFraction(metrics.widthPixels, metrics.widthPixels);
150                 }
151                 if (min > 0) {
152                     min -= (mDecorPadding.left + mDecorPadding.right);
153                 }
154                 if (width < min) {
155                     widthMeasureSpec = MeasureSpec.makeMeasureSpec(min, EXACTLY);
156                     measure = true;
157                 }
158             }
159         }
160 
161         if (measure) {
162             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
163         }
164     }
165 
getMinWidthMajor()166     public TypedValue getMinWidthMajor() {
167         if (mMinWidthMajor == null) mMinWidthMajor = new TypedValue();
168         return mMinWidthMajor;
169     }
170 
getMinWidthMinor()171     public TypedValue getMinWidthMinor() {
172         if (mMinWidthMinor == null) mMinWidthMinor = new TypedValue();
173         return mMinWidthMinor;
174     }
175 
getFixedWidthMajor()176     public TypedValue getFixedWidthMajor() {
177         if (mFixedWidthMajor == null) mFixedWidthMajor = new TypedValue();
178         return mFixedWidthMajor;
179     }
180 
getFixedWidthMinor()181     public TypedValue getFixedWidthMinor() {
182         if (mFixedWidthMinor == null) mFixedWidthMinor = new TypedValue();
183         return mFixedWidthMinor;
184     }
185 
getFixedHeightMajor()186     public TypedValue getFixedHeightMajor() {
187         if (mFixedHeightMajor == null) mFixedHeightMajor = new TypedValue();
188         return mFixedHeightMajor;
189     }
190 
getFixedHeightMinor()191     public TypedValue getFixedHeightMinor() {
192         if (mFixedHeightMinor == null) mFixedHeightMinor = new TypedValue();
193         return mFixedHeightMinor;
194     }
195 
196     @Override
onAttachedToWindow()197     protected void onAttachedToWindow() {
198         super.onAttachedToWindow();
199         if (mAttachListener != null) {
200             mAttachListener.onAttachedFromWindow();
201         }
202     }
203 
204     @Override
onDetachedFromWindow()205     protected void onDetachedFromWindow() {
206         super.onDetachedFromWindow();
207         if (mAttachListener != null) {
208             mAttachListener.onDetachedFromWindow();
209         }
210     }
211 }
212