14f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel/*
24f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel * Copyright (C) 2015 The Android Open Source Project
34f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel *
44f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
54f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel * in compliance with the License. You may obtain a copy of the License at
64f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel *
74f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel * http://www.apache.org/licenses/LICENSE-2.0
84f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel *
94f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel * Unless required by applicable law or agreed to in writing, software distributed under the License
104f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
114f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel * or implied. See the License for the specific language governing permissions and limitations under
124f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel * the License.
134f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel */
144f26c041ad0429710d135d8e179eec8f44077ebeYury Khmelpackage android.windowanimationjank;
154f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel
164f26c041ad0429710d135d8e179eec8f44077ebeYury Khmelimport android.content.Context;
174f26c041ad0429710d135d8e179eec8f44077ebeYury Khmelimport android.util.AttributeSet;
184f26c041ad0429710d135d8e179eec8f44077ebeYury Khmelimport android.view.View;
194f26c041ad0429710d135d8e179eec8f44077ebeYury Khmelimport android.view.ViewGroup;
204f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel
214f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel/**
224f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel * Custom layout that place all elements in flows with and automatically wraps them.
234f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel */
244f26c041ad0429710d135d8e179eec8f44077ebeYury Khmelpublic class FlowLayout extends ViewGroup {
254f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel    private int mLineHeight;
264f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel
274f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel    public FlowLayout(Context context) {
284f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        super(context);
294f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel    }
304f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel
314f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel    public FlowLayout(Context context, AttributeSet attrs) {
324f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        super(context, attrs);
334f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel    }
344f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel
354f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel    @Override
364f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
374f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        final int width =
384f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() -getPaddingRight();
394f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        int height =
404f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
414f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        final int count = getChildCount();
424f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel
434f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        int x = getPaddingLeft();
444f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        int y = getPaddingTop();
454f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        int lineHeight = 0;
464f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel
474f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        int childHeightMeasureSpec;
484f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
494f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
504f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        } else {
514f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
524f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        }
534f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel
544f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        for (int i = 0; i < count; i++) {
554f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel            final View child = getChildAt(i);
564f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel            if (child.getVisibility() != GONE) {
574f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
584f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                        childHeightMeasureSpec);
594f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                final int childWidth = child.getMeasuredWidth();
604f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                lineHeight = Math.max(lineHeight, child.getMeasuredHeight());
614f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel
624f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                if (x + childWidth > width) {
634f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                    x = getPaddingLeft();
644f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                    y += lineHeight;
654f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                }
664f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel
674f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                x += childWidth;
684f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel            }
694f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        }
704f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        mLineHeight = lineHeight;
714f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel
724f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED) {
734f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel            height = y + lineHeight;
744f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        } else if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
754f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel            if (y + lineHeight < height) {
764f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                height = y + lineHeight;
774f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel            }
784f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        }
794f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        setMeasuredDimension(width, height);
804f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel    }
814f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel
824f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel    @Override
834f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
844f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        if (p instanceof LayoutParams) {
854f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel            return true;
864f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        }
874f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        return false;
884f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel    }
894f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel
904f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel    @Override
914f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel    protected void onLayout(boolean changed, int l, int t, int r, int b) {
924f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        final int count = getChildCount();
934f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        final int width = r - l;
944f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        int x = getPaddingLeft();
954f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        int y = getPaddingTop();
964f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel
974f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        for (int i = 0; i < count; i++) {
984f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel            final View child = getChildAt(i);
994f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel            if (child.getVisibility() != GONE) {
1004f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                final int childWidth = child.getMeasuredWidth();
1014f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                final int childHeight = child.getMeasuredHeight();
1024f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                if (x + childWidth > width) {
1034f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                    x = getPaddingLeft();
1044f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                    y += mLineHeight;
1054f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                }
1064f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                child.layout(x, y, x + childWidth, y + childHeight);
1074f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel                x += childWidth;
1084f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel            }
1094f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel        }
1104f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel    }
1114f26c041ad0429710d135d8e179eec8f44077ebeYury Khmel}
112