1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.printspooler.widget; 18 19 import android.content.Context; 20 import android.content.res.TypedArray; 21 import android.util.AttributeSet; 22 import android.view.View; 23 import android.view.ViewGroup; 24 import com.android.printspooler.R; 25 26 /** 27 * This class is a layout manager for the print options. The options are 28 * arranged in a configurable number of columns and enough rows to fit all 29 * the options given the column count. 30 */ 31 @SuppressWarnings("unused") 32 public final class PrintOptionsLayout extends ViewGroup { 33 34 private int mColumnCount; 35 PrintOptionsLayout(Context context, AttributeSet attrs)36 public PrintOptionsLayout(Context context, AttributeSet attrs) { 37 super(context, attrs); 38 39 TypedArray typedArray = context.obtainStyledAttributes(attrs, 40 R.styleable.PrintOptionsLayout); 41 mColumnCount = typedArray.getInteger(R.styleable.PrintOptionsLayout_columnCount, 0); 42 typedArray.recycle(); 43 } 44 setColumnCount(int columnCount)45 public void setColumnCount(int columnCount) { 46 if (mColumnCount != columnCount) { 47 mColumnCount = columnCount; 48 requestLayout(); 49 } 50 } 51 52 @Override onMeasure(int widthMeasureSpec, int heightMeasureSpec)53 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 54 final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 55 final int widthSize = MeasureSpec.getSize(widthMeasureSpec); 56 57 final int columnWidth = (widthSize != 0) 58 ? (widthSize - mPaddingLeft - mPaddingRight) / mColumnCount : 0; 59 60 int width = 0; 61 int height = 0; 62 int childState = 0; 63 64 final int childCount = getChildCount(); 65 final int rowCount = childCount / mColumnCount + childCount % mColumnCount; 66 67 for (int row = 0; row < rowCount; row++) { 68 int rowWidth = 0; 69 int rowHeight = 0; 70 71 for (int col = 0; col < mColumnCount; col++) { 72 final int childIndex = row * mColumnCount + col; 73 74 if (childIndex >= childCount) { 75 break; 76 } 77 78 View child = getChildAt(childIndex); 79 80 if (child.getVisibility() == GONE) { 81 continue; 82 } 83 84 MarginLayoutParams childParams = (MarginLayoutParams) child.getLayoutParams(); 85 86 final int childWidthMeasureSpec; 87 if (columnWidth > 0) { 88 childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( 89 columnWidth - childParams.getMarginStart() - childParams.getMarginEnd(), 90 MeasureSpec.EXACTLY); 91 } else { 92 childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 93 getPaddingStart() + getPaddingEnd() + width, childParams.width); 94 } 95 96 final int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, 97 getPaddingTop() + getPaddingBottom() + height, childParams.height); 98 99 child.measure(childWidthMeasureSpec, childHeightMeasureSpec); 100 101 childState = combineMeasuredStates(childState, child.getMeasuredState()); 102 103 rowWidth += child.getMeasuredWidth() + childParams.getMarginStart() 104 + childParams.getMarginEnd(); 105 106 rowHeight = Math.max(rowHeight, child.getMeasuredHeight() + childParams.topMargin 107 + childParams.bottomMargin); 108 } 109 110 width = Math.max(width, rowWidth); 111 height += rowHeight; 112 } 113 114 width += getPaddingStart() + getPaddingEnd(); 115 width = Math.max(width, getMinimumWidth()); 116 117 height += getPaddingTop() + getPaddingBottom(); 118 height = Math.max(height, getMinimumHeight()); 119 120 setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, childState), 121 resolveSizeAndState(height, heightMeasureSpec, 122 childState << MEASURED_HEIGHT_STATE_SHIFT)); 123 } 124 125 @Override onLayout(boolean changed, int l, int t, int r, int b)126 protected void onLayout(boolean changed, int l, int t, int r, int b) { 127 final int childCount = getChildCount(); 128 final int rowCount = childCount / mColumnCount + childCount % mColumnCount; 129 130 int cellStart = getPaddingStart(); 131 int cellTop = getPaddingTop(); 132 133 for (int row = 0; row < rowCount; row++) { 134 int rowHeight = 0; 135 136 for (int col = 0; col < mColumnCount; col++) { 137 final int childIndex = row * mColumnCount + col; 138 139 if (childIndex >= childCount) { 140 break; 141 } 142 143 View child = getChildAt(childIndex); 144 145 if (child.getVisibility() == GONE) { 146 continue; 147 } 148 149 MarginLayoutParams childParams = (MarginLayoutParams) child.getLayoutParams(); 150 151 final int childLeft = cellStart + childParams.getMarginStart(); 152 final int childTop = cellTop + childParams.topMargin; 153 final int childRight = childLeft + child.getMeasuredWidth(); 154 final int childBottom = childTop + child.getMeasuredHeight(); 155 156 child.layout(childLeft, childTop, childRight, childBottom); 157 158 cellStart = childRight + childParams.getMarginEnd(); 159 160 rowHeight = Math.max(rowHeight, child.getMeasuredHeight() 161 + childParams.topMargin + childParams.bottomMargin); 162 } 163 164 cellStart = getPaddingStart(); 165 cellTop += rowHeight; 166 } 167 } 168 169 @Override generateLayoutParams(AttributeSet attrs)170 public LayoutParams generateLayoutParams(AttributeSet attrs) { 171 return new ViewGroup.MarginLayoutParams(getContext(), attrs); 172 } 173 } 174