1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 package android.windowanimationjank;
15 
16 import android.content.Context;
17 import android.util.AttributeSet;
18 import android.view.View;
19 import android.view.ViewGroup;
20 
21 /**
22  * Custom layout that place all elements in flows with and automatically wraps them.
23  */
24 public class FlowLayout extends ViewGroup {
25     private int mLineHeight;
26 
FlowLayout(Context context)27     public FlowLayout(Context context) {
28         super(context);
29     }
30 
FlowLayout(Context context, AttributeSet attrs)31     public FlowLayout(Context context, AttributeSet attrs) {
32         super(context, attrs);
33     }
34 
35     @Override
onMeasure(int widthMeasureSpec, int heightMeasureSpec)36     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
37         final int width =
38                 MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() -getPaddingRight();
39         int height =
40                 MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
41         final int count = getChildCount();
42 
43         int x = getPaddingLeft();
44         int y = getPaddingTop();
45         int lineHeight = 0;
46 
47         int childHeightMeasureSpec;
48         if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
49             childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
50         } else {
51             childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
52         }
53 
54         for (int i = 0; i < count; i++) {
55             final View child = getChildAt(i);
56             if (child.getVisibility() != GONE) {
57                 child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
58                         childHeightMeasureSpec);
59                 final int childWidth = child.getMeasuredWidth();
60                 lineHeight = Math.max(lineHeight, child.getMeasuredHeight());
61 
62                 if (x + childWidth > width) {
63                     x = getPaddingLeft();
64                     y += lineHeight;
65                 }
66 
67                 x += childWidth;
68             }
69         }
70         mLineHeight = lineHeight;
71 
72         if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED) {
73             height = y + lineHeight;
74         } else if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
75             if (y + lineHeight < height) {
76                 height = y + lineHeight;
77             }
78         }
79         setMeasuredDimension(width, height);
80     }
81 
82     @Override
checkLayoutParams(ViewGroup.LayoutParams p)83     protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
84         if (p instanceof LayoutParams) {
85             return true;
86         }
87         return false;
88     }
89 
90     @Override
onLayout(boolean changed, int l, int t, int r, int b)91     protected void onLayout(boolean changed, int l, int t, int r, int b) {
92         final int count = getChildCount();
93         final int width = r - l;
94         int x = getPaddingLeft();
95         int y = getPaddingTop();
96 
97         for (int i = 0; i < count; i++) {
98             final View child = getChildAt(i);
99             if (child.getVisibility() != GONE) {
100                 final int childWidth = child.getMeasuredWidth();
101                 final int childHeight = child.getMeasuredHeight();
102                 if (x + childWidth > width) {
103                     x = getPaddingLeft();
104                     y += mLineHeight;
105                 }
106                 child.layout(x, y, x + childWidth, y + childHeight);
107                 x += childWidth;
108             }
109         }
110     }
111 }
112