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