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