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 */
14package android.windowanimationjank;
15
16import android.content.Context;
17import android.util.AttributeSet;
18import android.view.View;
19import android.view.ViewGroup;
20
21/**
22 * Custom layout that place all elements in flows with and automatically wraps them.
23 */
24public class FlowLayout extends ViewGroup {
25    private int mLineHeight;
26
27    public FlowLayout(Context context) {
28        super(context);
29    }
30
31    public FlowLayout(Context context, AttributeSet attrs) {
32        super(context, attrs);
33    }
34
35    @Override
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
83    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
84        if (p instanceof LayoutParams) {
85            return true;
86        }
87        return false;
88    }
89
90    @Override
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